What is it and why should I care?
Cross-Site Request Forgery (CSRF) is an attack where victims are forced to execute unknown and/or undesired requests onto a website where those requests are currently authenticated. CSRF exploits the fact that the “credentials” needed to perform a function on a website are generally loaded into a client-side cookie, which is then automatically transmitted with every request. By exploiting this automatic transmission, an attacker can cause a victim to execute almost any request that is not protected against CSRF.
Below is a simple image that shows how a basic CSRF attack works:
The steps are:
Step 1. The victim is lured into visiting an evil site (evil.com)
Step 2. The victim’s browser loads the evil site, which contains a hidden image whose src points to an important transaction (on good.com)
Step 3. The victim’s browser executes the transaction at good.com, thus passing along the session cookie (general authn/z mechanism)
Step 4. The transaction occurs, but the victim is unaware until later – or perhaps never − that the transaction occurred
What should I do about this possibility?
Now that we know what CSRF is, and why it is so 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 using this solution is:
Step 1. When the user logs in, a randomized string (token) is then placed in the user session
Step 2. On every form for a non-idempotent request (essentially meaning any request that changes the server-side state – which should be your HTTP POSTs), the token is placed in the form when it is submitted
Step 3. The request handler for the non-idempotent request validates that the submitted token matches the token stored in the session. If either of the tokens is missing, or if they do not match, do not process the transaction
In the past, this per-session token solution has served pretty well for most CSRF situations, but it can be time-consuming to implement and it also creates opportunities for forgetting validation on some requests.
Another solution that uses the token pattern is the ESAPI project, which has built-in CSRF protection, However, ESAPI’s CSRF solution is tied to the authentication scheme. Here is a write-up about using ESAPI’s CSRF protection.
A very good option offering solid protection against CSRF is the OWASP CSRFGuard project. This library makes it relatively easy to build 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 share is some interesting work in the area of stateless CSRF protection. When you cannot – or do not want to – maintain the user token in the server-side session state, this is a seemingly novel solution. The idea is to allow the client side to create a cookie with the CSRF token (which is then submitted on every request), and to then include the token as a request parameter. Because an attacker can not read both the cookie and the request parameter, then all the server side should have to do is validate that the token in the cookie and the request parameter match on another. This solution, to my knowledge, has yet to be 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 definitely a popular and dangerous attack, but with the protections described above, it is certainly manageable.
One last note: The token approach (classic or stateless) will break down when the site on which it is deployed contains XSS (Cross-Site Scripting) vulnerabilities. If attackers can XSS your site, they can read the content and extract the token you are using; this will effectively nullify the protection you have established. The lesson is simple: Fix those XSS bugs, too!