Hacker News new | ask | show | jobs
by Xk 5186 days ago
CSRF is NOT a browser vulnerability. The browser is doing exactly what it's supposed to do: load content. The browser can not (and should not) attempt to identify the "evil" HTTP requests from the "good" ones. The browser's job is to make requests.

Now, you could argue the browser's job should be to implement security features as well. It does, after all, implement the same-origin policy. But, if you think about it, there is no good way for the browser to fix the CSRF issue. You can ask the user, which is what's suggested, but that never really works. They'll do one of two things: click "okay" every single time, or stop using your browser.

I would guess well over half of all websites do one of the following: (1) load an external JS file, (2) load an external image, (3) load an external CSS file, (4) use an iframe which points to a different origin, (5) use a JS redirect, (6) use a meta redirect, or (7) open a new window.

The proposed "solution" to CSRF stops ALL of these use cases. The user would have to manually approve each and every one of them. Given that well under 1% of alerts would be true attacks, the user would almost definitely "okay" on the attacks as well: they would have been trained by thousands of other alerts that this is an acceptable thing to do.

There was a paper by Barth and Jackson on CSRF defenses where they propose an Origin header, but that's the extent to which security is implemented in the browser. It is fundamentally up to the web application for verifying the user did in fact initiate the request. No amount of code in the web browser can get around this fact.

1 comments

>I would guess well over half of all websites do one of the following: (1) load an external JS file, (2) load an external image, (3) load an external CSS file, (4) use an iframe which points to a different origin, (5) use a JS redirect, (6) use a meta redirect, or (7) open a new window. The proposed "solution" to CSRF breaks ALL of these uses.

You definitely kidding me. Please point out where in my post I said to deny ALL requests. I was talking about ONLY POST requests. Probably I forgot to add it :) So, I'm talking only about forms sending and GET is ok sure.

Either you do it for everything, or you do it for only POST and you end up missing half of the vulnerabilities. Correct me if I'm wrong, but your CSRF attack used a GET request, did it not? [1]

Web applications make state-changing operations on GET requests. You might not like it, but they do.

[1] <img src="https://mail.google.com/mail/u/0/?logout style="display: none;" />

>Web applications make state-changing operations on GET requests. You might not like it, but they do.

but when developer made a mistake with GET it is 100% his problem - it's out of question. he should be punished :D

Nonsensical. CSRF isn't God's punishment for REST-lessness.
You're both just choosing different places to draw the line between developer responsibility and browser responsibility.
That is like saying "you're both just suggesting two totally different designs for the HTTP security model".

His model is wrong. Again: I assume he wants to know that, so, bluntness.

Perfectly solid web apps routinely ask browsers to POST to other domains.
So rather than deny ALL requests, I think it would work if browsers merely stopped passing cookies on cross-site POST form submissions, no?

Then if 3rd party sites wanted to still use form submissions, they could use an auth token in the form (though I'm unsure why they would do this instead of using JSONP).

Firefox already blocks off-domain POST requests, unless the 3rd party domain responds to an OPTIONS preflight request.

So, I'm talking only about forms sending and GET is ok sure.

Google's logout CSRF works because the logout link is a GET request. So, no, there is no quick fix.

No it does not.

---

https://developer.mozilla.org/en/http_access_control#Simple_...

A simple cross-site request is one that:

- Only uses GET or POST. If POST is used to send data to the server, the Content-Type of the data sent to the server with the HTTP POST request is one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.

- Does not set custom headers with the HTTP Request (such as X-Modified, etc.)

---

This is actually a big deal, since it means you can send a cross-domain mutlipart-POST with no preflight. That allows for an effective CSRF attack against file upload systems.

And of course, cross-domain POST requests via <form> tags have always worked and will continue to work.

Am I missing something here?

Let's say you're logged into Gmail and Gmail had no CSRF protection anywhere.

You're logged in while visiting my site. In my site, I include a little bit of JavaScript to make a POST request to Gmail telling it to forward copies of all your incoming email to my email address.

This will not work even without CSRF protection. It would only work if Google sends back the header Access-Control-Allow-Origin: mysite or Access-Control-Allow-Origin: * as noted in the section you linked to.

Of course, I could also try to trick you into filling out a form whose method actually is pointed at Gmail's and include all the hidden input tags to set you up for forwarding emails to me, but you would know something fishy is going on because it would redirect you to Gmail.

"This will not work even without CSRF protection."

It actually will work.

What you're describing is what's known as a "simple" request in XMLHttpRequest terms. That means there is no pre-flight necessary. Your browser will simply make the POST as requested and receive the response. It won't make the response available to you since the Access-Control-Allow-Origin header isn't set, but you're a malicious attacker in this example and you don't care what the response is: you just care that you were able to make the request. ;-)

You could even do this by creating an HTML form that POSTs to the right URL and using JavaScript to submit it automatically when the page loads. Same exact thing: no CORS checks.

If a pre-flight were necessary you would be right. The browser would send an OPTIONS request to the server, the server would respond without the appropriate headers, and the POST request would never be sent.

Let me know if any of this needs further explanation!

Oh, I see now. I had assumed that because I couldn't get the response, that the request itself was blocked.

Thanks!

I would like to know one thing.

Who the hell thought it was a good idea to allow crossdomain XmlHttpRequests? Given that the standard say that post is for modification no other website should ever make thoes requsts.