CSRF-protection

CSRF protectie is een beveiliging dat niet iedereen via andere websites een POST kan doen op formulieren van jou website. Dit geeft meer veiligheid tegen hackers.

Alle ins en outs over CSRF protectie kan je hier lezen.

We gaan onze eigen CSRF protectie inbouwen in onze site. Daarvoor moeten we bij elke POST request een controle doen of deze van onze site afkomstig is. Dit doen we door aan elk formulier een de volgende code toe te voegen

<form method="post">
    <?= csrf() ?>
 
   ... 
</form>

We gaan een nieuw bestand maken csrf.php en voegen een require toe aan index.php. Let op dat je dit doet nadat de functions.php wordt toegevoegd.

//csrf protectie
require "csrf.php";

functions.php

Dit bestand krijgt twee nieuwe functies. Een functie om de token te maken en toe te voegen aan het formulier. En een functie om te kijken of een meegestuurde token geldig is.

//valideren van een token
//valideren van een token
function validateToken(): bool
{
    if (in_array($_POST['_token'] ?? '', $_SESSION['tokens'] ?? [])) {
        $_SESSION['tokens'] = []; //alle tokens wissen, zodat ze niet hergebruikt kunnen worden
        return true;
    }
    if (isset($_SERVER['HTTP_X_CSRF_TOKEN'])) {
        if ($_SERVER['HTTP_X_CSRF_TOKEN'] == ($_SESSION['api_token'] ?? "")) {
            return true;
        }
    }
    return false;
}

//aanmaken van een token voor je formulier
function csrf($field = true): string
{
    $bytes = random_bytes(256);
    $token = bin2hex($bytes);
    $_SESSION['tokens'][] = $token;
    if ($field) {
        return "<input type=\"hidden\" name=\"_token\" value=\"$token\">";
    } else {
        return $token;
    }
}

csrf.php

Dit bestand doet een controle of er een POST is en roept de valideer functie aan.

Indien niet geldig zal het script de gebruiker een 401 error geven.

<?php

//CSRF protection
if ($_POST != null) {
    if (!validateToken()) {
        http_response_code(401);
        $error = "CSRF-token mismatch error.";
        require "view/401.view.php";
        die();
    }
}

 

status 401 view

Voeg een view/401.view.php toe met bijvoorbeeld onderstaande code

<?php
require "parts/header.view.php";
require "parts/menu.view.php";
?>
    <!-- hier de about pagina -->
    <div class="mx-auto max-w-7xl py-20 sm:px-6 lg:px:8">
        <h1 class="text-2xl font-bold  mb-4">401 Geen toegang: <?= $error ?? '' ?></h1>
        <p class="mt-2">
            <a href="/" class="text-indigo-800 hover:text-indigo-600">Ga terug naar home</a>
        </p>
    </div>
<?php
require "parts/footer.view.php";

 

Nu kan je de CSRF protectie makkelijk aan en uit zetten door wel of niet in je index een // voor require "csrf.php" te zetten

//csrf protectie
//require "csrf.php";