Three months ago Core Security posted an advisory regarding a CSRF vulnerability I’ve found in IBM WebSphere Application Server. While preparing the advisory, I’ve investigated some ways to mitigate this class of vulnerability when, for some reason, there’s no patch available for the affected web application. It turned that Cross-Site Request Forgery can be mitigated both on the server side and on the client side.
Mitigating on the server side
On the server side, OWASP states that “checking the referrer in the client’s HTTP request will prevent CSRF attacks.” Since CSRF means that a malicious third-party website can force our web browser to perform unintended requests against legitimate sites in which we’re already logged in, we can add a rule to a Web Application Firewall that checks the “Referer” header in the client’s HTTP request, and only allows those requests in which the referrer site matches the requested (vulnerable) site. This will ensure that the request is coming from the original site and not from other (possibly attacker-controlled) sites, thus preventing CSRF. Note that if the website is also vulnerable to XSS, the rule on the WAF will be bypassed, since the request will be coming from the same site.
Of course, this server side mitigation is only possible when we have control over the vulnerable web site (i.e, a web app on the Intranet of our company). If the vulnerable site is located somewhere in the Internet, there’s nothing we can do on the server side to mitigate the vulnerability, other than asking the developers to fix it. In the last case, we fortunately have a client side way to protect us from this kind of vulnerability, as described below.
Mitigating on the client side
On the client side, the NoScript addon for Mozilla Firefox comes in handy to mitigate CSRF, besides its well-known capabilities to block client-side scripts, iframes, Flash/Java/Silverlight objects, etc. NoScript includes a feature named Application Boundaries Enforcer, or ABE for short, available under the Options dialog of NoScript -> Advanced -> ABE:
ABE allows us to define rules like this:
Site *.example.com Accept from SELF Deny
that means: “For any website matching the pattern *.example.com, only perform requests originated from the same site; for the rest of the requests to *.example.com originated on other sites, just block them“.
That rule should prevent CSRF for *.example.com, as ABE will allow Firefox to make an HTTP request against *.example.com only if the request was originated on the same site. If the website generating the request to *.example.com is other than *.example.com, ABE will just prevent Firefox from performing the request.
Note that, although very useful for preventing CRSF attacks, the ABE rule discussed above could break websites that make legitimate use of *.example.com. Excessively tight rules will make impossible to do cross-site content inclusion (for example, something as simple as including an image file hosted on another domain) and even hyperlinking, which are key components for the Web.
In order to illustrate this possible side effect, take a look at the following screenshot. I have defined the following ABE rule:
Site *.google.com.ar Accept from SELF Deny
When loading a web page from localhost that includes a link to http://www.google.com.ar, an <img> tag referencing the Google Logo from http://www.google.com.ar and an <iframe> tag containing http://www.google.com.ar as source, both the <img> and the <iframe> become blocked (see the NoScript warning at the top), and the link becomes un-clickable.
Finally, you can take a look at more fine-tuned ABE rules examples here. Also, if you are going to give a try to this NoScript module, don’t forget to check the ABE Rules Synax and Capabilities PDF document.