Mitigating Cross-Site Request Forgery with NoScript

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.

Drawbacks

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.

4 thoughts on “Mitigating Cross-Site Request Forgery with NoScript

  1. Two points:

    1) Checking the Referer header is a good first step, but not reliable, since it’s possible for attackers to forge that header. And what about different applications hosted at the same site, as happens on eg Facebook? A much better solution is to include a random value as a hidden field in all forms, so that attackers won’t be able to craft a legitimate cross-site request (unless they find an XSS hole that will allow their attack to check the hidden field – in which case, you need to close that hole).

    2) Importing an image from another domain is not so harmless; img tags are frequently the mechanism for launching CSRF attacks! ABE is quite right to block them, and especially so with IFRAMEs (which have more power, and hence more danger). However, for a good balance between usability and protection, you can change the ABE rule to ‘Anon’ (stripping authentication information) instead of ‘Deny’, or you can try the RequestPolicy addon, which has an option to automatically allow subdomains to talk to each other.

    • Hi Thrawn,
      thanks for your insights.

      Regarding point 1), you’re right about the possibility of forging the Referer header, I’ve overlooked it; by the way, yesterday I’ve read an interesting blog post about methods for stripping the referrer in the client side, which are new to me: http://blog.kotowicz.net/2011/10/stripping-referrer-for-fun-and-profit.html.

      Besides that, the proposed WAF mitigation was intended as a workaround for a vulnerable web application that tries to prevent CSRF by using tokens, but somehow has a little hole somewhere (like in the WebSphere case described in the Core advisory), not as a replacement for anti-CSRF tokens. Definitely including random tokens in all forms is the way to go… as long as you do not forget to check them on the server side, as WebSphere did! 🙂

      Regarding point 2), thanks for the ‘Anon’ tip! And I’ll take a look at the RequestPolicy addon.

  2. In addition, since NoScript knows which sites are considered ‘trusted’ vs ‘untrusted’ by the user, it is able to apply another protection: requests sent from untrusted sites to trusted ones are automatically sanitized (remove cookies, auth, POST body).

Leave a reply to fdfalcon Cancel reply