Token , session et bug incompréhensible
Bonjour à tous,
J'ai une classe me permettant de générer des "token" pour sécurisé divers appel à des formulaire ou des appels ajax.
Je n'avais jusqu'à maintenant jamais eu de problème. Or je viens de tester la classe sur un hébergement mutualisé et là c'est le drame !
Le concept : On arrive sur un formulaire , un token est généré, stocké en session puis plaer dans un input hidden.
Après soumission du formulaire , je vérifie si le token en session est équivalent à celui passé dans le formulaire.
Le problème : La valeur en session est modifiée entre le clic sur le bouton d'envoi et l'apparition de la page du coup le token n'est jamais le bon.
J'ai retourné le code dans tous les sens mais rien à faire. Un petit exemple simplifié ou je rencontre le problème :
Token.class.php
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
class Util_Token
{
static public $error = 0;
static public function genToken($ttl = 15)
{
if(!isset($_SESSION))
throw new Exception("Une session doit être active");
$gentoken = hash('sha1',uniqid(rand(),true));
$rand = rand(1,20);
$gentoken = substr($gentoken,$rand,20);
$ttl *= 60;
$_SESSION['csrf_protect'] = array('token'=>$gentoken,'ttl'=>$ttl);
return $gentoken;
}
static public function checkToken()
{
if(!isset($_SESSION))
throw new Exception("Une session doit être active");
if($_REQUEST['csrf_protect'] == $_SESSION['csrf_protect']['token'])
return true;
else
return false;
}
} |
index.php
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| session_start();
require('Token.class.php');
if(!empty($_POST) || !empty($_GET))
{
echo 'Recu Form : '.$_POST['csrf_protect'].'<br />';
echo 'Connu Session : '.$_SESSION['csrf_protect']['token'].' ttl : '.$_SESSION['csrf_protect']['ttl'].'<br />';
}
else
{
$token = Util_Token::genToken();
echo 'Généré : '.$token;
?>
<form action="index.php" method="post">
<input type="text" value=" TEst" name="testtext">
<input type="hidden" value="<?php echo $token; ?>" name="csrf_protect">
<input type="submit" value="envoi" />
</form>
<?php
}
?> |
En remplacant la chaine aléatoire du token par une date (H:i:s) j'ai remarqué que sur le serveur mutualisé il y'avais 1 sec de décalage entre la date recu et la date en session.
Note : En local je n'ai pas de problème avec ce code...