Implementing XSRF Tokens
view all blogs...

Justin Bess :: June 5, 2018

Explaining XSRF

XSRF is a malicious attack, in which an unauthorized action is taken on behalf of a client, and the server trusts that command, as if it was authenticated. There are a number of possible ways that an attacker could hijack your session and attempt to make requests on your behalf. Some exploits may be available due to poor security of the application itself. A malicious user may take advantage of a poor comment field, which allows HTML image tags to be used, without doing some checks. Let’s take a look at an example

Let’s assume that the application has a button attached to a form event. This event logs a user out and the script for this is located at /logout.php and now let’s also assume that a user with malicious intent comments the following HTML.
<img src="/logout.php"></img>
As you can see, the image tag is not being used correctly here to load an image. Instead, it’s being used with the link to the logout script. When the browser loads the page, it will request the /logout.php page. When this happens, it will undoubtedly log the user out!

Defeating XSRF with Tokens

Now that you know what XSRF is, we’ll talk about the steps to prevent these types of malicious attacks. The most common approach to solve this issue, is the Synchronizer token pattern, also simply known by it’s acronym (STP). STP is a technique where a token that is purely random and unique is generated, and then validated on the server side of the application. If the token is purely random and unique, then an attacker can not figure out the token, or possibly generate a valid token for the request. An example in an HTML form field, may look similar to the following
<input type="hidden" name="xsrf-token" value="KbyUmhTLMpYj7CD2di7JKP1P3qmLlkPt" />

Creating the Token

There are many ways you can generate the token, I’ll only cover a PHP 7+ way, to give you an idea of how it works. There are a ton of stacks, and possible technologies that could be used for this, so it wouldn’t be worth writing out examples for all of them.

session_start();
if (empty($_SESSION['token'])) {
    $_SESSION['token'] = bin2hex(random_bytes(32));
}
$token = $_SESSION['token'];

Some notes to take away from this, is to not use md5(uniqid(rand(), TRUE)); This is because rand() is predictable and uniqid() only adds 29 bits of entropy. In addition, md5() itself does not add entropy, it only jumbles the data deterministically.

Comments