0

How to configure the simplest useful default-deny rule set for mod_security?

I want to configure mod_security to allow only very specific queries to single directory:

In short: I use Apache as a reverse proxy for directory /web_app/, in this directory will be a single php file named get.php. I want to pass to this script only queries that match the following regular expression:

get\.php\?ver=1&id=[a-f\d]{16,16}&v=[-.a-z\d\ ]{1,20}

In other words, queries with three fields only: id, ver and v. Where first is a digit 1, the second a 16 digit hexadecimal and the third is a string at most 20 characters long with letters, numbers, dots, hyphens and space. It has to deny or remove from queries anything but POST and GET values, that is: file uploads, cookies, all non-essential headers, values other than the 3 specified, etc...

I don't want to change the way any other directories work, just /web_app/. Filtering out wrong UTF or URL escaping/encoding is not a problem, so enabling mod_security shouldn't be a problem in itself.

Hubert Kario
  • 6,351
  • 6
  • 33
  • 65
  • 1
    Why? This is the job of your script. It ignores all other variables and it must check the content. Don't delegate variable checking to an external module. – mailq Aug 21 '11 at 14:05
  • @mailq: It's a reverse proxy, I provided PHP as an example, I'll be using it also with .NET, Java and Ruby. Besides, that's *exactly* what web application firewalls are for -- to double check that the application won't accept values it shouldn't. – Hubert Kario Aug 21 '11 at 14:11
  • 3
    @Hubert a web application firewall is there to protect you against attacks based on heuristics, not to do the work if the developers of the webapps – Thomas Berger Aug 21 '11 at 14:53
  • @Thomas: Are you suggesting that a "default deny" firewall won't be *more* effective? I know that this kind of firewall will be harder to configure for more complex applications, but then, I'll have to do it **once**, not constantly update the rules when new attack vectors come to life. Or do you configure your network firewall to drop only packets arriving on port 137, 138 and 445? Enumerating badness doesn't work anymore: http://www.ranum.com/security/computer_security/editorials/dumb/ – Hubert Kario Aug 21 '11 at 16:31
  • @Thomas: Not to mention situations where I just don't trust developers to write perfect code or can't modify the application, we all make mistakes. – Hubert Kario Aug 21 '11 at 16:35
  • 1
    @Hubert i don't see what you want to tell me. For mod_security there are bulk of rulesets for the most common issues. But if you KNOW a that your application has a security problem, its common that there are even more problems and you should check and fix the app. If you could not because it's closed source, talk to the vendor, if your developers have no clue, fire them or give them some education... I didn't talked about a "default deny" firewall anywhere, did i? – Thomas Berger Aug 21 '11 at 16:53
  • @Thomas: If you have access to developers that don't make mistakes I can only envy you, though I doubt that to be true. I don't know if the application has problems or does not. Simple application may well be bugfree, at the same time there can still be bugs in web servers, frameworks and dozens of other problems. All those heuristics are nothing else but "default allow" rule sets bundled together with simple counters that deny access after a threshold have been met. It won't work for a real attacker that has access to multiple computers or proxies. – Hubert Kario Aug 21 '11 at 17:30
  • @Hubert ok, in this case, would there be any problem with `positiv allow` rulesets? If you know how you application urls may look like? Or do you realy want to exclude specific cases? And every body makes mistakes, so there must be at leas four eyes on the code, and a QA to avoid any mistake. – Thomas Berger Aug 21 '11 at 17:34
  • @Thomas: Yes, I know what the HTML forms that are going to be submitted look like, they will be using both POST and GET, simple text and numeric fields. When I know how to make the submitted example work I'm 99% sure I'll know how to make the rest work. There are still comments to answers... There are already 4 eyes on the code and independent QA to that. But then this code will be *highly* critical so a 3rd tier of security in form of WAF really isn't an overkill. – Hubert Kario Aug 21 '11 at 18:15

2 Answers2

1

For filtering the argumetns, there is a much simpler way then using regular expressions on the whole uri:

<Location /web_app>
  SecFilterSelective ARG_NAMES "!^(id|ver|v)$"
  SecFilterSelective ARG_ver   "!^1$"
  SecFilterSelective ARG_id    "!^[a-f\d]{16,16}"
  SecFilterSelective ARG_v     "!^[-\.a-z\d\ ]{1,20}"

  # Here the same for the request type
  SecFilterSelective REQUEST_METHOD "!^(GET|HEAD|POST)$"
</Location>

Will match on any argument NOT in the list only under /web_app.

You could find good examples in the mod_security documentation: http://www.modsecurity.org/documentation/modsecurity-apache/1.9.3/html-multipage/09-examples.html

All othere parameters could be found there also.

Thomas Berger
  • 1,700
  • 12
  • 22
  • This lets through TRACE and OPTIONS request methods... Won't it also let through any Content-Type or Cookies? – Hubert Kario Aug 21 '11 at 19:08
  • 1
    Should i write you up the whole ruleset here? Ok, you could pay the usual price for security consulting. Go to the docs, you could do all the other rules here too. – Thomas Berger Aug 21 '11 at 19:12
  • The solution you provided still doesn't fulfill my rather straight-forward and simple requirements. If not for POST I could put it in a single regular expression for data and another for allowed headers! I couldn't find a way to reverse the way the mod_security rules work (let only specific arguments, headers and values) that's why I'm asking at serverfault. So yes, please write a full ruleset that I wrote in 4 lines of English, or a way to allow only specific headers the way you showed how to limit arguments. – Hubert Kario Aug 21 '11 at 19:30
  • added `HEAD` because you should allow that, your you'll break any caching functions on the remote ends. – Thomas Berger Aug 21 '11 at 19:37
  • You're right, it won't hurt. – Hubert Kario Aug 21 '11 at 20:31
1

I suppose you need something like this:

<LocationMatch "^/web_app/">
        SecRule REQUEST_URI "!(:?get\.php\?ver=1&id=([a-f\d]){16,16}&v=([-.a-z\d\ ]){1,20})" "id:123,phase:2, deny, status:406"
</LocationMatch>

For the REQUEST_METHOD you could add one additional rule to block if REQUEST_METHOD doesn't match the method you want/allow.

gryzli
  • 81
  • 6