comments (not for humans)
There has been a lot of writing about Cross-site request forgeries (XSRF/CSRF) lately. I've read numerous articles on how this could be used to capture home routers or create false online-banking transactions. In this post I'll discuss some techniques for protecting your website against XSRF.

What is XSRF?
If you don't know what XSRF is, I suggest you read this wikipedia article. XSRF exploits the fact that a user can reach a website (because he's behind a firewall or logged in to a site), that the attacker cannot attack directly. If the attacker can trick the user into running a malicious script, he can force the users browser to act on his behalf.


A typical XSRF scenario
The user sits on his home computer surfing the internet. He visits a malicious site, which runs some javascript on the users behalf. This script creates a form which it posts against the users home router. The form contains the standard username, password and IP-address of home routers from the user's ISP. The router cannot be reached from the internet, but the user is sitting in the same subnet as the router, and the router is accessible from the user's computer. Once the first form has been posted, the malicious script creates a second form, which tries to change the router's DNS to a malicious DNS. If this is successful, the attacker will have full control over what websites will be returned when the user enters an address in his browser, e.g. the attacker can return a fake banking site even though the user wrote the correct URL for his online-banking site in the browser (the user would get messages about untrusted SSL certificates, but most users blatantely ignore the messages).

It is important to understand that these attacks are blind, meaning the attacker only controls the user's browser indirectly and cannot always see if the XSRF was successful or not.

Protective measures
To be able to protect a web page from XSRF, the web server needs to check that the requests are legit. This means that it needs some measure to check that the request actually came from the corresponding form in the application.

1. The referer header
Since the attacker does not directly control the user's browser, the referer header is actually a posibility. But some users disable the referer header because it leaks information when users click on links to other sites.

2. Unique identifiers
The second option is to include a unique identifier for each user. When the user opens a form and posts it back the server, the identifier sent to the user in when opening the form, must be included when posting back. If it is different or not present, the post is rejected.

Some people tend to think that using the session identifier for this purpose, is a good idea. If XSRF was the only security concern, I would agree, but using the session identifier directly contradicts the idea of HttpOnly-cookies (where the session id is protected against cookie-stealing by not being accessible from javascript).

Creating unique identifiers is easy, and instead of using the session identifier directly, we can use the fact that the user has a session to help creating and checking the identifier. We can use hash-function (md5 or sha1) in combination with a timestamp and a secret password/key. We create our identifier like this: id = hash_function(secret_key + timestamp_in_milliseconds)
We put this identifier in the users session, and we then include this value in every form we send to the user. Checking the identifier when receiving a post is now trivial, and we do not expose the session identifier to javascript.

The protective measure described will not apply to GET requests, only POST requests. But if you are allowing GET requests to alter data in your application, your are misusing the semantics of the HTTP verbs.

Tabbed browsing and XSRF
Tabbed browsing actually makes XSRF more likely to succeed. The reasoning here is that all tabs share the same set of session cookies (session cookies are cookies that are deleted when the browser is closed), and users tend to be logged in to several sites at the same time. A malicious script in a tab, is thus more likely to succeed in performing malicious authenticated requests on behalf of the user.

Of course this is not a unique problem to tabbed browsing. When using the "File->Open new window" in IE6, the two windows would also share their session cookies. If opened from the start menu though, the new IE6 instance would be a completely separate process, and the two windows would not share their session cookies.

More information
Update 24.05.07: Ronald van den Heetkamp has a written an article about XSRF here
Tanned

Tabbed browsing and XSRF

I am a newbie, so have patience. I am confused by your comment -

"Tabbed browsing actually makes XSRF more likely to succeed. The reasoning here is that all tabs share the same set of session cookies (session cookies are cookies that are deleted when the browser is closed), and users tend to be logged in to several sites at the same time. A malicious script in a tab, is thus more likely to succeed in performing malicious authenticated requests on behalf of the user."

- My confusion is from my understanding that each web server will create it's own sessionID and will send it to the browser. Therefore, each open browser window on a machine will store a different session id as cookie. How would different tabbed windows share the same set of cookies?
Erlend

Re: Tabbed browsing and XSRF

That's a very good question. The reasoning is this:
As you say each application will issue its own SessionID, and these are usually stored in cookies. The sessions are usually only valid for a certain amount of time. If the user is idle for too long, the session is deleted and the user is required to login again. Theses cookies are specific to the domain/hostname of the application (specified by the cookie), and they are thus not shared between applications on different servers.
A user using a "non-tabbed" browser, will most likely surf one site, and then move on to the next. The sessions for the sites he visisted a while ago, will become idle and in the end deleted. Also many users log out, before moving on to the next server, and the session is deleted upon logout.
A user using a tabbed browser is more likely to surf several sites at the same time. Because of this he will have sessions to many of the sites he is surfing at the same time. So if one site performs an XSRF attack against another, and the user is surfing those sites at the same time, the attack is likely to succeed, because he still has a valid session. An XSRF attack against a site the user visited so long ago that the session has been deleted, will most likely not succeed.
Does this make things clearer?
Comments closed for this post