Cross-site request forgery (aka cross-site reference forgery) is a form of web application attack. The hacker tricks users through malicious requests into running tasks they do not intend to execute. The webserver needs a mechanism to determine whether a legitimate user generated a request via the user’s browser to avoid such attacks. A CSRF token helps with this by generating a unique, unpredictable, and secret value by the server-side to be included in the client’s HTTP request. When the subsequent request is made, the webserver validates the request parameter that contains the token and rejects those that don’t. The approach is commonly used to prevent CSRF attacks since it is almost impossible for the hacker to construct a complete, valid HTTP request to ambush a victim.
We discussed earlier how cross-site scripting vulnerabilities are among the most common forms of attacks involving the execution of malicious code on a victim’s browser. Though a CSRF may sound similar to XSS attacks, there are fundamental differences in how they are carried out.
This article discusses how a CSRF token works and its importance in application security.
Why Is a Valid CSRF Token Required?
CSRF tokens are recommended to be added to all state-changing requests and are validated on the back-end. Since only application servers and clients recognize the token, the backend must ensure the incoming request contains a valid CSRF token to avoid successful XSS or cross-site request forgery attacks.
The CSRF token is a secret value that should be handled securely to remain valid during cookie-based sessions. The token should be transmitted to the client within a hidden field in an HTML form, submitted using HTTP POST requests. As a best practice, verifying the origin of requests using standard headers is recommended. Additional measures should also identify and compare the source and target origin. If the origins match, the request is considered legitimate, while if they don’t, it indicates a cross-domain request and is discarded.
Significance of CSRF Tokens in Preventing Attacks
The CSRF token values contain significant entropy and are unpredictable since the generated tokens use a pseudo-random number generator, a static secret, and a seeded timestamp. In addition to this, tokens are different for each user and are stored only for an active user session. Security teams can improve the uniqueness of the token value by concatenating the output of the random number generator with a user-specific entropy and hashing the entire structure. This makes it substantially difficult for the hacker to guess the CSRF token based on a sample of tokens issued in earlier session cookies.
CSRF Tokens – How to Use
It is advisable to transmit the CSRF tokens within a custom request header in some applications. Though a token can be placed in the URL query string, this approach is considered unsafe since the query string is logged on multiple records on the server and client-side. However, the query string can be accessed on the screen within the client browser and can also be transmitted to the third-party applications within the HTTP referer header.
In addition to this, the CSRF token should be stored on the server-side application, which verifies every request that requires validation. The server-side application should ensure that valid requests include a token matching the value stored during the user’s active session. CSRF token validation should also be performed for all HTTP methods, including POST, PUT and DELETE.
How to implement CSRF Token in Java
Java applications lack innate protection against CSRF attacks. Therefore, the proposed implementation of CSRF tokens in Java involves using a filter and auxiliary classes that enable token creation, resource analysis, and the crafting of responses. One such solution is the Generic Stateless filter, which implements the double-submit cookie pattern to enable CSRF protection, and goes through the workflow as outlined below:
The filter is first defined in the java application’s web.xml
file as shown in the code snippet below:
<filter>
<filter-name>CSRFFilter</filter-name>
<filter-class>com.github.adriancitu.csrf.GenericCSRFStatelessFilter</filter-class>
<filter>
<filter-mapping>
<filter-name>CSRFFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The filter includes two optional initialization variables:
csrfHeadername
– the name of the header containing the token, andcsrfCookieName
– the identity of the cookie used to store the CSRF token.
For each HTTP request, the filter provides an instance of the ExecutionContext
class. This is a legacy Java object that contains the CSRF cookies, the HTTP request, and the response. The class also contains implementations of auxiliary classes (ResourceCheckerHook, ResponseBuilderHook
, and TokenBuilderHook
).
The filter first checks the requested HTTP resource’s protection status. There are three options:
MUST_NOT_BE_PROTECTED
MUST_BE_PROTECTED_BUT_NO_COOKIE_ATTACHED
MUST_BE_PROTECTED_AND_COOKIE_ATTACHED
For resources whose status is MUST_NOT_BE_PROTECTED
and MUST_BE_PROTECTED_BUT_NO_COOKIE_ATTACHED
, the filter first generates a cookie with a CSRF token provided by the TokenBuilderHook
class. For resources with the label MUST_BE_PROTECTED_AND_COOKIE_ATTACHED
, the filter checks the resource’s CSRF protection status using ResourceCheckerHook
then returns a response to the client using the ResponseBuilderHook
class.
Quick note: The code above is a reference sample and requires development teams to build further CSRF mitigation mechanisms in the source code.
How to implement CSRF Token in PHP
PHP is popular with Content Management Systems as it enables developers to create dynamic websites with interactive functionality. Therefore, it is essential to implement anti-CSRF protection in PHP contact/user input forms so that their post handlers can validate incoming requests against CSRF attacks. A typical workflow for the implementation of CSRF protection in PHP contact forms is as follows:
First, create a form footer script on the landing page that invokes SecurityService
– the PHP class generates the token and initiates the PHP session. SecurityService writes the token used to validate the requests and loads the token in a hidden field. A typical SecurityService.php
configuration would look similar to:
public function getCSRFToken()
{
if (empty($this->session[$this->sessionTokenLabel])) {
$this->session[$this->sessionTokenLabel] = bin2hex(openssl_random_pseudo_bytes(32));
}
if ($this->hmac_ip !== false) {
$token = $this->hMacWithIp($this->session[$this->sessionTokenLabel]);
} else {
$token = $this->session[$this->sessionTokenLabel];
}
return $token;
}
The PHP contact form is then rendered to input their details such as subject, message, name, and email. The form should also contain the generated token within a hidden field csrf-token
. Once the user clicks on the Submit button, the application performs a JQuery form validation, after which the parameters are posted to PHP.
Once the contact form is submitted, the form action executes a script that compares the embedded token with the one stored in the session. If the tokens match, the application will serve the user’s request. If not, PHP will acknowledge the user with an error message.
How to Implement CSRF Token in Django
Django offers a CSRF middleware tag out of the box, making it easy to enable protection against CSRF attacks. The sample workflow depicts how CSRF protection can be implemented within the framework:
In Django, CSRF middleware is enabled by default. If the developer overrides this setting, they should declare django.middleware.csrf.CsrfViewMiddleware
before any view to enable CSRF token validation.
For particular views, developers can invoke the csrf-protect
decorator. The decorator is used for views that insert the CSRF token in the output. The decorator’s configuration would look similar to:
from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect
@csrf_protect
def my_view(request):
c = {}
# ...
return render(request, "a_template.html", c)
Developers can enable protection for templates that use the POST form by including the csrf_token
tag within the <form>
element. This only applies to forms with an internal URL and not for POST forms targeting external URLs. For external URLs, the CSRF token tag can be invoked by using:
<form method="post">{% csrf_token %}
Besides this, it is also recommended to use RequestContext
to render the response within corresponding Django views.
How to Implement CSRF Token in Javascript
All Javascript frameworks come with default options to achieve CSRF protection. For instance, Express.js includes middleware known as csurf
, which helps to create and validate tokens. To enable CSRF protection using csurf
, follow the workflow below:
In the index.js
file, include the following code:
app.get('/', csrfProtection, (req, res) => {
res.render('index', { csrfToken: req.csrfToken() });
Following this, add a file index.ejs
to the views folder by using a configuration similar to:
<input type='hidden' name='_csrf' value='<%= csrfToken %>'>
<label for='name'> Name:</label>
<input type='text' name='name'>
<button type='submit'> Update </button>
</form>
The /
route in the main configuration file renders the csrfToken
variable in the index.ejs
template and interpolates the token in a hidden field. The request is added to the /profile
route when the user submits the form, which provides CSRF token validation. If this CSRF token is missing, the application returns an invalid CSRF token error.
How to Fix an invalid CSRF Token
The CSRF attack leads to the unauthenticated access of user sessions and has grave consequences. To prevent this type of attack, it is vital to ensure users post requests with valid tokens. Some common approaches to fix and prevent invalid tokens include:
- Use custom request headers
Adding CSRF tokens in a vulnerable application involves administrative tasks that lead to changes in the user interface and are often complex and problematic. As an alternative, security teams can build custom request headers that strengthen CSRF defense using the same-origin policy. The security policy rejects cross-origin requests while enforcing the restriction that custom headers can only be built in Javascript and can only be used within their origin.
- Utilize inbuilt and existing CSRF mitigation implementation
Most development frameworks include synchronizer token defenses built into the security suite designed to protect the entire application stack. If the framework in a team’s tech stack provides options to achieve CSRF protection by default, it is recommended to use those before attempting to craft a custom system. In most cases, inbuilt configurations offer a decent defense, which can be further strengthened to implement configurations based on the organization’s use case.
- Deploy UI-based CSRF Defense
Several mechanisms analyze a request method to prevent unauthorized actions through CSRF to filter legitimate requests from those that intend unwanted actions. Such include the CAPTCHA, re-authentication authentication mechanisms, and one-time tokens. While these offer strong defenses for input validation, they alter the user experience and should only be used for crucial security actions.
This article has already been published on https://crashtest-security.com/csrf-token-meaning/ and has been authorized by Crashtest Security for a republish.
Top comments (0)