Cross-Site Request Forgeries and You

For the IMG trick, what harm is it to GET something? Assuming your website doesn’t have anything destructive happen without a POST.

This depends on what you consider destructive. Logging a user out (being the given example) doesn’t typically alter data (maybe logging and maybe some other dull bookkeeping) on the server—it can, however, alter data on the client (cause the user to lose unsaved/unsent work).

This would imply that REST implemented sites would be very vulnerable to this type of attack.

Only if you consider Log out a Resource or destination. Somewhat more correctly, but still incorrectly, it would be a query on a resource (say, Authentication Controller). Correctly, it would be an action, which you would POST, to a resource—it alters your session and the data associated therewith.

There’s all sorts of other ways that this can go haywire, especially if you do a lot on the client. That’s why… you build the application with safeguards for this sort of stuff.

In other words, to quote Garren above: It depends entirely upon the implementation doesn’t it?

In further other words: Requiring a POST to do actions like log out and requiring the POST originate from the site is not inconsistent with REST. None of what the article above discussed as a solution can’t be done with REST.

@JW, @Michael L Perry: From reading your posts, I think that either you haven’t read Jeff’s post at all, or you massively misunderstand CSRF and think it’s the same as XSS.

You both might want to go and read up on CSRF/XSRF and make sure you’re clear on how it’s different to XSS. It’s nothing to do with encoding anything.

The form is not running on your site, hence cross-site… scripting vulnerability.

As you have pointed out that the form does not run on the original website, in that case wont the browser dis-allow such a request? As the request is being originated from javascript to a different domain shouldn’t the browser catch it and throw a javascript error?

I’m not a javascript wizard, but is it possible to load a remote page in a hidden iframe on the malicious page, parse it with javascript to find the hidden token and then populate the form the user is (presumably) about to submit with the right values?

http://www.owasp.org (Open Web Application Security Project) has many great articles, best practices, how tos, and checklists for securing web sites.

@David Goodwin: No, the same-origin policy would prevent the malicious page from reading the contents of the iframe.

Your comment on the referrer check is a bit of a cop-out, Jeff:

Furthermore, spoofing the referrer value is extremely easy. All in
all, a waste of time. Don’t even bother with referrer checks.

Spoofing the referrer is extremely easy for a malicious user agent, yes. However, in this case you are trying to trick a normal user’s browser, and a regular browser will not spoof the referrer string, so for protection against XSRF checking it will work.

I agree that it may still be a bad idea because the referrer field can be stripped, but your argument there was flawed.

great post! I finally understand what are those protect_from_forgery keys all about…

Another good way to avoid these type of attacks to your restful APIs is to not use cookies for authentication. Instead force the client App to insert an HTTP Authentication header in all requests (even if its just reusing a value stored in a cookie). This essentially forces your AJAX requests to be made using XMLHTTPRequests, and prevents requests from third party domains.

What a uncanny coincidence, Simon Willison posted a link regarding robust CSRF today: http://simonwillison.net/2008/Sep/24/robust/

The digg link is nice, but it seems that it’s author wasn’t smart enough to remove or prevent comment spam :frowning:

If the only thing you ever deal with is comments on a website, blogs, or other word documents, then yes, you need to preserve what is displayed = what was input. But don’t fool anyone into thinking that because it ‘looks’ the same, it needs to be stored exactly as the user typed it. JW and MLP made a big fuss about preserving input exactly, but it’s not a universal truth. There’s nothing sacred about user input. The user can be malicious.

The problem is that the abstraction of html leaks out, and it’s the leaky abstraction that is exploited.

I’m no expert (and am likely missing something obvious), but your logout example seems to defy the REST paradigm because a GET operation changes the state (logs you out). If you truely follow the REST paradigm, then it would already be a POST.

Also, I’m a little confused on about the comment: force the target URL to be retrieved by any random user who happens to browse that page – using their browser credentials!

