Search code examples
mod-securitymod-security2

mod_security(2.x): How to match on an undefined mod-sec variable?


Note: Question has been updated:

What I am really trying to solve is:

Two types of requests: A and B.

B shall only be allowed if A has been called within the last 5 minutes (from the same ip-address).

My idea to trying so solve this is by having one SecRule, for A-requests, setting a mod_sec-variable with an expire timeout, to say the other type of request will be ok.

For B-requests I want to check if this mod_sec-variable is set or not. If it is not set I want to deny the request.

My problem with this is that I can not make the second SecRule match when the variable is not yet set or has expired.

Original question that is more of a description how I tried to make the second match

How do I make a mod_security(2.x) SecRule match on a (yet) undefined variable in Apache config?

I.e. I need the SecRule to be fulfilled if the variable is not yet defined. Some things I tested is matching with @eq 0 as anything else should be converted into a 0 but that did not work. I also tries using ! as a not operator inside the operator field of SecRule but to no use (or maybe incorrect use?). And also even tried using the @unconditionalMatch but it still does not match.

SecAction id:'400000',phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR}
... in a <location ...> ...
  SecRule REQUEST_METHOD "^POST$" "id:'400002',t:none,nolog,deny,status:401,chain"                                                      
  SecRule ip:my_var_name "@unconditionalMatch"  
...

I tested replacing my (yet) undefined variable with some defined value like REQUEST_METHOD. Then it matches so it is just the usage of the variable that makes it fail. Note: I am adding this just as an example of my tests:

SecAction id:'400000',phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR}
... in a <location ...> ...
  SecRule REQUEST_METHOD "^POST$" "id:'400002',t:none,nolog,deny,status:401,chain"                                                      
  SecRule REQUEST_METHOD "@unconditionalMatch"  
...

so it seems that just bu using an (yet) undefined variable it fails to fulfill.

I was searching https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-%28v2.x%29 for ways to check for undefined variables but could not find anything useful.


Solution

  • Unfortunately the mentioned documentation above doesn't describe the & "operator" in case of SecRule's variables. This character has a special meanings:

    • if the variable is a collection (eg. ARGS), then using of & gives back the length of collection. Eg. &ARGS gives you how many arguments are there
    • if the variable is a string (eg. REQUEST_URI) then it gives the length of it's value. You can use it for collection members, eg. &REQUEST_HEADERS:Host

    You can use this form against the operator @eq with a numeric argument, eg. @eq 0.

    So, based on your clarification, I think you can use something like this:

    SecRule REQUEST_METHOD "^POST$" \
        "id:400002,\
        t:none,\
        nolog,\
        deny,\
        status:401,\
        chain"                                                      
        SecRule &IP:my_var_name "@eq 0"
    

    Here you can find some examples.

    Note that the mentioned @unconditionalMatch does "nothing", it returns always true - it's equivalent as you use SecAction instead of SecRule. See the documentation