Get started with 33% off your first certification using code: 33OFFNEW

Demystifying Cross-Site Request Forgery (CSRF) attacks in PHP

3 min read
Published on 7th July 2023
Demystifying Cross-Site Request Forgery (CSRF) attacks in PHP

Cross-Site Request Forgery (CSRF) is a prevalent security threat in web applications today. It tricks unsuspecting users into executing unwanted actions on a web application in which they're authenticated. This article will demystify CSRF attacks, providing an in-depth explanation of how they occur and offering strategies to prevent them in PHP applications.

What are CSRF Attacks?

In a CSRF attack, an attacker tricks a victim into performing an action that the victim did not intend to do. If the victim is authenticated in a web application, the attack could lead to unwanted changes such as email alteration, password change, or even data theft.

How Does a CSRF Attack Work?

Imagine a scenario where a user is logged into their bank account and, without logging out, visits another website. This other website could have malicious scripts that send a request to the bank's website to transfer funds. The bank's website sees this request as coming from an authenticated user and proceeds with the transaction. That's a CSRF attack in action.

Preventing CSRF Attacks in PHP

PHP offers several strategies to combat CSRF attacks:

1. Synchronizer Token Pattern

This is the most common method to prevent CSRF attacks. The server generates a unique, unpredictable token for each session. This token is embedded and sent as a hidden field in every form that's presented to the user.

When the user submits a form, the server verifies the existence and correctness of this token. If the token is missing or incorrect, the request is rejected.

session_start();

// Generate CSRF token
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// Validate CSRF token
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
        // CSRF attack detected
        die('Invalid CSRF token');
    }
}

// Generate form with CSRF token
echo '<form method="POST" action="/process.php">';
echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">';
// the rest of your form fields go here
echo '</form>';

2. SameSite Cookies

The SameSite attribute in cookies provides some automatic defense against CSRF attacks if you're setting session cookies. There are three settings for SameSite: "Strict", "Lax", and "None". Setting SameSite to "Strict" or "Lax" can help prevent CSRF attacks.

session_start([
    'cookie_samesite' => "Strict",
]);

3. Double Submit Cookie

In this method, when a user visits a site, the site issues a cookie. For every subsequent request that the user makes, the site includes a request parameter with the same value as the cookie. The server then compares the cookie value with the request parameter. If they match, the request is legitimate.

session_start();

// Generate CSRF token
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    setcookie('csrf_token', $_SESSION['csrf_token']);
}

// Validate CSRF token
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if ($_COOKIE['csrf_token'] !== $_POST['csrf_token']) {
        // CSRF attack detected
        die('Invalid CSRF token');
    }
}

// Generate form with CSRF token
echo '<form method="POST" action="/process.php">';
echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">';
// the rest of your form fields go here
echo '</form>';

Although CSRF attacks are a potent security risk for web applications, PHP developers can employ several strategies to protect against them. As with all aspects of security, it's vital to keep your knowledge up-to-date and apply best practices to ensure that your applications remain secure.

Remember that security is a layered approach, and CSRF protection is just one aspect. Always consider other security practices like sanitizing input, using parameterized queries, and enforcing HTTPS.