Anti-CSRF tokens

CSRF attacks are possible because the attacker knows which request parameter values to send to the target website.

In fact, for an CSRF attack to be successful, the CSRF link or redirect must provide the website with the correct parameters and values.

This fact tells us how to defend against CSRF: make sure that the attacker does NOT know all the correct parameter values.

An implementation of this concept is to require a specific, secret request parameter with each request. This parameter is called security token.

The value of this token must be known to the legitimate user only.

Let's see how this technique works.

Anti-CSRF tokens

To defend against CSRF attacks, your web application must require a security token from the user before allowing any operation.

Let's go back to the user.php example.

A new input value named "csrf_token" is added to the form. This input contains the security token.

The token itself is created as a random string, so there is no way to guess it.

The token is also stored inside the user's Session.

Here is the PHP code:

Each time the user.php page is accessed, a new random token will be created and included in the form like this:

When the form is submitted, the back-end must check that the token sent with the form matches the one saved inside $_SESSION.

If there is no match, the operation is not allowed:

Since the token is generated when the authenticated user accesses user.php, there is no way for the attacker to retrieve it. Even if the attacker obtains a token, it will not be able to use it for other requests.

Note that the token must be included in any request sent to the server, including JavaScript and AJAX-based ones (you will find more details in the next lesson).

Token generation

The anti-CSRF token should be cryptographically secure so that attackers cannot "guess" it.

The simplest way to generate it is to use the random_bytes() and bin2hex() PHP functions.

The previous example uses a 16 bytes value, which is usually enough (since the token is used once and then discarded).

However, you can also use a bigger value, for example a 32 bytes token:


Lesson takeaways

  • Anti-CSRF tokens are an effective defense against CSRF attacks.
  • Every request must include the dynamically generated token. If the token doesn't match, the request must be denied.
  • The token must be cryptographically secure. You can generate it with random_bytes() and bin2hex().

Complete and Continue