There is a great article by High-Tech Bridge Security Research team about the Open Source WAF ModSecurity. I thought it'd be interesting to cover a few of the topics they mentioned at a high level.
Have you ever had a scenario where a security vulnerability was identified (perhaps by a scanner, or an outside resources, etc.) but you were unable to immediately patch it. Perhaps you were in the middle of a large project and had no resources. Perhaps the vulnerability was in a fragile high risk area of the sites and numerous hours or days of testing are required. Perhaps the site is hosted/built by a 3rd party and you have to deal with formalities and other delays. A possible solution to any of these problems would be to apply a temporary "virtual patch" with your WAF in order to block the attack from occurring until you get the developers to build & test the real patch. Remember you still want to perform real patching, your virtual patching should only be temporary because WAFs are just another layer, and that layer could also have vulnerabilities or weaknesses of their own (such as WAF bypasses). Thus the only real way to prevent exploit is to perform a full patch.
But for the temporary fix, you might be wondering ... what does a virtual patch look like? Well essentially you can write a rule (think of it as similar to a SNORT IDS/IPS rule) that restricts what data can be utilized on the website to hopefully allow the good data and block that attackers data.
XSS Example
Exploit Url: http://www.mysite.com/product.aspx?productid=alert(document.cookie)
Virtual Patch:
SecRule REQUEST_FILENAME "/product.aspx" "phase:2, t:none, t:normalisePath, t:lowercase, t:urlDecodeUni, chain, deny, log, id:1001"
SecRule ARGS_GET:productid "!^[0-9]+$" "t:none"
To explain further, let's say in the example above that you confirm the productid parameter on the product.aspx page is vulnerable to XSS but you cannot apply permanent patch yet. Thus you want to create a temporary WAF virtual patch to block attackers from exploiting it. The 'SecRule' keyword allows you to analyze and act upon variables. You'll notice there are 2 lines thus we are analyzing 2 variables. The 1st is the 'REQUEST_FILENAME' variable and it holds the name of the file being requested. In this case we validate that it's the product.aspx page. Then we can set a bunch of actions. The first one I want to point out is the word 'chain'. This indicates that there are multiple 'SecRule's that are getting chained together (in this case our 2 lines/2 variables we're comparing). Also it says 'deny' and 'log' which means if these chained rules match we are denying and logging it. Just like a snort rule there is an "id" also for tracking. There are also a bunch that start with the letter 't' which stand for transformation functions. 'none' starts you with a clean slate, then it's saying do all the comparisons in 'lowercase', and use the 'normalisePath' to eliminate any double slashes, and use unicode with 'urlDecodeUni'. The other action in the first line is 'phase:2' which indicates for the WAF to look at the Request. Phase 1 is the request headers, Phase 2 is the request, Phase 3 is the Response headers, phase 4 is the Response, and Phase 5 is logging. The phase is for performance.
The second line is another 'SecRule' on a variable called 'ARGS_GET'. More specifically, it's comparing the value of the 'productid' query string argument. This line creates a whitelist to basically attempt to allow the good data and block the attackers bad data. In this case it's providing a regular express that says the productid can only contain numbers (1 to many). Thus by allowing only numbers, the WAF will 'deny' the request and 'log' if anybody tries to pass anything other than numbers into the productid parameter. Just like that you've prevented the XSS.
SQLi Example
Exploit Url: http://www.mysite.com/search.aspx?keyword=value';insert+into+user+('admin','password');--
Virtual Patch:
SecRule REQUEST_FILENAME "/search.aspx" "phase:2, t:none, t:normalisePath, t:lowercase, t:urlDecodeUni, chain, deny, log, id:1002"
SecRule ARGS:keyword "'" "t:none, t:urlDecodeUni"
Just to provide a second example, above is a url that you've identified as having a keyword parameter vulnerable to SQL injection. In the case above, the attacker terminates the keyword value in SQL with the apostrophe, then inserts an admin user into the user table, then comments out the rest of the SQL. To prevent this we chain 2 'SecRule's again. We first check that we're on the vulnerable 'search.aspx' page and we're going to 'deny' and 'log' again.
The second line then look for the 'keyword' query string parameter, and if it contains an apostrophe or any unicode variation, then it will 'deny' the requst, thus you've temporarily prevented the SQL injection.
The article has many more great examples of how to block things like CSRF, Path Traversal, etc.
More about neonprimetime
Top Blogs of all-time
Top Github Contributions
Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Showing posts with label WAF. Show all posts
Showing posts with label WAF. Show all posts
Tuesday, March 1, 2016
ModSecurity Virtual Patching 101
Labels:
ModSecurity,
Patching,
SQL Injection,
SQLi,
Virtual Patching,
WAF,
Web Application Firewall,
XSS
Wednesday, September 23, 2015
WAF Is not an Excuse to Ignore an Vulnerability
WAFs are great, they can add an extra layer, and they can make attacks more difficult. But they are not the end-all-be-all. They have their flaws and thus as a developer you still need to write secure code and fix known open vulnerabilities. I thought it'd be interesting to review some of the concepts found in the Bypass WAF Cookbook to illustrate how this can be.
.NET specific % symbol - Some versions of IIS/ASP allow the % character in the url but actually ignore it when processing. Therefore if your url was 'http://mysite.com?a=sele%ct * from users' then IIS/ASP will actually just run 'http://mysite.com?a=select * from users'. Why is this a problem? If you wrote a Snort, IDS, or WAF regex rule to search for the word 'select', then 'sele%ct' may not match but will still run in IIS/ASP so you just found a way to possibly bypass the WAF if it can't handle that and perform some sql injection attacks!
.NET specific %u symbol - Some versions of IIS/ASP allow the %u to specify unicode characters instead of ascii. Therefore if your url was 'http://mysite.com?a=sel%u0065ct * from users' then IIS/ASP will actually just run 'http://mysite.com?a=select * from users' because %u0065 is unicode for 'e'. Why is this a problem? If you wrote a Snort, IDS, or WAF regex rule to search for the word 'select', then 'sel%u0065ct' may not match but will still run in IIS/ASP so you just found another way to bypass the WAF. Now WAFs may be getting smarter and learning tricks like this, but it's difficult if not impossible to capture all these scenarios. Like the author mentioned, a windows firewall bypass was found where in multibyte unicode sets, sometimes multiple codes resolve to the same character so like %u0065 and %u00f0 might both resolve to 'e'.
Apache specific http methods - Some versions of Apache are too lax in their http method syntax and thus you don't even need the word 'GET' in the request and it'll still perform one. Thus if your rule specifically looks for the 'GET' keyword, it won't match but yet Apache will still serve the request, thus you can send this malformed request, the WAF doesn't match the rule, but Apache still process the request ... bypass!
PHP specific normalization issues - Some version of PHP may parse the Content-Type header in strange ways that can trick the WAF into thinking it's requesting an image but PHP will process a non-image request.
HTTP parameter method changes - There are usually multiple ways to submit parameters, like GET, POST, and Cookies on a website. Sometimes a WAF may look only for GET and POST and thus you can use a Cookie to submit the same parameter and bypass the WAF.
Content-Type header changes - The WAF is inline and has to take performance related shortcuts. So it may decide to filter out or ignore certain types of data. So it's possible to bypass the WAF by tricking it into thinking the request is ignore-able ... such as switching the Content-type to 'multipart/form-data' (which is a method for transferring bulk form data to a server)
Parameter pollution - Another trick is to send multiple parameters like 'http://mysite.com?a=1&a=2&a=select * from users'. Now which 'a' will the WAF look at? The first or the last? And which will the web server use? If you can find a mismatch such that the WAF picks one but the Web Server picks the other, then you have a bypass!
Database tricks - If you have a WAF rule that's looking for a space followed by the word union you may find bypasses by finding characters that databases (like mysql) access beforehand like '\N' ... such that a URL like this 'http://mysite.com?x=1=1\Nunion select * from users' passes by the WAF rule, but the web server still processes it as a valid statement. Of course you can do other tricks too that involve certain string manipulation functions like CONCAT, SUBSTR, etc. and it's not likely the WAF can understand them all, yet the database will know exactly what to do with them.
Performance Bypass - Another concept is that the WAF's usually have a timeout period or some performance threshold, if they can't finish analysis in X period of time then they ignore it. Thus if you can find a way to submit a larger or slower than normal request that the WAF ignores but the web server takes the time to process, you just found a bypass!
Application Layer IP Filtering - Another concept is that some WAF's allow certain IPs to bypass and go directly to the Web Server (perhaps your corporate assets for performance reasons, etc.). The problem then is some of those headers or attributes can be spoofed to tricking the WAF into thinking you're coming from a different ip (such as using x-forwarded-for, etc.). If you can trick it into thinking you're one of the allowed ips, them bypass!
There is no simple fix, as you can see the bypasses could occur at the WAF itself, at the Web Server (IIS/Apache), at the language (PHP), at the database (mysql) or anywhere in between. Thus you can't trust WAFs as your only saving grace. Instead you should implement your WAF as 1 layer in your defense that would also include Firewall, IPS, secure coding, etc.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
.NET specific % symbol - Some versions of IIS/ASP allow the % character in the url but actually ignore it when processing. Therefore if your url was 'http://mysite.com?a=sele%ct * from users' then IIS/ASP will actually just run 'http://mysite.com?a=select * from users'. Why is this a problem? If you wrote a Snort, IDS, or WAF regex rule to search for the word 'select', then 'sele%ct' may not match but will still run in IIS/ASP so you just found a way to possibly bypass the WAF if it can't handle that and perform some sql injection attacks!
.NET specific %u symbol - Some versions of IIS/ASP allow the %u to specify unicode characters instead of ascii. Therefore if your url was 'http://mysite.com?a=sel%u0065ct * from users' then IIS/ASP will actually just run 'http://mysite.com?a=select * from users' because %u0065 is unicode for 'e'. Why is this a problem? If you wrote a Snort, IDS, or WAF regex rule to search for the word 'select', then 'sel%u0065ct' may not match but will still run in IIS/ASP so you just found another way to bypass the WAF. Now WAFs may be getting smarter and learning tricks like this, but it's difficult if not impossible to capture all these scenarios. Like the author mentioned, a windows firewall bypass was found where in multibyte unicode sets, sometimes multiple codes resolve to the same character so like %u0065 and %u00f0 might both resolve to 'e'.
Apache specific http methods - Some versions of Apache are too lax in their http method syntax and thus you don't even need the word 'GET' in the request and it'll still perform one. Thus if your rule specifically looks for the 'GET' keyword, it won't match but yet Apache will still serve the request, thus you can send this malformed request, the WAF doesn't match the rule, but Apache still process the request ... bypass!
PHP specific normalization issues - Some version of PHP may parse the Content-Type header in strange ways that can trick the WAF into thinking it's requesting an image but PHP will process a non-image request.
HTTP parameter method changes - There are usually multiple ways to submit parameters, like GET, POST, and Cookies on a website. Sometimes a WAF may look only for GET and POST and thus you can use a Cookie to submit the same parameter and bypass the WAF.
Content-Type header changes - The WAF is inline and has to take performance related shortcuts. So it may decide to filter out or ignore certain types of data. So it's possible to bypass the WAF by tricking it into thinking the request is ignore-able ... such as switching the Content-type to 'multipart/form-data' (which is a method for transferring bulk form data to a server)
Parameter pollution - Another trick is to send multiple parameters like 'http://mysite.com?a=1&a=2&a=select * from users'. Now which 'a' will the WAF look at? The first or the last? And which will the web server use? If you can find a mismatch such that the WAF picks one but the Web Server picks the other, then you have a bypass!
Database tricks - If you have a WAF rule that's looking for a space followed by the word union you may find bypasses by finding characters that databases (like mysql) access beforehand like '\N' ... such that a URL like this 'http://mysite.com?x=1=1\Nunion select * from users' passes by the WAF rule, but the web server still processes it as a valid statement. Of course you can do other tricks too that involve certain string manipulation functions like CONCAT, SUBSTR, etc. and it's not likely the WAF can understand them all, yet the database will know exactly what to do with them.
Performance Bypass - Another concept is that the WAF's usually have a timeout period or some performance threshold, if they can't finish analysis in X period of time then they ignore it. Thus if you can find a way to submit a larger or slower than normal request that the WAF ignores but the web server takes the time to process, you just found a bypass!
Application Layer IP Filtering - Another concept is that some WAF's allow certain IPs to bypass and go directly to the Web Server (perhaps your corporate assets for performance reasons, etc.). The problem then is some of those headers or attributes can be spoofed to tricking the WAF into thinking you're coming from a different ip (such as using x-forwarded-for, etc.). If you can trick it into thinking you're one of the allowed ips, them bypass!
There is no simple fix, as you can see the bypasses could occur at the WAF itself, at the Web Server (IIS/Apache), at the language (PHP), at the database (mysql) or anywhere in between. Thus you can't trust WAFs as your only saving grace. Instead you should implement your WAF as 1 layer in your defense that would also include Firewall, IPS, secure coding, etc.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Subscribe to:
Posts (Atom)