Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 13-02-2015 17:52:28

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Purge/Réutilisation de jeton CSRF

Bonjour,

j'utilise l'élément CSRF un peu partout dans mon application pour protéger mes formulaires. J'ai remarqué un fonctionnement assez étrange, je m'explique :

Lorsque le CSRF est généré, il est ajouté au container de session CSRF dans un tableau.

1er fonctionnement étrange :

Ce tableau n'est jamais purgé, et au fur et à mesure de la navigation client, il grossit en conséquence...

2nd fonctionnement étrange :

L'expiration des éléments CSRF est contrôlé globalement par une seul date d'expiration (au niveau de la session).... Et cette date d'expiration est mis à jour à chaque requête cliente. Donc, si je ne dis pas de bêtises, tous les jetons générés sont encore valides (et donc réutilisable après le timeout csrf...).

Esct-ce un comportement normal ?



En espérant obtenir quelques éclaircissements... Merci d'avance

Hors ligne

 

#2 13-02-2015 18:09:44

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Re: Purge/Réutilisation de jeton CSRF

Dois-je utiliser un container de session avec un setExpireByHops(1) ?

Hors ligne

 

#3 16-02-2015 10:23:41

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Re: Purge/Réutilisation de jeton CSRF

up ? hmm

Hors ligne

 

#4 16-02-2015 14:01:08

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Purge/Réutilisation de jeton CSRF

Bonjour,

Si je comprend ton problème tu as fait un var_dump de

Code:

$_SESSION['Zend_Validator_Csrf_salt_date_csrf']

et tu à vu un truc dans ce genre ?

Code:

[lang=php]
object(Zend\Stdlib\ArrayObject)[292]
  protected 'storage' => 
    array (size=2)
      'tokenList' => 
        array (size=14)
          '8b9e280d8515a657b26da6b0610f420c' => string 'e111588b3e744863fe5350a504ffd341' (length=32)
          '30561dd35f2d3735fdf8f938cc234545' => string '196eb7cf952ee26f4a6089fe9896ab78' (length=32)
          '356fdcd6e1c879bd0a78be0f17fbdf7b' => string '160021bf8544ec9beca03831cc5cde0d' (length=32)
          'f4c6b3d882b47a8161dd0354bfe37573' => string '6eda10812c20514de49520a307d2f1fd' (length=32)
          'bd8557f782210ce50b95ace336946dd1' => string '826bd5a37a2bb90040dc5ed094d6141c' (length=32)
          '7e1d508ae52b7b0cee43c2631a021907' => string 'd5a7ed0dc0ec8c028d806ae92ce21e88' (length=32)
          '259d5c81b2bd1e0aed6f979a6332b194' => string 'e6b3516c0f132550efdc3d85c787ea09' (length=32)
          'ed4e79328987a3115577b8e7c30d389b' => string '6954481a77cff6e0cfa7a1168d4b3355' (length=32)
          'e2042ec3b0d055aa4e7678e1408c6ed4' => string '640718e9e865bb45ffae5c817a395f33' (length=32)
          '2fa552ec6fadd49b6792d449fe2f6490' => string '9d69779fe587f113bbad8e93412a1629' (length=32)
          'f4ee2ccb42481e3fb1306b9ba80c65cb' => string '8d3aabb1303f491d124d488c55065c5e' (length=32)
          'f72bdb0288fb4d12f22f9f026a71bcba' => string 'fb1c5540d951080f5801cbc808b21171' (length=32)
          'ee2e8900fbf0bc0f5b9dac584521b1fd' => string '6b285a3344fb377e9d5180884c7d9dc5' (length=32)
          '9be8ce55dee5137e1515af14aba4a28f' => string '9922c9fa3e75ce9bf4895da16344f113' (length=32)
      'hash' => string '9922c9fa3e75ce9bf4895da16344f113-9be8ce55dee5137e1515af14aba4a28f' (length=65)

ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#5 16-02-2015 17:37:01

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Re: Purge/Réutilisation de jeton CSRF

Voilà je suis partis de là. Mais jusque là, rien d'anormal...