which credentials are you referring to? wouldn’t the cookies and other form fields within the page NOT be sent during the image fetch (since they are in a different domain) ? only referring url might give away a URL embedded session id?

Perhaps you are referring to some malformed HTML that makes the browser reveal values in other form fields on the original page?

Can anyone shed some light on what I’m missing?

Jeff, please do not complicate the already complicated Web with more cookies and obscure POST forms.

There are at least two much better solutions than what you propose:

The first is based on understanding that exposing a generic URL like
/logout means whoever uses it, is logged out. The authentication is essentially missing. The website simply assumes some things internally when the URL is called. Since all websites use cookies or server-side sessions of sorts, what such URLs do is they logout the user they have information on either in these cookies or session variables. What is a much better idea, and is essentially transparent to the user (ONLY if he uses site navigation, and not third party request by URL) is to use a sort of authentication that cannot be forged. Since the default /logout URL request, wherever from and by whomever submitted, already carries all necessary user id data, it may be misused. If one requires that such request comes with a POST data generated prior to request, or a query string variable, both identifying the user, an attacker will not be able to trick anybody into logging themselves out accidentally, because a complimentary user authorization data is not sent beside the request.

Another solution is to think twice when processing HTML input on forums and such containing IMG objects that carry a src attribute that points to anything else than image mime-types. Again, a whitelist of such mime types. And this is done by sending a HEAD request first, prior to embedding such images which will be requested with GET and thus trigger server-side script processing such as the /logout URL would. Issue a HEAD request, check the mime type header, and if it is not an image type, reject the tag input.

Funny how it reads no HTML in this very form field I am typing this text in. Talk about FUD.

Spoofing the referrer is extremely easy for a malicious user agent, yes. However, in this case you are trying to trick a normal user’s browser, and a regular browser will not spoof the referrer string, so for protection against XSRF checking it will work.

Interesting you should say that, because I use a FireFox addon named RefControl on my home computer that doesn’t strip out the referrer, but changes it to whatever I want (the domain’s root url usually).

Incidentally, thank you for reminding me that I hadn’t installed it on my work computer. goes to install it

Steven Sanderson Said: You both might want to go and read up on CSRF/XSRF and make sure you’re clear on how it’s different to XSS. It’s nothing to do with encoding anything.

I think that they are simply referring to Jeff’s comment: The name of the XSS game is sanitizing user input. This was just a side note to the conversation and they picked up on it. They understand the difference between XSS and XSRF.

This would imply that REST implemented sites would be very vulnerable to this type of attack.

What does REST have to with this issue? It seems like any site is vulnerable if this issue is not considered during design. I don’t see how a RESTful architecture makes you more or less vulnerable.

FWIW, Placing a verb in the URI, e.g. http://foo.com/logout, is not considered RESTful and in the original example it violates the usage of HTTP GET, as it’s not safe.

This type of URI design is the same thing that got 37 signals in trouble with Google Web Accelerator.

What if you just removed http:// from input? And then htmlEncode everything else? If users want to use links, setup your page to have them enter ">http://www.mylink.com[/IMG] instead.

If then can’t create tags, they can’t do this. Unless I’m missing something.

[URL]http://www.mylink.com[/URL] - meant that instead of using IMG tags.

Wow! I can’t beleive I’d never considered this as a vulnerability. I’ve been aware of XSS for awhile but this must have been around since the start of the web?

How come it’s got such a low profile?

Another solution is to think twice when processing HTML input on forums and such containing IMG objects that carry a src attribute that points to anything else than image mime-types. Again, a whitelist of such mime types. And this is done by sending a HEAD request first, prior to embedding such images which will be requested with GET and thus trigger server-side script processing such as the /logout URL would. Issue a HEAD request, check the mime type header, and if it is not an image type, reject the tag input.

That is sensible but then I could put load on your server and possibly bring it down by linking to hugggge image files! :slight_smile: