Php Token Anti CSRF

Résolu
Patate -  
 Patate -

Bonjour, me revoilà avec mes tokens anti CSRF je déploie ces tokens sur tous les formulaires de mon appli et là je rencontre l'erreur undefined index sur mes tokens.

Je m'explique : dans ma vue qui contient mon formulaire je génère un token et je met un champ caché dans le formulaire qui prend pour valeur le token.

<?php
ob_start();
$token = generer_token('mail_rs');   //Je génère mon token
?>

<form method="POST" enctype="multipart/form-data" action="<?= URL ?>rs/mailRsValid">
    <div class="row">
        <div class="form-group col-6 p-2">
            <label for="depot_de_plainte">Liste de diffusion</label>
            <select class="form-control" name="id">
                <?php
                for ($i = 0; $i < count($rs2); $i++) : ?>
                    <option value="<?php echo htmlentities($rs2[$i]->getId()); ?>"><?= htmlentities($rs2[$i]->getNom()); ?> </option>
                <?php endfor; ?>
            </select>
        </div>
        <div class="form-group col-6 p-2">
            <label for="travaux">Action en cours</label>
            <select class="form-control" name="actions">
                <?php
                for ($i = 0; $i < count($actions); $i++) : ?>
                    <option value="<?php echo htmlentities($actions[$i]->getDescriptionAction()); ?>"><?= htmlentities($actions[$i]->getDescriptionAction()); ?> </option>
                <?php endfor; ?>
            </select>
        </div>


        <div class="form-group col-6 p-2">
            <label for="formFile" class="form-label">Ajout de fichier(s)</label>
            <input class="form-control" name='fichier' id='fichier' type="file">
        </div>

        <div class="form-group col-6 p-2">
            <label for="tech" class="form-label">Tech</label>
            <select class="selectpicker " multiple aria-label="multiple select example" id="cmblmail" name="cmbl[]" data-size="8" data-width="100%" multiple data-live-search="true" data-actions-box="true" title="" data-style="btn-white border">
                <optgroup label="Normandie">
                    <?php for ($i = 0; $i < count($cmbl); $i++) {
                        if ($cmbl[$i]->getZone() == "Normandie") { ?>
                            <option value="<?= $cmbl[$i]->getNom() ?>"><?= $cmbl[$i]->getNom() ?></option>
                        <?php } ?>
                    <?php } ?>
                </optgroup>
                <optgroup label="Centre-Val de Loire">
                    <?php for ($i = 0; $i < count($cmbl); $i++) {
                        if ($cmbl[$i]->getZone() == "Centre-Val de Loire") { ?>
                            <option value="<?= $cmbl[$i]->getNom() ?>"><?= $cmbl[$i]->getNom() ?></option>
                        <?php        } ?>
                    <?php        } ?>
                </optgroup>
            </select>
        </div>
        <div class="form-group col-6 p-2">
            <label  class="form-label">Ajout derco ou ticket père</label>
            <input class="form-control" name='derco'  type="text">
        </div>
    </div>
    <input type="hidden" name="ville" value="<?= htmlentities($rs->getVille_id()); ?>">
    <input type="hidden" name="cable" value="<?= htmlentities($rs->getTypeDeCables()); ?>">
    <input type="hidden" name="type" value="<?= htmlentities($rs->getTypeAlerte()); ?>">
    <input type="hidden" name="datefin" value="<?= htmlentities($rs->getDateDeRetablissement()); ?>">
    <input type="hidden" name="date" value="<?= htmlentities($rs->getDatesHeuresAlarme()); ?>">
    <input type="hidden" name="pilote" value="<?= htmlentities($rs->getPilote()); ?>">
    <input type="hidden" name="nb_de_clients_impactes" value="<?= htmlentities($rs->getNbDeClientsImpactes()); ?>">


    <div class="form-group col-md-8">
        <br>
        <button type="submit" class="btn btn-primary bouton border-0" id="baseN2" data-mdb-ripple-color="dark" data-bs-toggle="modal" data-bs-target="#referencer">Envoyer</button>
    </div>
    <input type="hidden" name="token" id="token" value="<?php echo $token; ?>"/>    // Mon champ caché qui a pour valeur le token 
</form>
<?php
$content = ob_get_clean();
$titre = "Envoi de mail - " . htmlentities($rs->getTypeAlerte());
require "views/template.php";
?>

Dans une autre page php (RsManager.class.php) qui gère ici l'envoi d'un mail je met une condition pour vérifier que mon token est valide