Le problème que je vois, c'est que ces jetons ne sont jamais purgés ? et donc réutilisable tant que la session utilisateur existe ? On peut donc rejouer facilement les requêtes hmm ?

Hors ligne

 

#6 17-02-2015 07:57:06

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Purge/Réutilisation de jeton CSRF

Qu'ils ne soient pas purgé semble pas poser de problème puis-qu’a chaque page ou il y a un formulaire, le csrf est regénéré.
D'autre part, je pense qu'il y a dans ce hash une notion de timeout, puisque mes formaulaire expirent bien comme il faut.

En apparence il n'y as pas de problème pour moi.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#7 17-02-2015 10:27:10

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Re: Purge/Réutilisation de jeton CSRF

En fait, quand tu dis que le CSRF est régénéré, il est simplement ajouté à la ''tokenList''....

D'autre part, la notion de timeout sur les CSRF est global :

Code:

[lang=php]
array (size=2)
  '__ZF' => 
    array (size=3)
      '_REQUEST_ACCESS_TIME' => float 1424161015.5129
      'Zend_Validator_Csrf_salt_csrf' => 
        array (size=1)
          'EXPIRE' => int 1424161613
  'Zend_Validator_Csrf_salt_csrf' => 
    object(Zend\Stdlib\ArrayObject)[1034]
      protected 'storage' => 
        array (size=2)
          'tokenList' => 
            array (size=1)
              ...
          'hash' => string '98f389d35f6242dbf1da0d7d5eb11306-960865426b2e2f3c9b8f19ccae82b8fd' (length=65)

A chaque rafraîchissement de page, la variable 'EXPIRE' de $_SESSION['__ZF']['Zend_Validator_Csrf_salt_csrf'] est mise à jour...


Donc tous les jetons contenus dans le tableau 'tokenList' expirent à cette date...

Hors ligne

 

#8 17-02-2015 10:40:27

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Re: Purge/Réutilisation de jeton CSRF

En inspectant un peu le code, j'en ai déduis que pour avoir des éléments CSRF avec une date d'expiration propre, il faut déclarer une option 'name' différente pour chaque élément CSRF utilisé :

Code:

[lang=php]
$form->add(array(
     'type' => 'Zend\Form\Element\Csrf',
     'name' => 'csrf',
     'options' => array(
             'csrf_options' => array(
                     'timeout' => 600,
                     'name' => 'login_csrf' //différent dans chaque Form utilisé 
             )
     )
 ));

Mais ça ne répond pas à ma deuxième interrogation : pourquoi ces données de SESSION ne sont pas purgés... ? hmm

Hors ligne

 

#9 17-02-2015 10:56:20

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Re: Purge/Réutilisation de jeton CSRF

Pour la purge de ces élément j'ai pensé à utiliser un namespace de session particulier pour ces éléments csrf et définit un nombre maximal d'accès à 1...

Code:

[lang=php]
$session = new Container('CSRF');
$session->setExpirationHops(1);

$form->add(array(
     'type' => 'Zend\Form\Element\Csrf',
     'name' => 'csrf',
     'options' => array(
             'csrf_options' => array(
                     'timeout' => 600,
                     'name' => 'login_csrf' //différent dans chaque Form utilisé 
                     'session' => $session
             )
     )
 ));

Mais est-ce la bonne solution ? Est-ce que quelqu'un voit une meilleure solution ?
Je trouve étrange que ce ne soit pas prévu out-of-the-box dans ZF...

Hors ligne

 

#10 17-02-2015 11:35:07

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Purge/Réutilisation de jeton CSRF

Edit ton post la prochaine fois, plutôt que 3 post d'affilés.

Oui, lorsque je crée personnellement mes formulaires, je fais cela :

Code:

[lang=php]
        $this->add(
            array(
                'type' => 'Zend\Form\Element\Csrf',
                'name' => 'add_config_csrf',
                'options' => array(
                    'csrf_options' => array(
                        'timeout' => 600,
                        'message' => 'form_valid_600_csrf_flash_msg',
                    )
                )
            )
        );

        $this->setValidationGroup(
            array(
                'add_config_csrf',
        ));

