IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Sécurite CSRF par la "méthode des tickets"


Sujet :

Langage PHP

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 19
    Points : 8
    Points
    8
    Par défaut Sécurite CSRF par la "méthode des tickets"
    Bonjour,

    je souhaite sécuriser la partie administrateur de mon site contre les attaques CSRF, avec la "méthode des jetons".
    Pour ceux qui ne savent pas en quoi tout cela consiste :
    http://guillaume-affringue.developpe.../?page=4#LIV-B

    On peut utiliser cette methode avec un champs de type "hidden" récupérant la valeur du jeton dans un formulaire (très pratique pour entrer dans une partie administrateur avant un formulaire login/password).
    J'ai testé cette méthode, et ça fonctionne chez moi (cf. le code ci-dessous).

    Le problème c'est qu'il faut comparer le ticket(jeton)(POST ou COOKIE) au ticket de la session à chaque chargement d'une page différente dans la partie administrateur. C'est expliqué dans le lien, pour lequel je n'arrive pas à faire fonctionner le code (avec un cookie donc sans formulaire).

    Supposons qu'il y ai une page formulaire.php où l'administrateur entre son login et password, une page traitement_formulaire.php qui traite le formulaire puis renvoi ensuite sur la page admin1.php (si tout est ok) qui est la première page d'administration.

    J'ai donc ceci dans la page formulaire.php :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <?php
    session_start();
    $token = md5(uniqid(rand(), true));
    $_SESSION[$nom.'_token'] = $token;
    $_SESSION[$nom.'_token_time'] = time();
    ?>
    <html>
    <head>
    <title>Formulaire d'identification</title>
    </head>
    <body>
    <form action="traitement_formulaire.php" method="post">
    login  : <input type="text" name="login">
    password : <input type="password" name="pwd">
    <input type="hidden" name="token" id="token" value="<?php echo $token; ?>"/>
    <input type="submit" value="Connexion">
    </form>
    </body>
    </html>
    puis traitement_formulaire.php :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    <?php
    $login_valide = "blabla";
    $pwd_valide = "blablabla";
     
    	// on teste si nos variables sont définies
    	if (isset($_POST['login']) && isset($_POST['pwd']))
    	{
    		// on vérifie le pseudo saisi et le mot de passe
    		if ($login_valide == $_POST['login'] && $pwd_valide == $_POST['pwd'])
    		{
    			session_start ();
    			//Vérification du token -> la fonction verifier_token est incluse au début de cette page par une include. Cette fonction verifier_token() est explicitée dans le premier lien.
    			if(verifier_token(600, 'http://$$$$$$$$$$$$/formulaire.php', 'forum'))
    			{
    				//on récupère une nouvelle valeur du token en écrasant la variable, c'est important
    				$token = md5(uniqid(rand(), true));
    				$_SESSION[$nom.'_token'] = $token;
    				$_SESSION[$nom.'_token_time'] = time();
     
     
    				// on enregistre les paramètres de notre visiteur comme variables de session ($login et $pwd) 
    				$_SESSION['login'] = $_POST['login'];
    				$_SESSION['pwd'] = $_POST['pwd'];
     
    				// on redirige notre visiteur vers une page de notre section membre
    				header ('location: admin1.php');
    			}
    			else
    			{
    				echo 'On DECONNECT';
    			}
    		}
    		else
    		{
    			// Le visiteur n'a pas été reconnu comme étant membre de notre site.
    			echo '<body onLoad="alert(\'Membre non reconnu...\')">';
    			// puis on le redirige vers la page d'accueil
    			echo '<meta http-equiv="refresh" content="0;URL=index.html">';
    		}
    	}
    	else
    	{
    		echo 'Les variables du formulaire ne sont pas déclarées.';
    	}
    ?>
    Voilà, c'est un début (je n'ai rien fait en fait, juste testé que ça fonctionnait bien). Maintenant je ne sais pas comment faire pour avoir un jeton qui se balade dans toute la partie session de l'administration. Il faudrait probablement changer la page traitement_formulaire.php et créer la page admin1.php.

    Merci d'avance pour votre aide et les experts sont aussi les bienvenus pour donner leurs avis ou propositions de code .

    Ce système de jetons est-il utile pour un envoi de mail par formulaire?
    Merci par avance.

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 19
    Points : 8
    Points
    8
    Par défaut
    petite erreur de code (deuxième lien) :
    ce n'est pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ticket = uniqid(strval(mt_rand() (1, 999999)));
    mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ticket = uniqid(strval(mt_rand(1, 999999)));
    mon problème est au niveau des cookies.
    Je les créé avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    setcookie('ticket', $ticket, 300);
    et vérifie s'il existe bien dans la page d'après avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (isset($_COOKIE['ticket']))
    et ça bloque sur cette dernière ligne. Donc soit le cookie ne passe pas soit mon code n'est pas bon.
    J'ai également essayé de créé le cookie avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $_COOKIE['ticket'] = $ticket;
    comme sur l'exemple, mais ça ne fonctionne pas non plus.

  3. #3
    FoxLeRenard
    Invité(e)
    Par défaut
    Bonjour,
    Je suis pret a regarder ta solution, mais avant d'aller plus loin, tu est bien OK que "afficher/source" donne accés aux input hidden


    Je réédites pour te dire que la lecture d'un cookies en PHP c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if (!isset($_COOKIE["ticket"])) $ticket=""; 
            else $ticket=$_COOKIE["ticket"];
    et l'écriture

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    setCookie('ticket',$ticket,(time()+60*60*24*365));

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 19
    Points : 8
    Points
    8
    Par défaut
    Premièrement, merci à toi,

    Bonjour,
    Je suis pret a regarder ta solution, mais avant d'aller plus loin, tu est bien OK que "afficher/source" donne accés aux input hidden
    tout à fait mais le ticket est aléatoire à chaque chargement de page, et le ticket du cookie est comparé à celui de la session à chaque fois pour vérifier l'authenticité de l'administrateur. Je crois aussi que c'est pour obliger l'administrateur à valider le formulaire, pour éviter la provenance de sites pirate extérieurs. C'est mieux expliqué dans les liens, je suis pas expert.

    Même avec ce code, j'ai le même problème, ça bloque sur le cookie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (!isset($_COOKIE["ticket"])) $ticket=""; 
            else $ticket=$_COOKIE["ticket"];
    Pour la solution que je propose(et qui ne marche pas donc), voici la page traitement_formulaire.php changée et admin1.php créée :

    traitement_formulaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    <?php //traitement_formulaire.php
    $login_valide = "blabla";
    $pwd_valide = "blablabla";
     
    include ("securite.php");
     
    	// on teste si nos variables sont définies
    	if (isset($_POST['login']) && isset($_POST['pwd']))
    	{
    		// on vérifie le pseudo saisi et le mot de passe
    		if ($login_valide == $_POST['login'] && $pwd_valide == $_POST['pwd'])
    		{
    			session_start ();
    			//Vérification du token -> la fonction verifier_token est incluse au début de cette page par une include. Cette fonction verifier_token() est explicitée dans le premier lien.
    			if(verifier_token(600, 'http://localhost/CSRF/formulaire.php', 'forum'))
    			{
    				//on récupère une nouvelle valeur du token en écrasant la variable, c'est important
    				$token = md5(uniqid(rand(), true));
    				$_SESSION[$nom.'_token'] = $token;
    				$_SESSION[$nom.'_token_time'] = time();
     
     				//création/écrasement du cookie pour la partie interne de l'administration
    				$token = uniqid(strval(mt_rand(1, 999999)));
    				setcookie('forum_token', $token, 300);
    				$_SESSION['forum_token'] = $token;
     
    				// on enregistre les paramètres de notre visiteur comme variables de session ($login et $pwd) 
    				$_SESSION['login'] = $_POST['login'];
    				$_SESSION['pwd'] = $_POST['pwd'];
     
    				// on redirige notre visiteur vers une page de notre section membre
    				header ('location: admin1.php');
    			}
    			else
    			{
    				echo 'On DECONNECT';
    			}
    		}
    		else
    		{
    			// Le visiteur n'a pas été reconnu comme étant membre de notre site.
    			echo '<body onLoad="alert(\'Membre non reconnu...\')">';
    			// puis on le redirige vers la page d'accueil
    			echo '<meta http-equiv="refresh" content="0;URL=index.html">';
    		}
    	}
    	else
    	{
    		echo 'Les variables du formulaire ne sont pas déclarées.';
    	}
    ?>
    admin1.php :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    <?php //admin1.php
    // On démarre la session (ceci est indispensable dans toutes les pages de notre section membre)
    session_start ();
     
    include ("securite.php");
     
    // On récupère nos variables de session
    if (isset($_SESSION['login']) && isset($_SESSION['pwd']))
    {
    	if(verifier_token_admin(5, 'http://localhost/$$$$/traitement_formulaire.php', 'forum'))
    	{
    		// On le renouvelle	en l'écrasant
    		$token = uniqid(strval(mt_rand(1, 999999)));
    		setcookie($nom.'_token', $token, 300);
    		$_SESSION[$nom.'_token'] = $token;
     
    		// On affiche un lien pour fermer notre session
    		echo '<a href="./logout.php" >Déconnexion</a>';
     
    	}
    	else
    	{
    		echo 'On DéCONNECT';
    	}
    }
    else
    {
    	echo 'Les variables ne sont pas déclarées.';
    }
    ?>
    le fichier securite.php au passage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    <?php //securite.php
    //Cette fonction génére, sauvegarde et retourne un token
    //Vous pouvez lui passer en paramètre optionnel un nom pour différencier les formulaires
    function generer_token($nom = '')
    {
    	//session_start();
    	$token = md5(uniqid(rand(), true));
    	$_SESSION[$nom.'_token'] = $token;
    	$_SESSION[$nom.'_token_time'] = time();
    //	$_COOKIE[$nom.'_token'] = $token; //à ne pas oublier dans vérifier_token_admin!!!
    	return $token;
    }
     
     
    //**********************************************************************************************************************************-//
    //**********************************************************************************************************************************-//
    //**********************************************************************************************************************************-//
     
     
    //Cette fonction vérifie le token
    //Vous passez en argument le temps de validité (en secondes)
    //Le referer attendu (adresse absolue, rappelez-vous :D)
    //Le nom optionnel si vous en avez défini un lors de la création du token
    function verifier_token($temps, $referer, $nom = '')
    {
    //session_start();
    if(isset($_SESSION[$nom.'_token'], $_SESSION[$nom.'_token_time'], $_POST['token']))
    {
    	if($_SESSION[$nom.'_token'] == $_POST['token'])
    	{
    		$timestamp_ancien = time() - $temps;
    		if($_SESSION[$nom.'_token_time'] >= $timestamp_ancien)
    		{
    			if($_SERVER['HTTP_REFERER'] == $referer)
    			{
    				return true;
    			}
    			else
    			{
    				return false;
    			}
    		}
    		else
    		{
    			return false;
    		}
    	}
    	else
    	{
    		return false;
    	}
    }
    else
    {
    	return false;
    }
     
    }
     
    //**********************************************************************************************************************************-//
    //**********************************************************************************************************************************-//
    //**********************************************************************************************************************************-//
     
     
    //Cette fonction vérifie le token
    //Vous passez en argument le temps de validité (en secondes)
    //Le referer attendu (adresse absolue, rappelez-vous :D)
    //Le nom optionnel si vous en avez défini un lors de la création du token
    function verifier_token_admin($temps, $referer, $nom = '')
    {
    //session_start();
    if (!isset($_COOKIE["ticket"])) 
    {
    	return false;
    }
    else
    {
    	return true;
    }
     
    }
    ?>
    je recopie le fichier formulaire.php pour plus de clarté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    <?php //formulaire.php
    session_start();
    include ("securite.php");
    $token = generer_token('forum');
    ?>
    <html>
    <head>
    <title>Formulaire d identification</title>
    </head>
    <body>
    <form action="traitement_formulaire.php" method="post">
    login  : <input type="text" name="login">
    password : <input type="password" name="pwd">
    <input type="hidden" name="token" id="token" value="<?php echo $token; ?>"/>
    <input type="submit" value="Connexion">
    </form>
    </body>
    </html>
    Tenez-vous en à ces 4 derniers fichiers, c'est là où j'en suis.

    A ce stade une fois le login/password rentrés, le navigateur m'affiche la page admin1.php avec écrit : "On DéCONNECT ". Cela veut bien dire que le traitement du formulaire (et du jeton du formulaire avec) a bien été traité. ça bloque donc ici dans la fonction verifier_token_admin() dans le fichier securite.php :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (!isset($_COOKIE["ticket"]))
    le cookie n'exiterai pas???!!.
    Je précise que ça correspond à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(verifier_token_admin(5, 'http://localhost/$$$$/traitement_formulaire.php', 'forum'))
    du fichier admin1.php.
    Et je ne sais pas pourquoi.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 19
    Points : 8
    Points
    8
    Par défaut
    Qu'en pensez-vous?

Discussions similaires

  1. Réponses: 28
    Dernier message: 29/12/2011, 19h24
  2. [Turbo Pascal] Déterminant d'une matrice par la méthode des mineurs principaux
    Par afmimra dans le forum Turbo Pascal
    Réponses: 2
    Dernier message: 18/12/2009, 22h17
  3. detection de contour par les méthodes des Contours actifs
    Par aichaeside dans le forum Traitement d'images
    Réponses: 1
    Dernier message: 19/10/2009, 14h12
  4. Calcul d'une intégrale double par la méthode des quadratures
    Par deubelte dans le forum Mathématiques
    Réponses: 5
    Dernier message: 10/05/2009, 12h40
  5. Equation du cercle par la méthode des moindres carrés
    Par olivier21c dans le forum MATLAB
    Réponses: 1
    Dernier message: 29/03/2009, 20h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo