ModSecurity Help Needed (URLencoded requests)

PCZero

Well-Known Member
Dec 13, 2003
695
85
178
Earth
My objective is to black list any IP that makes a urencoded request on my server.


Example:

If someone tries to fetch this uRL
Code:
/http://www.mysite.com/cgi-bin/php.cgi?%2D%64+%61%6C%6C%6F%77%5F%75%72%6C%5F%69%6E%63%6C%75%64%65%3D%6F%6E+%2D%64+%73%61%66%65%5F%6D%6F%64%65%3D%6F%66%66+%2D%64+%73%75%68%6F%73%69%6E%2E%73%69%6D%75%6C%61%74%69%6F%6E%3D%6F%6E+%2D%64+%64%69%73%61%62%6C%65%5F%66%75%6E%63%74%69%6F
I want them immediately and permanently blocked form the server. It was suggested to me that ModSecurity would be the tool to use but my level of knowledge of this is very weak.

I also run CSF.

Any suggestions would be appreciated.
 

quizknows

Well-Known Member
Oct 20, 2009
1,008
87
78
cPanel Access Level
DataCenter Provider
You don't want to blacklist just any urlencoded request (I hope that's not your goal).

Anyway, this particular request is trying to exploit something that requires PHP with a CGI handler; cPanel/WHM's implementation of PHP is not vulnerable to this, even with a CGI handler. However for the sake of education I'll answer your question anyway :)

Modsecurity has a nice feature called "transformations." These transform the request before matching it to a rule. These can be things like converting to lowercase, url encoding/decoding, base64, etc. Your example URLdecodes to:

Code:
http://www.mysite.com/cgi-bin/php.cgi?-d allow_url_include=on -d safe_mode=off -d suhosin.simulation=on -d disable_functio
Quite frankly I'd think it would be safe to block any request with "safe_mode=off" in the REQUEST_URI or QUERY_STRING (request_uri is everything after .com, and query_string is everything after the ? ). A legit user should never be sending a request to yoursite.com/some.php?safe_mode=off

So to block this exact request, I'd make this rule in modsec2.user.conf :
Code:
SecRule QUERY_STRING "safe_mode=off" "deny,id:1000847,t:urldecode"
I have tested and verified that this rule works.

[Fri Nov 29 21:47:02.386051 2013] [:error] [pid 17541] [client MY IP ADDRESS] ModSecurity: Access denied with code 406 (phase 2). Pattern match "safe_mode=off" at QUERY_STRING. [file "/usr/local/apache/conf/modsec2/custom.conf"] [line "57"] [id "1000847"] [hostname "www.mysite.com"] [uri "/cgi-bin/php.cgi"] [unique_id "UplRpkMrAkQAAESFrQwAAAAJ"]

I sent the request to my server urlencoded just like your example, and ModSecurity did the urldecode transformation (t:urldecode) then matched safe_mode=off in the query string, and denied the request.

As far as blocking the offending IP, CSF's LF_MODSEC will block repeat offenders. Normally it takes 5 modsecurity errors to be blocked unless you've changed the default config, and I think that's a fair number. Blocking an IP for just one modsec failure will lead to headaches. Just ensure LF_MODSEC is configured in your csf.conf
 
Last edited:

PCZero

Well-Known Member
Dec 13, 2003
695
85
178
Earth
Actually that is EXACTLY my goal. I have been running servers for over a decade and NEVER has there been ANY legitimate request that was URL Encoded. There are 100% all hack attempts. :)

Appreciate the info. I know most of that as far as the construction of a request, I just am not knowledgeable about modsec in particular. That rule combined with a little htacces trickeration let me take care of the issue in a very acceptable manner.
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,913
2,201
363
Appreciate the info. I know most of that as far as the construction of a request, I just am not knowledgeable about modsec in particular. That rule combined with a little htacces trickeration let me take care of the issue in a very acceptable manner.
Would you mind sharing the .htaccess modification you made in-case others viewing this thread would like to implement the same thing?

Thank you.
 

PCZero

Well-Known Member
Dec 13, 2003
695
85
178
Earth
Let's just say that by combining the csf capabilities of blocking an IP on X number of 404s in Y time span, one can accomplish the task by artificially creating sufficient 404s.


1) Add the MODSEC rule.

2) Set up handler for the 406 error created by MODSEC
ErrorDocument 406 /406.php

3) Create the file referenced above. In that file use the onLoad event to call a js function in the <body> tag. The function should make sufficient window.open calls to a non-existant file such that it will trigger the csf 404 block.

4) Create/Edit your robots.txt file to disallow the 406.php file so as to keep google, bing, etc bots form being blocked.



I realize this is a dirty fix and that in actuality you really should only need the MODSEC rule (and a preferably 406 error file) if quizknowns comment about r MODSEC errors trigger a block is accurate. I very much prefer custom error pages as it gives a site a much more professional look and keeps visitors to your site in the actual context of your site rather than presenting them with the generic black text on white background error pages.

These are the error pages I have set up for one of my clients. I set up this combination of error pages for all of my sites.)

Capital City Coins & Currency - Error 400
Capital City Coins & Currency - Error 401
Capital City Coins & Currency - Error 403
Capital City Coins & Currency - Error 404
Capital City Coins & Currency - Error 410
Capital City Coins & Currency - Error 500
 

PCZero

Well-Known Member
Dec 13, 2003
695
85
178
Earth
OK the saga continues. I have more url encoded requests coming in still. Running them through a decoder reflects st that they do not contain the string we filtered earlier. This is why i want to just trap ALL url encoded requests, reject them, and block them. There is absolutely no legit reason for anyone to request anything form any client on my server using url encoding. So we are back to the original question. How do I write a script that rejects and IP block ANY url encoded request?
 

quizknows

Well-Known Member
Oct 20, 2009
1,008
87
78
cPanel Access Level
DataCenter Provider
Checking the modsecurity reference manual I honestly don't see any recommended option that does this. You could use a regex to match the pattern of a urlencoded URI though.

This rule will block any request with nine or more sequential urlencoded characters, and accounts for the possibilitiy of the "+" character between the urlencoded chars.
Code:
SecRule REQUEST_URI "(\%[0-9a-fA-F][0-9a-fA-F]\+?){9}" "deny,id:1000849"