Sécurisez vos formulaires - PHP

Walky 🇫🇷

Cryptoboy
Ancien staff
Inscription
18 Octobre 2012
Messages
1 278
Réactions
1 187
Points
23 400
header1.png

Bonjour à tous , aujourd'hui nous allons, ensemble, apprendre à sécuriser nos formulaires HTML.

header2.png
Bien évidemment, nous n'utiliserons pas de vérification Captcha ou ReCaptcha pour ne pas embêter le visiteur.

Le principe va consister à générer une clé secrète pour l'insérer dans un champ invisible dans notre formulaire.
Et lors de l'envoi du formulaire, nous allons vérifier la validité de la clé.

Pour générer notre clé secrètre, nous utiliserons deux paramètres:

  • Un salt (de préférence tapé à la main)
  • Le timestamp actuel
Veillez à ne pas utiliser de variables statiques, voilà pourquoi j'utilise le timestamp .

header3.png
Comme vu dans la partie précédente, nous utiliserons deux paramètres, mais vous vous doutez bien qu'on ne les affichera pas directement dans le formulaire (même en champ masqué), on va donc utiliser une fonction PHP permettant de crypter les données , dans ce tutoriel je vais utiliser SHA1.

Commençons donc par créer notre seul et unique fichier, qui contiendra le formulaire HTML ainsi que le code PHP .


Je tiens à vous informer que j'utiliserai la POO tout au long du tutoriel.
PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9'; // tapé à la main
    public $erreur = null; // ici, sera stocké l'erreur

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }
}

On constate donc qu'il y a une variable de class: $salt, contenant notre salt, ainsi que 2 fonctions. L'une, exécutée directement lors du chargement de la page, et une autre permettant de générer la clé secrète .

À cela on va ajouter le formulaire HTML , de base un formulaire non sécurisé ressemble à ceci:
HTML:
<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

On va donc stocker notre clé secrète dans une variable, générée par notre fonction créée précédemment.

PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

Et l'insérer dans un champ invisible dans le formulaire HTML
PHP:
<input type="hidden" name="key" value="<?= $secretKey ?>" />

Il ne nous reste donc, seulement la vérification de la clé ! Et afficher l'erreur dans le formulaire HTML
PHP:
public function verifyKey()
{
    if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
    {
        $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    $secretKey = sha1($_SESSION['key'] . $this->salt);
    if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    return true;
}

En dehors de la class, nous avons donc quelque chose du genre
PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}

header4.png
PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9';
    public $erreur = null;

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key']))
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }

    public function verifyKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        return true;
    }
}

$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}
?>

<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <?php
            if ($class->erreur)
            {
                echo $class->erreur;
            }
        ?>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="hidden" name="key" value="<?= $secretKey ?>" />
            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

header5.png
Je vous remercie d'avoir lu ce tutoriel, et n'hésitez pas à me faire part de vos erreurs / bugs rencontrés si vous utilisez le système que je viens de vous présenter ::cool::

Merci @Lawid SEC pour les headers :love:

Walky
 

Fichiers joints

  • header1.png
    header1.png
    76.1 KB · Affichages: 158

Louki

Ancien staff
Inscription
12 Mars 2021
Messages
7 536
Réactions
4 583
Points
10 116
Voir la pièce jointe 101360
Bonjour à tous , aujourd'hui nous allons, ensemble, apprendre à sécuriser nos formulaires HTML.

Voir la pièce jointe 101356
Bien évidemment, nous n'utiliserons pas de vérification Captcha ou ReCaptcha pour ne pas embêter le visiteur.

Le principe va consister à générer une clé secrète pour l'insérer dans un champ invisible dans notre formulaire.
Et lors de l'envoi du formulaire, nous allons vérifier la validité de la clé.

Pour générer notre clé secrètre, nous utiliserons deux paramètres:

  • Un salt (de préférence tapé à la main)
  • Le timestamp actuel
