CSRF protection

Inleiding

Wanneer we een formulier hebben (kan ook alleen een button zijn) om een 'Post' te verwijderen is er ook een url beschikbaar om dat te doen bv. http://localhost/posts-destroy/4

Bij het volgen van de link zal 'Post' met id=4 worden verwijderd. 

Ook buiten onze website kunnen nu 'Posts' verwijderd worden. Het zou dus mogelijk zijn om vanaf een andere website een post in onze database te verwijderen. Dit is een beveiligingsrisico. Een oplossing daarvoor is een CSRF token.

 

CSRF token

Elke wijziging in de database zou alleen verstuurd moeten worden d.m.v.een method="post". In het formulier kunnen we dan een CSRF-token opnemen. Dit is een lange reeks tekens die door het framework wordt gemaakt en wordt opgeslagen in een SESSION. Op het moment dat het formulier naar onze website wordt verstuurd zal het framework controleren of dit een geldige token is. Zo ja, dan zal doorverwezen worden naar de controller. Zo niet dan zal het verzoek afgewezen worden. Deze token controle voeren we dan ook alleen uit bij verzoeken via een POST. Alles via GET laten we altijd door.

 

Beschikbaar hiervoor zijn de functies csrf() en validateToken().

 

Gebruik van CSRF tokens

Alleen bij POST

Aan elk formulier dat wordt verstuurd met POST moet een csrf token worden toegevoegd om het te laten werken. Anders krijg je de boodschap:

401 Geen toegang: CSRF-token mismatch error.

Een CSRF-token toevoegen is vrij eenvoudig

<?= csrf() ?>

De code voor de volledige verwijder button wordt dan:

<form method="post" action="/posts-destroy/<?= $post['id'] ?>">
  <?= csrf() ?>
  <input type="submit" value="Verwijder" name="delete" class="border border-1 rounded-md px-2 py-1 hover:bg-gray-100 cursor-pointer">
</form>

Het is nu niet meer mogelijk om met externe scripts posts te verwijderen.

De <?php csrf() ?> zal worden vervangen door een verborgen input veld met als name="_token" en als value een flink lange reeks willekeurige letters en getallen.

<form action="/posts-store" method="post">
    <input type="hidden" name="_token" value="b754d4e0eae5154d8470acd177561d6f6e23289e349e7682bd6e4dc5cc6b176c586047e94fbef8b6adb8eda6d32d5b7c1d3c9ffc821140487117725b6235b58f8372d54789d993d4535870af23019feb1ab2a983648453b93fe527cb0bb7bc15e4a2fc57adec0fdcfd225cac3a71db52d65dd72d6237f93bf32d8f925a515a16fe48641a2786fa9eabcc4b4bf1d75a56e4b02b0a0481f0b177744a80b4785e72f946f7224ac62799769efbbe134274ebd005765546eaf4a8721f117032f58ac6ec367a9c1afdac8951d541552ee36ff104904d56b902334651928148005dc7fded2896ee061ffe018d1c19e973a3b31fda80c43b8b2a4c0383e35106c6ce8b83">            <input type="text" name="title" placeholder="Titel" required="" value=""><br>

Als je meer wilt weten over csrf protectie kan je dat  hier lezen.