Anti-CSRF and Bad Choices
This is very a old vulnerability, however especially with the new "AJAX friendly" Anti-CSRF tokens this has been exploited in various ways.
Some weak Anti-CSRF implementations use HTTP Headers with predictable or static data. For example as long as the request made with a header like this
X-Requested-With: XMLHttpRequest, request will pass the Anti-CSRF check.
Since classical exploitation of CSRF relies on simple
POST requests with a simple HTML and redirect/auto submit, and since you cannot add custom headers to these requests, in theory this is not exploitable. I guess this and the simplicity of it is why some libraries and developers chose this design. Having said that it's obviously a weak and lazy implementation.
The real question is;
If it's weak, how can you exploit it?
We know security is not always answering "Is it vulnerable now?", it's mostly about answering the question:
Is it well designed?
If you've seen enough vulnerabilities in your time, your gut will tell you when something smells.
Call it Gladwell's Blink or call it "history repeats itself" or an "educated guess" however you need to make your design future proof.
Security of a feature should be designed with the assumption of what has been broken in the past can be broken again.
Think about some of the recent vulnerabilities / bypasses we've seen. Take Rosetta Flash and Same Origin Method Execution. Both attacks are possible because common JSONP implementations don't follow a well known security pattern: "Whitelisting". JSONP doesn't really need to be that flexible, a fixed callback name would save the day. Secondly, a length check would make Rosetta Flash attack impossible. So it's all about level of security. Just like code smells, security design smells as well.
Even when something is not immediately exploitable you can smell the weakness in design. JSONP is a good example of this.
ASP.NET ViewState (and similar state implementaions in other frameworks) is another example of smelly design. ViewState takes data that can be stored on the server-side and push it to the client-side with encryption. Granted this can be done securely however it's an unnecessary risk, increases attack surface. We've seen it effected by Padding Oracle attacks and this even caused remote code execution in ASP.NET. Not to mention this design caused (and possibly will cause in the future) regular other problems such as XSS and leakage of private information. Some designs also makes it harder for developers to write secure applications.
Back to Flash
So there are lazy Anti-CSRF implementations that relies on the assumption an attacker cannot force a request with custom header. True, that all of the current browsers protect against this however Flash allows users to add custom HTTP headers on cross origin requests.
As you know Flash normally doesn't let you make a cross origin requests without a Crossdomain.xml that allows it. However by using Status 307 you can make a request to a domain that you control and redirect it to the real destination.
307 Temporary Redirect
Http Status 307 has exploited in various ways in the past. It's main difference from Status 301 and 302 is it actually redirects the whole request (body, headers etc. all of it). So you can redirect POST requests or requests with various headers, that's not the case with 301 and 302.
Putting All Together
- Make a Flash that carries out CSRF attack with forged custom header such as
- Carry out the request to your own domain ( attacker.com/redirect307/ )
- Your page returns Status 307 with the new URL ( victim.com/lame-anti-csrf/ )
- Now you'll see that the request includes a custom header
Effectively you have managed to add a custom header to a cross domain requests. That's all we were trying to accomplish.
Indeed this is old news, it just ended up on our discussion list this week and I wanted to cover it, touch couple of design mistakes and finally to let you know somehow Adobe decided to fix this problem after 6+ years.
Which browsers, how
There is a summary write-up on this issue from 2011, and this is the results of browser behaviours from that message, CSRF: Flash + 307 redirect = Game Over
Mac - Flash Player 10,2,154,12 Chrome 9.0.597.94 302 Redirect GET Request, with headers Chrome 9.0.597.94 307 Redirect Not Sent Safari 5.0.3 (6533.19.4) 302 Redirect GET Request, with headers Safari 5.0.3 (6533.19.4) 307 Redirect POST Request, with headers (No Confirmation) FireFox 3.6.10 302 Redirect GET Request, no headers FireFox 3.6.10 307 Redirect POST Request, with headers FireFox 4 beta 8 no bueno Windows XP - Flash Player 10.2.152.26 FireFox 3.6.10 302 Redirect GET Request, no headers FireFox 3.6.10 307 Redirect POST Request, with headers IE 7 no bueno IE 8 no bueno
Details for a real world case, Anti-CSRF bypass in Vimeo
Which headers are black listed in Flash
According to Flash documentation these are the black listed header names;
What about XMLHTTP
A relevant topic is what headers are blacklisted in XMLHTTP, you can find a nice list of them in Browser Security Handbook
NCC guys put up a nice repo in Github with Adobe PDF/Flash samples for cross origin data stealing stuff, so take a look if you are rusty in Action Scipt, well.... who isn't!