Veillez à ne pas utiliser de variables statiques, voilà pourquoi j'utilise le timestamp .

Comme vu dans la partie précédente, nous utiliserons deux paramètres, mais vous vous doutez bien qu'on ne les affichera pas directement dans le formulaire (même en champ masqué), on va donc utiliser une fonction PHP permettant de crypter les données , dans ce tutoriel je vais utiliser SHA1.

Commençons donc par créer notre seul et unique fichier, qui contiendra le formulaire HTML ainsi que le code PHP .


Je tiens à vous informer que j'utiliserai la POO tout au long du tutoriel.
PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9'; // tapé à la main
    public $erreur = null; // ici, sera stocké l'erreur

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }
}

On constate donc qu'il y a une variable de class: $salt, contenant notre salt, ainsi que 2 fonctions. L'une, exécutée directement lors du chargement de la page, et une autre permettant de générer la clé secrète .

À cela on va ajouter le formulaire HTML , de base un formulaire non sécurisé ressemble à ceci:
HTML:
<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

On va donc stocker notre clé secrète dans une variable, générée par notre fonction créée précédemment.

PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

Et l'insérer dans un champ invisible dans le formulaire HTML
PHP:
<input type="hidden" name="key" value="<?= $secretKey ?>" />

Il ne nous reste donc, seulement la vérification de la clé ! Et afficher l'erreur dans le formulaire HTML
PHP:
public function verifyKey()
{
    if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
    {
        $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    $secretKey = sha1($_SESSION['key'] . $this->salt);
    if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    return true;
}

En dehors de la class, nous avons donc quelque chose du genre
PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}

PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9';
    public $erreur = null;

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key']))
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }

    public function verifyKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        return true;
    }
}

$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}
?>

<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <?php
            if ($class->erreur)
            {
                echo $class->erreur;
            }
        ?>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="hidden" name="key" value="<?= $secretKey ?>" />
            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

Je vous remercie d'avoir lu ce tutoriel, et n'hésitez pas à me faire part de vos erreurs / bugs rencontrés si vous utilisez le système que je viens de vous présenter ::cool::

Merci @Lawid SEC pour les headers :love:

Walky
Yeah, beau topic Walky ! ::):
 

Ichigo' SEC

Commercial
Ancien staff
Inscription
24 Septembre 2011
Messages
6 700
Réactions
4 079
Points
25 620
Voir la pièce jointe 101360
Bonjour à tous , aujourd'hui nous allons, ensemble, apprendre à sécuriser nos formulaires HTML.

Voir la pièce jointe 101356
Bien évidemment, nous n'utiliserons pas de vérification Captcha ou ReCaptcha pour ne pas embêter le visiteur.

Le principe va consister à générer une clé secrète pour l'insérer dans un champ invisible dans notre formulaire.
Et lors de l'envoi du formulaire, nous allons vérifier la validité de la clé.

Pour générer notre clé secrètre, nous utiliserons deux paramètres:

  • Un salt (de préférence tapé à la main)
  • Le timestamp actuel
Veillez à ne pas utiliser de variables statiques, voilà pourquoi j'utilise le timestamp .

Comme vu dans la partie précédente, nous utiliserons deux paramètres, mais vous vous doutez bien qu'on ne les affichera pas directement dans le formulaire (même en champ masqué), on va donc utiliser une fonction PHP permettant de crypter les données , dans ce tutoriel je vais utiliser SHA1.

Commençons donc par créer notre seul et unique fichier, qui contiendra le formulaire HTML ainsi que le code PHP .


Je tiens à vous informer que j'utiliserai la POO tout au long du tutoriel.
PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9'; // tapé à la main
    public $erreur = null; // ici, sera stocké l'erreur

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }
}

On constate donc qu'il y a une variable de class: $salt, contenant notre salt, ainsi que 2 fonctions. L'une, exécutée directement lors du chargement de la page, et une autre permettant de générer la clé secrète .