Et dans la vue j'ajoute a mon formulaire la clé csrf correspondant au formulaire que je valide, si je dépasse le timeout, j'ai mon erreur csrf qui s'affiche
bien, n'oublie pas d' jouter le champ csrf dans le setValidation group.

Et y afficher dans ton controlleur comme suit :

Code:

[lang=php]
$csrfErrors = $form->getMessages('add_config_csrf');
                if (!empty($csrfErrors)) {
                    foreach ($csrfErrors as $errorCsrf) {
                        $this->flashMessenger()->setNamespace('warning')
                            ->addMessage($errorCsrf);
                    }
                }

et dans la vue d'ajouter

Code:

<?=$this->formHidden($this->form->get('add_config_csrf'));?>

De là, même si ta token list ne se vide pas, le csrf est lié a ton formulaire, il apparait en input hidden. Donc je pense que cette liste est juste un historique qui est vidé en fin de session. Il doit avoir une utilité quelque part, pour générer un hash unique peut être. Je t'avoue que j'en sais pas plus.

EDIT: pour ton container session CSRF avec le hops, je ne peux t'en dire plus. Désolé

Dernière modification par JGreco (17-02-2015 11:38:15)


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#11 17-02-2015 12:32:54

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Re: Purge/Réutilisation de jeton CSRF

Tout d'abord, merci pour tes réponses et ton temps.

En revanche je pense que tu n'a pas bien compris mon problème (ou que je m'explique très mal ^^)...
J'arrive très bien à faire fonctionner les jetons CSRF partout dans mon application et comme le suggère la documentation ZF2. Tout va bien jusqu'ici.

Mon problème est lié à la sécurité... et notamment à la non réutilisation des jetons périmés...

Imaginons que tes CSRF sont paramétrés avec un timeout de 600.
Va sur un formulaire de ton application, attends 500 secondes, puis va sur un autre formulaire et attends 500 secondes ==> ensuite réutilise le premier jeton qui a été généré ==> il est toujours valide (pourtant les 600 secondes sont dépassés) ...

C'est plus clair ? hmm

Hors ligne

 

#12 17-02-2015 12:58:13

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Purge/Réutilisation de jeton CSRF

J'ai testé ceci d'après ce que j'ai compris de ton soucis :

J'ai deux formulaires que j'ai paramétré avec un timeout de 30 secondes :

Test case 1 :

- Form1  est donc de 30 secondes je l'ai laissé expirer et validé le formulaire, mon message csrf est bien apparu.
J'ai relaissé expiré form1 et j'ai généré un autre formulaire form2 de 30 secondes également. Tout de suite après j'ai revalidé form1 et l'expiration était encore d'actualité.

Test case 2 :
- J'ai rafraichi form1 et 15 secondes après j'ai rafraichi form2, à la 32eme seconde j'ai validé form1 et csrf était en error.

Edit: En fait tu voudrais que je copie le csrf regénéré dans form2 dans le form1 qui as expiré (dans l'input hidden) ?


Est-ce que j'ai bien compris ton soucis ?

Dernière modification par JGreco (17-02-2015 13:00:53)


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#13 17-02-2015 14:34:22

mamelon
Nouveau membre
Date d'inscription: 13-02-2015
Messages: 9

Re: Purge/Réutilisation de jeton CSRF

Hum en fait c'est ça, sauf qu'il ne faut pas attendre l'expiration du token1...

Formulaire1 : 30 secondes de timeout
Formulaire2 : 30 secondes de timeout

TestCase :

Tu arrive sur le Formulaire1 (token1 est alors ajouté à ta tokenList), après moins de 30 secondes, tu vas sur le Formulaire2.
Arrivé sur le Formulaire2 (token2 est alors ajouté à ta tokenList), tu reste moins de 30 secondes et tu reviens sur le Formulaire1 en essayant d'utiliser le token1 ==> il est valide alors qu'il ne devrait pas.

Voilà en gros le problème...

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages