Articles

The month of PHP functions : protection against CSRF

  • Ecrit par Rodolphe Eveilleau
  • vendredi 13 avril 2007
Image pour le titre du contenu

Ce document est aussi disponible en français fr 



On webapps, one has often the need to uniquely identify some resource. This is the need for identifiers. Producing such a value may be tricky, and its unicity is always a problem. This is why PHP has the function uniqid()


Example n°1 :

<?php
 
 
 
   print $identifiant = <a href="http://www.php.net/uniqid" target="_self">uniqid()</a>;
 
 
 
   // Donne 461e5220837d7
 
 
 
?>
The result variable will containt a 13 char length string, based on the current microtime. This string will change slightly between two calls. As it is always changing, unicity is enforced. But it is always good to avoid such an identifier to be predictible. With this in mind, we may add a prefix (first argument), some more entropy (second argument, as true). Then, MD5() will finish the job.


Exemple n°2 :

<?php
 
 
 
 
 
    $identifiant = md5(uniqid(<a href="http://www.php.net/rand">rand()</a>, true));
 
 
 
  // Gives b5a984ae3f11836826325cc5cb6f1c08
 
 
 
 
 
?>

The result variable is now a 32 chars strings, which is difficult to guess. This approach is the recommanded practise, so as to make sure that the generated ID is truly unique.

Example n°3 :

La génération d'un identifiant unique peut vous permettre de sécuriser vos formulaires contre les CSRF. Le principe est de forcer le chargement unitial du formulaire en y posant un identifiant unique, qui sera vérifié lors de la soumission du formulaire.  L'exemple ci-dessous permet d'écrire des messages dans un fichier (livre d'or, par exemple).

<?php
 
 
 
 
 
    <a href="http://www.php.net/session_start">session_start()</a>;
 
 
 
 
 
    if (isset($_POST['message'])) 
 
    {
 
        if (isset($_SESSION['token']) &amp;&amp; $_POST['token'] == $_SESSION['token'])
 
        {
 
            $message = htmlentities($_POST['message']);
 
 
 
 
 
            $fp = fopen('./messages.txt', 'a');
 
            fwrite($fp, "$message<br />");
 
            fclose($fp);
 
        }
 
    }
 
 
 
 
 
    $token = md5(uniqid(<a href="http://www.php.net/rand">rand()</a>, true));
 
    $_SESSION['token'] = $token;
 
 
 
 
 
?>
 
 
 
 
 
<form action="livre_or.php" method="post">
 
    <input type="hidden" name="token" value="<?php echo $token; ?>" />
 
    <input type="text" name="message"><br />
 
    <input type="submit">
 
</form>
 
 
 
 
 
<?php
 
 
 
 
 
    readfile('./messages.txt');
 
 
 
 
 
?>
The token makes sure that the user actually use the form before submitting the message.

This is exmaple is extracted from the PHP security Guide, at this address :
http://phpsec.org/projects/guide/en/index.html

CSRF definition and illustrations are here : http://phpsec.org/projects/guide/fr/2.html#2.4

To be noted

  • uniqid() est disponible depuis PHP4
  • En PHP4, uniqid() attend un paramètre en entrée : un préfixe
  • Pour un identifiant uniquement chiffrés, prenez la partie fractionnaire de microtime()
< Précédent   Suivant >

Commentaires

Vous pouvez ajouter votre commentaire!


Vous devez vous connecter pour commenter