À cela on va ajouter le formulaire HTML , de base un formulaire non sécurisé ressemble à ceci:
HTML:
<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

On va donc stocker notre clé secrète dans une variable, générée par notre fonction créée précédemment.

PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

Et l'insérer dans un champ invisible dans le formulaire HTML
PHP:
<input type="hidden" name="key" value="<?= $secretKey ?>" />

Il ne nous reste donc, seulement la vérification de la clé ! Et afficher l'erreur dans le formulaire HTML
PHP:
public function verifyKey()
{
    if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
    {
        $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    $secretKey = sha1($_SESSION['key'] . $this->salt);
    if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    return true;
}

En dehors de la class, nous avons donc quelque chose du genre
PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}

PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9';
    public $erreur = null;

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key']))
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }

    public function verifyKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        return true;
    }
}

$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}
?>

<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <?php
            if ($class->erreur)
            {
                echo $class->erreur;
            }
        ?>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="hidden" name="key" value="<?= $secretKey ?>" />
            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

Je vous remercie d'avoir lu ce tutoriel, et n'hésitez pas à me faire part de vos erreurs / bugs rencontrés si vous utilisez le système que je viens de vous présenter ::cool::

Merci @Lawid SEC pour les headers :love:

Walky
Lourd ! :panic:
 

xRwizz

Ancien staff
Inscription
12 Juin 2013
Messages
18 462
Réactions
5 765
Points
21 368
Voir la pièce jointe 101360
Bonjour à tous , aujourd'hui nous allons, ensemble, apprendre à sécuriser nos formulaires HTML.

Voir la pièce jointe 101356
Bien évidemment, nous n'utiliserons pas de vérification Captcha ou ReCaptcha pour ne pas embêter le visiteur.

Le principe va consister à générer une clé secrète pour l'insérer dans un champ invisible dans notre formulaire.
Et lors de l'envoi du formulaire, nous allons vérifier la validité de la clé.

Pour générer notre clé secrètre, nous utiliserons deux paramètres:

  • Un salt (de préférence tapé à la main)
  • Le timestamp actuel
Veillez à ne pas utiliser de variables statiques, voilà pourquoi j'utilise le timestamp .

Comme vu dans la partie précédente, nous utiliserons deux paramètres, mais vous vous doutez bien qu'on ne les affichera pas directement dans le formulaire (même en champ masqué), on va donc utiliser une fonction PHP permettant de crypter les données , dans ce tutoriel je vais utiliser SHA1.

Commençons donc par créer notre seul et unique fichier, qui contiendra le formulaire HTML ainsi que le code PHP .


Je tiens à vous informer que j'utiliserai la POO tout au long du tutoriel.
PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9'; // tapé à la main
    public $erreur = null; // ici, sera stocké l'erreur

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }
}

On constate donc qu'il y a une variable de class: $salt, contenant notre salt, ainsi que 2 fonctions. L'une, exécutée directement lors du chargement de la page, et une autre permettant de générer la clé secrète .

À cela on va ajouter le formulaire HTML , de base un formulaire non sécurisé ressemble à ceci:
HTML:
<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

On va donc stocker notre clé secrète dans une variable, générée par notre fonction créée précédemment.

PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

Et l'insérer dans un champ invisible dans le formulaire HTML
PHP:
<input type="hidden" name="key" value="<?= $secretKey ?>" />

Il ne nous reste donc, seulement la vérification de la clé ! Et afficher l'erreur dans le formulaire HTML
PHP:
public function verifyKey()
{
    if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
    {
        $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    $secretKey = sha1($_SESSION['key'] . $this->salt);
    if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    return true;
}

En dehors de la class, nous avons donc quelque chose du genre
PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}

PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9';
    public $erreur = null;

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key']))
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }

    public function verifyKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        return true;
    }
}

$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}
?>

