30 Mar 2012

CSRF Is A Vulnerability In All Browsers

Navigation:
#1 CSRF Is A Vulnerability In All Browsers - You MUST Deny It ASAP.
#2 top secret(will be published on April 1)
#3 Another Rails Issue(April 2-3)
#4 The Webkit Hole(April 2-4)

It took me a long time to understand the point behind CSR (cross-site requests) and CRSF fully enough to find them EXTREMELY malicious.
Following points should be made before any explanation.
  • It is well known attack(yep, just like mass assignment). It's known but not well. You won't find any mention of CSRF in books for beginners a la "PHP in 24 hours" or "HTML/CSS for dummy". Underestimated kind of attack.
  • It is neither bug in OS nor in browser nor in the servers' adjustments. Linux/Mac/Windows, Chrome/Firefox/IE - it just doesn't matter! This is just an expected behavior. And it works like it supposed to. Funny, isn't it? Known since 2001 but not fixed yet. Interested? Keep reading.
  • HTTPS? Would not help. SSL has nothing to do with this attack.
  • Short sessions? Sounds nice, but there are always a few ways to ask/force user to sign in and than script can attack. We are human, it's not so difficult to cheat on us. And, short sessions are rare, most sites with a "remember me" button do not rely on short sessions.
  • Special plugins/extensions to be secure(e.g. https://www.requestpolicy.com/). Who uses them?! O_o Almost nobody.
  • Protection on server-side. Rails 3 framework has it out-of-box - using authenticity_token helps. By the way Rails is the most secure framework I've ever seen.(sic!) Mass assignment is "vulnerability" in the documentation and developers are in charge; but not in rails. At the same time to have protection with other langs/platforms(PHP, Java, Asp.net) you have to write ~10-50 additional lines of code. IMO(and *these cases* prove it) 90% of developers just don't care and don't spend time on that. That's a huge hole, easy to find and easy to use.
The backbone.
There is site1.com. It could be anything: blog, social network like facebook/twitter/google+ or even payment system. You have an account on this site.
1. You are remembered with cookies mechanism.
2. Site has short sessions. Hacker asks you to sign in anyhow. E.g. the banner "you won 1 dollar for visiting this page, check your %payment _system%!" and in a few seconds after you signed in hacker's page fires up the malicious script.

So, you are signed in.

You visit site site2.com(with funny pictures, free mp3 or pr0n). No matter how you got there - let's assume friend gave you the link.
That site sells "iframe traffic"(or just contains malicious code itself). It means that funny site uses your browser(and your accounts on all sites where you are logged in!!).  You know nothing and notice nothing. Hidden iframe loads malicious Javascript which executes POST(or GET/DELETE/PATCH etc - all HTTP Verbs are supported) by submitting generated <form> with specific params. Form's action points to site1.com/someaction, form's target - name of another hidden iframe. Then, code fires up formObject.submit(). It is manual form submitting.
What has happened? "You"(in fact "your browser") just sent request to site1.com/someaction with all needed cookies(browser attached them automatically) with (definitely malicious) params - for example "spam blog post", "start following another spam account" or even data for withdrawing money to hacker's bank account(sic!) - anything.
Server side has no idea that you are not "you" - it looks the same. And Application executes your request just like it was you who made a request. You didn't notice anything.

One day you will, for example, check list of your followings and find there unknown strange accounts named like "viagra_buy_online_ca" or "celitra_no_prescription" lol. Or find out that few days ago you tweeted "Earn 10 Dollars Per Second Super Technique Blah Blah link.com/referal". (sent not via twitter.com but approved apps like vulnerable YFrog)

Prevention.
It is the common case described above. Of course sites like google, twitter, facebook etc most likely are protected from this attack. But not necessary! Protection requires additional efforts - this is why so many websites are CSRF-vulnerable.

I so much enjoy the following quote from the previous shit storm:
Insecure-by-default means "insecure"
Exactly, the same thing here. By default your app is insecure.

If your apps consume requests w/o verifying authenticity token for each POST/GET/... request - you are vulnerable. For each, every time.
Yeah, you can check 'referer' every time but it involves additional regexp/rules and looks so lame to me, this is not a panacea at all.

What do I suggest.
A compromise. We cannot deny the technique right away for a lot of reasons - backwards compatibility, most ads and analytics engines use it - denial will break tons of code in the internet, and sometimes it's really useful and needed thing etc.

Look at the pictures:







These are default top bars in chrome and firefox for some actions that could potentially be malicious. I suggest to make a similar one e.g.:

*This page %hackersite.com% submits data to an external resource %paymentsystem.com%! What to do?*
[button Accept]
[button Decline]
[check box - add the resource domain to whitelist(for stats and ads)]

But it should be denied by default and request should be sent only if user accepts it.

Again, kind of conclusion: CSRF is not a vulnerability in apps. It is a HUGE HOLE in browsers. And this damn hole makes us, developers, to invent wheel such stupid things like csrfmiddlewaretoken compulsory IN EVERY REQUEST. Imagine milliards of HTTP requests and each contains sort of  "9f38ada5f4e2c62ca8550071c2c44a0796be8c40" thing + tons of checks cookie[token]=params[token]. What a fail?! It's you job, dear browser, to handle requests and SameOriginPolicy stuff. What a workaround?! Are you kidding us, honey?

We(browsers+developers+w3c etc) must find the best solution of the issue and fix it. OK, I know in before you won't listen to the speech. Words don't change the way how web browsers work. *Here are actions*.

This change will dramatically make the Internet 80%(And this is not a random number but pretty real percent of "vulnerable" sites) more secure and safe! Let's solve the issue once and for all ASAP.


References:
http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html - in 2008 youtube had no protection at all. Do you still think it's newbies' mistake? Jeff Antwood SHOUTED about CSRF. What has changed since 2008? Nothing. Youtube is safe but thousands of new startups aren't.
https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/request_forgery_protection.rb - that's how rails rockstars got rid of the issue by default.
https://media.blackhat.com/bh-eu-12/shah/bh-eu-12-Shah_HTML5_Top_10-Slides.pdf - slides from recent black hat conf
http://pentestmonkey.net/blog/csrf-xml-post-request - don't rely on custom Request Payload. The same thing with json's payloads.
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Checking_Referer_Header - RTFM

tbc

P.S. the first post contains only theory. Please, stay tuned until April 1 and you will get lulz info