What is it and why should I care?
Cross Site Request Forgery (CSRF) is an attack wherein a victim is forced to execute unknown and/or undesired requests to a website at which he/she is currently authenticated. It exploits the fact that the “credentials” needed to perform a function on a website are generally loaded into a client-side cookie, which is transmitted automatically with every request. By exploiting this fact, an attacker can cause a victim to execute almost any request that isn’t protected against CSRF.
Here is a simple image that shows a basic CSRF attack. The steps are:
Step 1. The victim is lured to visit an evil site (evil.com)
Step 2. The victim’s browser loads the evil site, which contains a hidden image whose src points at an important transaction on good.com)
Step 3. The victim’s browser executes the transaction at good.com, passing along the session cookie (general authn/z mechanism).
Step 4. The transaction occurs, and the victim is not aware until later, if at all.
What should I do about it?
Now that we know what CSRF is and why it is dangerous, let’s consider some possible solutions.
The classic solution to CSRF has been a per-session token (known as the synchronizer token design pattern). The basic flow is:
Step 1. User logs in and a randomized string (token) is placed in the user session
Step 2. On every form for a non-idempotent request (meaning essentially any request that changes server-side state – should be your HTTP POSTs), place the token in the form when it’s submitted.
Step 3. On the request handler for the non-idempotent request, validate that the submitted token matches the token stored in the session. If either is missing or they don’t match, do not process the transaction.
This solution has served pretty well for most situations over the years, but can be time-consuming to implement and often creates opportunities for forgetting validation on some requests.
A very good option with solid protection is the OWASP CSRFGuard project. This library makes it relatively simple to include CSRF protection into your application by simply mapping a filter and updating a configuration file. This is certainly a resource worth checking out.
Stateless CSRF Protection
One more thing I’d like to point out is some interesting work John Wilander (@johnwilander) is doing in the area of stateless CSRF protection. In the case where you can’t or don’t want to maintain the user token in server-side session state, John proposes a seemingly novel solution. The proposal is to allow the client side to create a cookie with the CSRF token (which gets submitted on every request) and to include the token as a request parameter. Since an attacker can’t read both the cookie and request parameter, all the server side should have to do is validate that the token in the cookie and the request parameter match. This solution, to my knowledge, has not been widely reviewed or tested, but it is a great example of an elegant solution to a difficult problem. Only time will tell if this is the go-forward solution for stateless CSRF protection.
CSRF is a popular and dangerous attack, but with the protections described above, it is certainly manageable.
One last note here is that the token approach (classic or stateless) does break down when the site it is deployed on contains XSS (Cross Site Scripting) vulnerabilities. If an attacker can XSS your site, they can read the content and extract out the token you’re using, effectively nullifying the protection. The lesson is simple: fix those XSS bugs too!