<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <?php
            if ($class->erreur)
            {
                echo $class->erreur;
            }
        ?>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="hidden" name="key" value="<?= $secretKey ?>" />
            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

Je vous remercie d'avoir lu ce tutoriel, et n'hésitez pas à me faire part de vos erreurs / bugs rencontrés si vous utilisez le système que je viens de vous présenter ::cool::

Merci @Lawid SEC pour les headers :love:

Walky
Du lourd, beau topic Walky ::cool::
 

❤cœur

Le plus beau
Inscription
21 Juin 2014
Messages
1 171
Réactions
384
Points
4 788
Voir la pièce jointe 101360
Bonjour à tous , aujourd'hui nous allons, ensemble, apprendre à sécuriser nos formulaires HTML.

Voir la pièce jointe 101356
Bien évidemment, nous n'utiliserons pas de vérification Captcha ou ReCaptcha pour ne pas embêter le visiteur.

Le principe va consister à générer une clé secrète pour l'insérer dans un champ invisible dans notre formulaire.
Et lors de l'envoi du formulaire, nous allons vérifier la validité de la clé.

Pour générer notre clé secrètre, nous utiliserons deux paramètres:

  • Un salt (de préférence tapé à la main)
  • Le timestamp actuel
Veillez à ne pas utiliser de variables statiques, voilà pourquoi j'utilise le timestamp .

Comme vu dans la partie précédente, nous utiliserons deux paramètres, mais vous vous doutez bien qu'on ne les affichera pas directement dans le formulaire (même en champ masqué), on va donc utiliser une fonction PHP permettant de crypter les données , dans ce tutoriel je vais utiliser SHA1.

Commençons donc par créer notre seul et unique fichier, qui contiendra le formulaire HTML ainsi que le code PHP .


Je tiens à vous informer que j'utiliserai la POO tout au long du tutoriel.
PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9'; // tapé à la main
    public $erreur = null; // ici, sera stocké l'erreur

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }
}

On constate donc qu'il y a une variable de class: $salt, contenant notre salt, ainsi que 2 fonctions. L'une, exécutée directement lors du chargement de la page, et une autre permettant de générer la clé secrète .

À cela on va ajouter le formulaire HTML , de base un formulaire non sécurisé ressemble à ceci:
HTML:
<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

On va donc stocker notre clé secrète dans une variable, générée par notre fonction créée précédemment.

PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

Et l'insérer dans un champ invisible dans le formulaire HTML
PHP:
<input type="hidden" name="key" value="<?= $secretKey ?>" />

Il ne nous reste donc, seulement la vérification de la clé ! Et afficher l'erreur dans le formulaire HTML
PHP:
public function verifyKey()
{
    if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
    {
        $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    $secretKey = sha1($_SESSION['key'] . $this->salt);
    if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
    {
        $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
        return false;
    }

    return true;
}

En dehors de la class, nous avons donc quelque chose du genre
PHP:
$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}

PHP:
<?php

class SubmitForm
{
    public $salt   = '782hdbbab001mbdjbxaoi9';
    public $erreur = null;

    public function __construct()
    {
        session_start(); // on démarre la session
        $_SESSION['key'] = uniqid(microtime(true)); // on stocke notre clé relative au timestamp dans une variable de session
    }

    public function buildKey()
    {
        if (!isset($_SESSION['key']))
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        return $secretKey;
    }

    public function verifyKey()
    {
        if (!isset($_SESSION['key'])) // la variable de session "key" doit obligatoirement exister
        {
            $this->erreur = 'Une erreur s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        if (!isset($_POST['key'])) // le formulaire doit contenir le champ "key"
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        $secretKey = sha1($_SESSION['key'] . $this->salt);
        if ($_POST['key'] != $secretKey) // la clé secrète envoyée doit correspondre exactement à celle créée par la fonction
        {
            $this->erreur = 'Une erreur de sécurité s\'est produite, veuillez rafraîchir la page.';
            return false;
        }

        return true;
    }
}

$class     = new SubmitForm();
$secretKey = $class->buildKey();

if ($_SERVER['REQUEST_METHOD'] == 'post') // on vérifie la clé seulement si la requête envoyée est au format POST
{
    $class->verifyKey();
}
?>

<!DOCTYPE html>
<html>
    <head>
        <!-- Vos données -->
    </head>
    <body>
        <?php
            if ($class->erreur)
            {
                echo $class->erreur;
            }
        ?>
        <form method="post" action="/">
            <input type="text" name="prenom" placeholder="Prénom..." />
            <input type="text" name="age" placeholder="Age..." />