public function mailRsBd($id, $ville, $cmbl, $fichier) {

if(verifier_token(600, 'http://localhost/portail/rs/mailrs/' . $id, 'mail_rs')) 
{
  //Requete sql qui permet de sélectionner un utilisateur 
  //Création du mail 
  //Envoi du mail 
}
else { // Pour afficher mes messages d'erreurs 

            var_dump($_SESSION['mail_rs']);
            echo '<br><br>';
            var_dump($_POST['token']);
            echo '<br><br>';
            var_dump($_SESSION['mail_rs_time']);
            echo '<br><br>';
            echo time();
            echo '<br><br>';
            var_dump($_SERVER['HTTP_REFERER']);
            echo '<br><br>';
            if(isset($_SESSION['mail_rs']) && isset($_SESSION['mail_rs_time']) && isset($_POST['token'])){
                if($_SESSION['mail_rs'] == $_POST['token']){
                    if($_SESSION['mail_rs_time'] >= (time() - 600)){
                        if($_SERVER['HTTP_REFERER'] == 'http://localhost/portail/rs/mail/59'){
                            echo 'token bien vérifié';
                        }
                        else{
                            echo 'problème avec http_referer != http://localhost/portail/rs/mail/59';
                        }
                    }
                    else{
                        echo 'problème avec le time';
                    }
                }
                else{
                    echo '$_SESSION["mail_rs_token"] != $_POST["token"]';
                }
            }
            else{
                echo 'mail_rs, mail_rs_time, token ne sont pas tous isset';
            }
 
        }
}

Les fonctions verfier_token et generer_token dans mon index.php

function generer_token($nom = '')
{
	
	$token = uniqid(rand(), true);
	$_SESSION[$nom.'_token'] = $token;
	$_SESSION[$nom.'_token_time'] = time();
	return $token;
}

function verifier_token($temps, $referer, $nom = '')
{

    if(isset($_SESSION[$nom.'_token']) && isset($_SESSION[$nom.'_token_time']) && isset($_POST['token'])){
        if($_SESSION[$nom.'_token'] == $_POST['token']){
            if($_SESSION[$nom.'_token_time'] >= (time() - $temps)){
                if($_SERVER['HTTP_REFERER'] == $referer){
                    return true;
                }
            }
        }       
    }
    else{
        return false;
    }    
}

Et les message d'erreurs :

Notice: Undefined index: mail_rs in C:\Applications\wamp64\www\portail\models\RsManager.class.php on line 893
NULL

string(31) "31792904637cc5e35b3ca3.88068889"


Notice: Undefined index: mail_rs_time in C:\Applications\wamp64\www\portail\models\RsManager.class.php on line 897
NULL

1669121518

string(43) "http://localhost/portail/rs/mailrs/59"

mailRs_token, mailRs_token_time, token ne sont pas tous isset

Comment avoir accès à mon token générer dans ma vue ?

