Protecting Your Users Against CSRF

Cross-site request forgery (CSRF) vulnerabilities can be used to trick a user’s browser into performing an unwanted action on your site.

Risks

Prevalence Common
Rating prevelance on a298cccc3e525887223509d0e6fe9a464d7d7f60574014de1fe402608154d354 Rating prevelance on a298cccc3e525887223509d0e6fe9a464d7d7f60574014de1fe402608154d354 Rating prevelance on a298cccc3e525887223509d0e6fe9a464d7d7f60574014de1fe402608154d354
Exploitability Easy
Rating exploitability on 6b817c6c589f0911378579408b6cbfc6d82345849ae2da559b8d11602b9a987b Rating exploitability on 6b817c6c589f0911378579408b6cbfc6d82345849ae2da559b8d11602b9a987b Rating exploitability on 6b817c6c589f0911378579408b6cbfc6d82345849ae2da559b8d11602b9a987b
Impact Harmful
Rating impact on 48bdb4077813afe9762f27e229e64207ec59c3891a54a3adf931c2c91a6d99bd Rating impact on 48bdb4077813afe9762f27e229e64207ec59c3891a54a3adf931c2c91a6d99bd Rating impact on 48bdb4077813afe9762f27e229e64207ec59c3891a54a3adf931c2c91a6d99bd

Any function that your users can perform deliberately is something they can be tricked into performing inadvertently using CSRF. As we saw in our example, in the most malign cases, CSRF attacks can spread themselves as a worm.

CSRF attacks in the past have been used to:

It is hard to estimate the prevalence of CSRF attacks; often the only evidence is the malicious effects caused by the attack. CSRF is routinely described as one of the top-ten security vulnerabilities by OWASP.

Protection

Websites consist of a combination of client-side and server-side code. The client-side code is HTML and JavaScript that is rendered by and executed in the browser. This allows users to navigate to other URLs on your site, submit HTML forms to the server, and trigger AJAX requests via JavaScript. Your server-side code will intercept the data sent in the HTTP request, and act upon it appropriately.

These server-side actions can also be triggered by forged HTTP requests, unless you explicitly put in protective measures. A CSRF attack occurs when a malicious actor tricks a victim into clicking on a link, or running some code, that triggers a forged request. (This malicious code is typically hosted on a website owned by the attacker, on another domain – hence the “cross-domain” denomination.)

Protecting against CSRF (commonly pronounced “sea-surf”) requires two things: ensuring that GET requests are side-effect free, and ensuring that non-GET requests can only be originated from your client-side code.

REST

Representation State Transfer (REST) is a series of design principles that assign certain types of action (view, create, delete, update) to different HTTP verbs. Following REST-ful designs will keep your code clean and help your site scale. Moreover, REST insists that GET requests are used only to view resources. Keeping your GET requests side-effect free will limit the harm that can be done by maliciously crafted URLs–an attacker will have to work much harder to generate harmful POST requests.

Anti-Forgery Tokens

Even when edit actions are restricted to non-GET requests, you are not entirely protected. POST requests can still be sent to your site from scripts and pages hosted on other domains. In order to ensure that you only handle valid HTTP requests you need to include a secret and unique token with each HTTP response, and have the server verify that token when it is passed back in subsequent requests that use the POST method (or any other method except GET, in fact.)

This is called an anti-forgery token. Each time your server renders a page that performs sensitive actions, it should write out an anti-forgery token in a hidden HTML form field. This token must be included with form submissions, or AJAX calls. The server should validate the token when it is returned in subsequent requests, and reject any calls with missing or invalid tokens.

Anti-forgery tokens are typically (strongly) random numbers that are stored in a cookie or on the server as they are written out to the hidden field. The server will compare the token attached to the inbound request with the value stored in the cookie. If the values are identical, the server will accept the valid HTTP request.

Most modern frameworks include functions to make adding anti-forgery tokens fairly straightforward. See the code samples below.

The Google Chrome team added a new attribute to the Set-Cookie header to help prevent CSRF, and it quickly became supported by the other browser vendors. The Same-Site cookie attribute allows developers to instruct browsers to control whether cookies are sent along with the request initiated by third-party domains.

Setting a Same-Site attribute to a cookie is quite simple:

Set-Cookie: CookieName=CookieValue; SameSite=Lax;
Set-Cookie: CookieName=CookieValue; SameSite=Strict;

A value of Strict will mean than any request initiated by a third-party domain to your domain will have any cookies stripped by the browser. This is the most secure setting, since it prevents malicious sites attempting to perform harmful actions under a user’s session.

A value of Lax permits GET request from a third-party domain to your domain to have cookies attached - but only GET requests. With this setting a user will not have to sign in again to your site if the follow a link from another site (say, Google search results). This makes for a friendlier user-experience - but make sure your GET requests are side-effect free!

Include Addition Authentication for Sensitive Actions

Many sites require a secondary authentication step, or require re-confirmation of login details when the user performs a sensitive action. (Think of a typical password reset page – usually the user will have to specify their old password before setting a new password.) Not only does this protect users who may accidentally leave themselves logged in on publicly accessible computers, but it also greatly reduces the possibility of CSRF attacks.

Code Samples

Django

To enable CSRF protection in Django, configure your middleware appropriately. Then add anti-forgery tokens to your HTML forms in the following manner:


<form action="." method="post">
  {% csrf_token %}
</form>  

Tokens can be checked using a pre-processor, or manually.

Rails

Rails includes CSRF counter-measures out-of-the-box. Protecting against CSRF is usually as simple as adding the following snippet in your Rails controller:


protect_from_forgery with: :exception

Rails will handle the rest of the logic – CSRF tokens will be included in any HTML form, and validated when they are received back in non-GET requests.

OWASP has a standard library for CSRF protection in Java. If you need stateless sessions, review this example.

OWASP has a standard library for CSRF protection in .NET.

Express

The express/csurf library implements CSRF protection for Express.

OWASP has a description of how to implement CSRF protection in PHP.

Further Reading

Using the Same-Site Cookie Attribute to Prevent CSRF Attacks

Is your website vulnerable to CSRF?

Netsparker n 834848961a0bf6ec5556448ff47f421d0b1204a572877a59717064b1088e8c43 Check today. Scan your website for Cross-site Request Forgery and other vulnerabilities with the Netsparker Web Application Security Scanner.