            <input type="hidden" name="key" value="<?= $secretKey ?>" />
            <input type="submit" value="Soumettre" />
        </form>
    </body>
</html>

Je vous remercie d'avoir lu ce tutoriel, et n'hésitez pas à me faire part de vos erreurs / bugs rencontrés si vous utilisez le système que je viens de vous présenter ::cool::

Merci @Lawid SEC pour les headers :love:

Walky
Premier Developpédacteur ?
 

Rivals

Ancien staff
Inscription
27 Août 2016
Messages
1 705
Réactions
895
Points
13 104
Bonjour Walky SEC ,

Je ne veux pas être méchant mais ça ne sécurise en rien ton formulaire à l'heure d'aujourd'hui, avec par exemple on peut très facilement spammer ton formulaire et rendre ton token inutile :p

PHP:
public $erreur = null;

Equivaut à :
PHP:
public $erreur;

Et le salt doit avoir une portée limitée donc protected ;)

Presque parfait :trollface:

P.S : Tu as oublié de charger ta classe

Bonne journée,
Rivals
 

Walky 🇫🇷

Cryptoboy
Ancien staff
Inscription
18 Octobre 2012
Messages
1 278
Réactions
1 187
Points
23 400
P.S : Tu as oublié de charger ta classe
PHP:
$class = new SubmitForm();
:d:

Je ne vois pas comment PhantomJS pourrait "bypass" le formulaire, sachant que si la clé n'est pas valide / non définie, le formulaire ne s'envoie pas (je prends le cas ou les données du formulaire seraient sauvegardées etc..)
 

Rivals

Ancien staff
Inscription
27 Août 2016
Messages
1 705
Réactions
895
Points
13 104
PHP:
$class = new SubmitForm();
:d:

Je ne vois pas comment PhantomJS pourrait "bypass" le formulaire, sachant que si la clé n'est pas valide / non définie, le formulaire ne s'envoie pas (je prends le cas ou les données du formulaire seraient sauvegardées etc..)
C'est pas ça charger, ça c'est instancier (tu dois require ton fichier) :d:

PhantomJS te permet de toucher au DOM, donc avoir accès à ton input caché et ainsi on peut faire des boucles :p
 

Walky 🇫🇷

Cryptoboy
Ancien staff
Inscription
18 Octobre 2012
Messages
1 278
Réactions
1 187
Points
23 400
C'est pas ça charger, ça c'est instancier (tu dois require ton fichier) :d:
Le code HTML et PHP sont dans le même fichier, donc pas besoin :)

PhantomJS te permet de toucher au DOM, donc avoir accès à ton input caché et ainsi on peut faire des boucles :p
Hum, oui je vois un peu près le fonctionnement :mmh:

Enfin bon, ça permet toujours de sécuriser un minimum ses formulaires, contrairement à un formulaire sans clé.
 

Rivals

Ancien staff
Inscription
27 Août 2016
Messages
1 705
Réactions
895
Points
13 104
Le code HTML et PHP sont dans le même fichier, donc pas besoin :)


Hum, oui je vois un peu près le fonctionnement :mmh:

Enfin bon, ça permet toujours de sécuriser un minimum ses formulaires, contrairement à un formulaire sans clé.
Ah d'accord, je pensais que tu séparais les deux, good job :neo:
 
Haut