Cross-Site Request Forgery (CSRF) is a malicious exploit where an attacker tricks a user into submitting a request that they did not intend to make. This typically occurs when a user is logged into a web application and the attacker sends a request that performs actions on behalf of the user, such as changing account settings or making transactions.
How CSRF Works
To illustrate how CSRF works, consider the following scenario:
- A user logs into their online banking account.
- The user then visits a malicious website while still logged in.
- The malicious website contains a hidden form that submits a request to transfer funds from the user’s account to the attacker’s account.
- Since the user is authenticated, the request is processed by the bank’s server, resulting in an unauthorized fund transfer.
Prevention Techniques
Preventing CSRF attacks requires implementing several strategies. Here are some effective methods:
- CSRF Tokens: One of the most common methods to prevent CSRF is by using CSRF tokens. A unique token is generated for each user session and included in forms. The server validates this token upon form submission. Here’s a simple example in PHP:
// Generate a CSRF token
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
In your HTML form, include the token as a hidden field:
<form method="POST" action="submit.php">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<!-- Other form fields -->
<input type="submit" value="Submit">
</form>
On the server side, validate the token:
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("CSRF token validation failed.");
}
2. SameSite Cookies: Modern browsers support the SameSite
attribute for cookies, which can help mitigate CSRF attacks. By setting the SameSite
attribute to Strict
or Lax
, cookies will not be sent along with cross-site requests.
setcookie("session_id", $sessionId, [
'expires' => time() + 3600,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax' // or 'Strict'
]);
3. Custom Request Headers: Another approach is to require custom headers for state-changing requests. This can be implemented using JavaScript to set a custom header, which the server checks for validity.
fetch('/api/endpoint', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken // Custom header
},
body: JSON.stringify(data)
});
On the server side, validate the presence of this header:
if ($_SERVER['HTTP_X_CSRF_TOKEN'] !== $_SESSION['csrf_token']) {
die("CSRF token validation failed.");
}
4. User Education: Educating users about the risks of CSRF and encouraging them to log out of sensitive applications when not in use can also help mitigate risks.
CSRF is a significant security threat that can lead to unauthorized actions on behalf of users. By implementing CSRF tokens, utilizing SameSite cookies, requiring custom request headers, and educating users, developers can effectively protect their applications from these types of attacks. Always remember that security is an ongoing process, and staying informed about the latest vulnerabilities and mitigation strategies is essential for safeguarding web applications.
Happy coding… 🙂
I’ve been designing web applications—on and off—since 2001, back when animated GIFs were all the rage and ‘responsive design’ meant answering your client’s emails. Over the past 14 years, I’ve kept pace with the ever-evolving trends in PHP development, successfully delivering a variety of projects that made my clients happy (and kept me caffeinated).
This website serves as my soapbox—a place to share the insights I’ve picked up along the way with anyone curious enough to dive in. Welcome aboard!
Need some custom work done? Or, just want to reach out? Email: dan@danoriordan.com