3 réponses

  1. jordane45 Messages postés 30427 Date d'inscription   Statut Modérateur Dernière intervention   4 832
     

    Bonjour,

    Dans ton fichier RsManager.class.php, à la ligne , fais donc des var_dump de $_POST et de $_SESSION ... et regarde ce que ça t'affiche...


    0
    1. Patate
       

      Merci de ton retour, 

      var_dump($_POST)

      array(12) { ["id"]=> string(2) "31" ["actions"]=> string(13) "AUCUNE ACTION" ["cmbl"]=> array(1) { [0]=> string(16) "Guy" } ["derco"]=> string(5) "DERCO" ["ville"]=> string(28) "Le Desert - - 14 - Calvados" ["cable"]=> string(6) "électrique" ["type"]=> string(7) "Dommage" ["datefin"]=> string(10) "2022-11-23" ["date"]=> string(10) "2022-11-22" ["pilote"]=> string(13) "Guy" ["client_impacte"]=> string(3) "100" ["token"]=> string(33) "2030131701637dcb9aba3957.86973164" }
      
      

      var_dump($_SESSION)

      array(7) { ["connexion_token"]=> string(33) "2128277159637dca42944d97.16366661" ["connexion_token_time"]=> int(1669188162) ["profil"]=> array(7) { ["login"]=> string(8) "AAAA2727" ["bd"]=> string(1) "1" ["dist"]=> string(1) "1" ["admin"]=> string(1) "1" ["demande"]=> string(1) "1" ["pilote"]=> string(1) "1" ["rs"]=> string(1) "1" } ["create_rs_token"]=> string(33) "2125239567637dcb963a2949.53656776" ["create_rs_token_time"]=> int(1669188502) ["mail_rs_token"]=> string(33) "2030131701637dcb9aba3957.86973164" ["mail_rs_token_time"]=> int(1669188506) } 

      On peut voir que j'ai bien mes deux token de mail pourtant : 

       ["mail_rs_token"]=> string(32) "700426528637dce26774477.88740088" ["mail_rs_token_time"]=> int(1669189158) 
      0
    2. jordane45 Messages postés 30427 Date d'inscription   Statut Modérateur Dernière intervention   4 832 > Patate
       

      Et maintenant, regarde la ligne correspondant à tes messages d'erreur .... (compare le nom des variables avec ceux que tu as en session... )

      0
    3. Patate > jordane45 Messages postés 30427 Date d'inscription   Statut Modérateur Dernière intervention  
       

      Si tu fais allusion à 

      ["mail_rs_token"]

      comparé à  

      if(verifier_token(600, 'http://localhost/portail/rs/mailrs/' . $id, 'mail_rs')) 

      C'est normal sur tous mes autres token c'est pareil et ça fonctionne, si tu regarde ces deux fonctions : 

      function generer_token($nom = '')
      {
      	
      	$token = uniqid(rand(), true);
      	$_SESSION[$nom.'_token'] = $token;
      	$_SESSION[$nom.'_token_time'] = time();
      	return $token;
      }
      
      function verifier_token($temps, $referer, $nom = '')
      {
      
          if(isset($_SESSION[$nom.'_token']) && isset($_SESSION[$nom.'_token_time']) && isset($_POST['token'])){
              if($_SESSION[$nom.'_token'] == $_POST['token']){
                  if($_SESSION[$nom.'_token_time'] >= (time() - $temps)){
                      if($_SERVER['HTTP_REFERER'] == $referer){
                          return true;
                      }
                  }
              }       
          }
          else{
              return false;
          }    
      }

      J'ai quand même essayé ça pour être sur mais ça ne fonctionne pas : 

      if(verifier_token(600, 'http://localhost/portail/rs/mailrs/' . $id, 'mail_rs_token')) 
      0
    4. jordane45 Messages postés 30427 Date d'inscription   Statut Modérateur Dernière intervention   4 832 > Patate
       

      Il faut bien garder mail_rs dans l'appel de ta fonction

      ¨Par contre, je parlais des messages d'erreurs liés à tes var_dump .. pas du fonctionnement de ta fonction.

      Pour ta fonction, ajoutes y des else et du debug pour comprendre ce qui n'est pas bon.

      par exemple

      function verifier_token($temps, $referer, $nom = 'mail_rs')
      {
        $s_token = !empty($_SESSION[$nom.'_token']) ? $_SESSION[$nom.'_token'] : NULL;
        $s_token_time = !empty($_SESSION[$nom.'_token_time']) ? $_SESSION[$nom.'_token_time'] : NULL;
        $p_token = !empty($_POST['token']) ? $_POST['token'] : NULL;
        
        
          if( $s_token && $s_token_time && $p_token ){
              if($s_token == $p_token){
                  if($s_token_time >= (time() - $temps)){
                      if($_SERVER['HTTP_REFERER'] == $referer){
                          return true;
                      }else{
                        echo "SERVER['HTTP_REFERER'] != referer ";
                        echo "<br>" . $_SERVER['HTTP_REFERER'] ;
                        echo "<br>" . $referer ;
                      }
                  }else{
                    echo "<br>" . " s_token_time < temps " . $s_token_time . "-".$temps;  //le temps du debug
                  }
              } else{
                echo "<br>" . "Variables session et post différentes! "; //le temps du debug
              }
          } else{
            echo "<br>" .  "Variables non renseignées ! "; //le temps du debug
          } 
      
           return false; // si aucune condition bonne
      }
      0
    5. Patate > jordane45 Messages postés 30427 Date d'inscription   Statut Modérateur Dernière intervention  
       

      J'ai changé ma fonction par la tienne, 

      Voici le résultat : 

      SERVER['HTTP_REFERER'] != referer
      http://localhost/portail/rs/mailrs/59
      http://localhost/portail/rs/mailrs/31
      Notice: Undefined index: mail_rs in C:\Applications\wamp64\www\portail\models\RsManager.class.php on line 893
      NULL
      
      string(33) "1386178879637e2a4432d304.93825408"
      
      
      Notice: Undefined index: mail_rs_time in C:\Applications\wamp64\www\portail\models\RsManager.class.php on line 897
      NULL
      
      1669212749
      
      string(43) "http://localhost/portail/rs/mailrs/59"
      
      array(12) { ["id"]=> string(2) "31" ["actions"]=> string(13) "TOUJOURS RIEN" ["cmbl"]=> array(1) { [0]=> string(16) "Guy" } ["derco"]=> string(4) "TEST" ["ville"]=> string(28) "Le Desert - - 14 - Calvados" ["cable"]=> string(6) "electrique" ["type"]=> string(7) "Dommage" ["datefin"]=> string(10) "2022-11-23" ["date"]=> string(10) "2022-11-22" ["pilote"]=> string(15) "Guy" ["nb_de_clients_impactes"]=> string(3) "100" ["token"]=> string(33) "1386178879637e2a4432d304.93825408" }
      
      array(17) { ["connexion_token"]=> string(33) "2128277159637dca42944d97.16366661" ["connexion_token_time"]=> int(1669188162) ["profil"]=> array(7) { ["login"]=> string(8) "AAAA2727" ["bd"]=> string(1) "1" ["dist"]=> string(1) "1" ["admin"]=> string(1) "1" ["demandevalidation"]=> string(1) "1" ["pilote"]=> string(1) "1" ["rs"]=> string(1) "1" } ["create_rs_token"]=> string(33) "2125239567637dcb963a2949.53656776" ["create_rs_token_time"]=> int(1669188502) ["mail_rs_token"]=> string(33) "1386178879637e2a4432d304.93825408" ["mail_rs_token_time"]=> int(1669212740) ["create_user_token"]=> string(33) "1554851162637dd12b178e18.04492781" ["create_user_token_time"]=> int(1669189931) ["update_user_token"]=> string(33) "1867447902637dd2134bd543.38206207" ["update_user_token_time"]=> int(1669190163) ["create_listemail_token"]=> string(33) "1237212366637decdccdab78.53906800" ["create_listemail_token_time"]=> int(1669197020) ["update_listemail_token"]=> string(33) "2135006987637dfcbac768a0.91016414" ["update_listemail_token_time"]=> int(1669201082) ["update_rs_token"]=> string(32) "720301184637dfd42e3d3a6.67284650" ["update_rs_token_time"]=> int(1669201218) }
      
      mailRs_token, mailRs_token_time, token ne sont pas tous isset

      J'comprend pas bien à ce moment là on dirait qu'il prend plusieurs mails 

      SERVER['HTTP_REFERER'] != referer
      http://localhost/portail/rs/mailrs/59  // 59 = id du rs 59 dans ma bdd
      http://localhost/portail/rs/mailrs/31  // 31 = id du rs 31 dans ma bdd
      0
  2. Patate
     

    Okay j'ai essayé de mettre l'id en statique dans mon if au lieux de 

    'http://localhost/portail/rs/mailrs/' . $id

    J'ai mis 

    'http://localhost/portail/rs/mailrs/59' 

    Et ça m'a bien envoyé mon mail de l'id 59 mais mtn j'aimerais mettre $id mais j'ai toujours ce 31 qui reviens et je ne sais pas du tout à quoi il correspond il y a aucun id 31 en plus dans ma table. 

    0
    1. jordane45 Messages postés 30427 Date d'inscription   Statut Modérateur Dernière intervention   4 832
       

      Faudrait regarder ( et nous montrer ? ) comment tu fais appel à ta fonction 

      mailRsBd
      0
      1. Patate > jordane45 Messages postés 30427 Date d'inscription   Statut Modérateur Dernière intervention  
         

        J'ai capté en fait pour remettre dans le contexte je choisis quelque chose qui a un id pcq c dans ma bdd que j'envois à une liste de diffusion qui a aussi un id et en fait au lieux de prendre l'id de mon truc que j'envois, celui qui est dans la barre d'url, il prend l'id de la liste de diffusion à laquelle j'envois le mail.

        L'appel de ma fonction mailRsBd dans mon controller 

        public function mailRsValidation()
            {
        
                $this->rsManager->mailRsBd(
                    $_POST['id'],
                    $_POST['clients_impactes'],
                    $_POST['pilote'],
                    $_POST['actions'],
                    $_POST['der'],
                    $_POST['date'],
                    $_POST['type'],
                    $_POST['cable'],
                    $_POST['datefin'],
                    $_POST['ville'],
                    $_POST['bml'],
                    $_FILES["fichier"]
                );
                //header('Location: ' . URL . "rs", "X-XSS-Protection: 1; mode=block");
            }
        
        
        

        Du coup l'id que j'ai dans les paramètres de ma fonction mailRsBd est celui de la liste de diffusion et non pas de mon rs 

        public function mailRsBd($id, $ville, $cmbl, $fichier) {}

        A noter : je reprend du code qui n'est pas le miens donc je déchiffre peu à peu ce qui a été fait.

        EDIT : Je viens d'afficher le $_POST['id'] qu'il y a dans le Controller pcq je pensais que lui prenais l'id de mon RS mais nan il prend aussi l'id de la liste de diffusion. WTF comment il sait quoi envoyer ??

        0
  3. Patate
     

    Ok j'ai finis par réussir à corriger ça, merci pour l'aide :)

    0