As a security researcher, going out and discovering a cross site scripting (XSS) orcross site request forgery (XSRF) vulnerability is a great pick me up while sludging through mounds of code looking for more respectable vulnerabilities. While XSS and XSRF vulnerabilities are often “low hanging fruit”, they do present legitimate security concerns. However, I am not here to talk about XSS & XSRF and their security impact; that has already been done by a plethora of sources. And while important, I also wish to avoid discussing the need for input validation. What I do want to comment on is the shortcomings of a way web developers are attempting to mitigate XSS and XSRF attacks.
A popular way to address XSRF is to check the HTTP Referer header (yes, I know “Referer” is misspelled but blame the RFC) and verify that the request indeed came from the same web site. A side effect of this XSRF mitigation technique is that non-persistent XSS vulnerabilities are prevented with the same effectiveness. Is this a good solution? Not really, but it is better than nothing. The big question is, how do these web sites handle situations where there is no Referer header? According to RFC 2616, “the Referer field MUST NOT be sent if the Request-URI was obtained from a source that does not have its own URI, such as input from the user keyboard.” Turns out, a lot of web sites default to accepting requests that do not have a Referer header. This allows web sites to still work with browsers that do not use the Referer header or have it turned off. Consider the impact: every time you click a link in an email, no Referer header is sent (assuming you are not using web-based email). In fact, in order to prevent information leakage, it is often encouraged as a security measure to configure your browser to disable the transmission of the HTTP Referer header. On the corporate side, a lot of web proxies are configured to strip the HTTP Referer header even if it is sent by the web browser.
So if checking the Referer header is not enough, how can XSRF attacks be effectively prevented? There is no 100% effective solution but the best technique is to generate a nonce and include it in every link and form that is served. The server keeps track of this nonce and the client submits it to the server with every request. The server verifies the submitted nonce before performing the requested action. Implementing this can involve extensive web site redesign and introduces increased server overhead since it has to keep track of the nonce(s). Is there a simpler solution? While not as effective as the nonce method, what if a web site that receives a request without a HTTP Referer header defaulted to redirecting the browser to the login page or the site’s “main” page instead of performing the requested action. For sites that already do HTTP Referer checking, this would be a simple addition that offers a large security benefit. The impact here is obvious — browsers that do not support HTTP Referer headers or have them disabled would still be incompatible but attack vectors such as links in emails would be blocked.
Preventing XSRF attacks is difficult and effective mitigation while maintaining browser support is by no means simple. By defaulting to not performing requests with no HTTP Referer header, web sites increase their security while at the same time introducing the possibility of browser incompatibility.
Further information on XSRF can be found in the following links: