Sécurisez vos formulaires avec des clés de formulaire

La sécurité est un sujet brûlant. Garantir la sécurité de vos sites Web est extrêmement important pour toute application Web. En fait, je passe 70% de mon temps à sécuriser mes applications. Une des choses les plus importantes que nous devons sécuriser sont les formulaires. Aujourd'hui, nous allons examiner une méthode permettant d'empêcher la falsification de requêtes XSS (script intersite) et de demande intersite sur des formulaires..

Pourquoi?

Les données POST peuvent être envoyées d'un site Web à un autre. Pourquoi est-ce mauvais? Un scénario simple…

Un utilisateur, connecté à votre site Web, visite un autre site Web au cours de sa session. Ce site Web pourra envoyer des données POST sur votre site Web, par exemple avec AJAX. Étant donné que l'utilisateur est connecté à votre site, l'autre site Web pourra également envoyer des données de publication à des formulaires sécurisés qui ne sont accessibles qu'après une connexion..

Nous devons également protéger nos pages contre les attaques utilisant cURL

Comment réparons nous ça?

Avec des clés de formulaire! Nous ajouterons un hachage spécial (clé de formulaire) à chaque formulaire pour nous assurer que les données ne seront traitées que lorsqu'elles auront été envoyées à partir de votre site Web. Après l'envoi d'un formulaire, notre script PHP validera la clé de formulaire soumise par rapport à la clé de formulaire que nous avons définie dans une session..

Ce que nous devons faire:

  1. Ajouter une clé de formulaire à chaque formulaire.
  2. Stocker la clé de formulaire dans une session.
  3. Valider la clé de formulaire après la soumission d'un formulaire.

Étape 1: Un formulaire simple

Nous avons d’abord besoin d’un formulaire simple à des fins de démonstration. L'un des formulaires les plus importants que nous devons sécuriser est le formulaire de connexion. Le formulaire de connexion est vulnérable aux attaques par force brutale. Créez un nouveau fichier et enregistrez-le sous. index.php dans votre racine web. Ajoutez le code suivant dans le corps:

     Sécurisation des formulaires avec des clés de formulaire   

Nous avons maintenant une simple page XHTML avec un formulaire de connexion. Si vous souhaitez utiliser des clés de formulaire sur votre site Web, vous pouvez remplacer le script ci-dessus par votre propre page de connexion. Maintenant, passons à l'action réelle.

Étape 2: Créer une classe

Nous allons créer une classe PHP pour nos clés de formulaire. Parce que chaque page ne peut contenir que un forme clé, nous pourrions faire un singleton de notre classe pour nous assurer que notre classe est utilisée correctement. La création de singletons étant un sujet plus avancé de la programmation orientée objet, nous ignorerons cette partie. Créez un nouveau fichier appelé formkey.class.php et placez-le dans votre racine Web. Nous devons maintenant penser aux fonctions dont nous avons besoin. Premièrement, nous avons besoin d’une fonction pour générer une clé de formulaire afin de pouvoir la placer dans notre formulaire. Dans votre fichier PHP, insérez le code suivant:

 

Ci-dessus, vous voyez une classe en trois parties: deux variables et une fonction. Nous rendons la fonction privée car cette fonction ne sera utilisée que par notre sortiefonctions, que nous créerons plus tard. Dans les deux variables, nous allons stocker les clés de formulaire. Celles-ci sont également privées car elles ne peuvent être utilisées que par des fonctions de notre classe..

Nous devons maintenant trouver un moyen de générer notre clé de formulaire. Comme notre clé de formulaire doit être unique (sinon nous n’avons aucune sécurité), nous utilisons une combinaison de l’adresse IP de l’utilisateur pour associer la clé à un utilisateur, mt_rand () pour la rendre unique et la fonction uniqid () pour le rendre encore plus unique. Nous cryptons également ces informations avec md5 () pour créer un hachage unique que nous pourrons ensuite insérer dans nos pages. Comme nous avons utilisé md5 (), un utilisateur ne peut pas voir ce que nous avons utilisé pour générer la clé. La fonction entière:

 // Fonction permettant de générer la clé de formulaire fonction privée generateKey () // Récupère l'adresse IP de l'utilisateur $ ip = $ _SERVER ['REMOTE_ADDR']; // Nous utilisons mt_rand () au lieu de rand () car il est préférable de générer des nombres aléatoires. // Nous utilisons 'true' pour obtenir une chaîne plus longue. // Voir http://www.php.net/mt_rand pour une description précise de la fonction et d'autres exemples. $ uniqid = uniqid (mt_rand (), true); // Retourne le hash return md5 ($ ip. $ Uniqid); 

Insérez le code ci-dessus dans votre formkey.class.php fichier. Remplacer la fonction par la nouvelle fonction.

Étape 3: Insertion d'une clé de formulaire dans notre formulaire

Pour cette étape, nous créons une nouvelle fonction qui génère un champ HTML masqué avec notre clé de formulaire. La fonction comprend trois étapes:

  1. Générer une clé de formulaire avec notre fonction generateKey ().
  2. Stocker la clé de formulaire dans notre variable $ formKey et dans une session.
  3. Sortir le champ HTML.

Nous nommons notre fonction outputKey () et le rendre public, car nous devons l'utiliser en dehors de notre classe. Notre fonction appellera la fonction privée generateKey () pour générer une nouvelle clé de formulaire et l’enregistrer localement dans une session. Enfin, nous créons le code XHTML. Maintenant, ajoutez le code suivant dans notre classe PHP:

 // Fonction permettant d'afficher la clé de formulaire public function outputKey () // Génère la clé et la stocke dans la classe $ this-> formKey = $ this-> generateKey (); // Stocke la clé de formulaire dans la session $ _SESSION ['form_key'] = $ this-> formKey; // Affiche la clé de formulaire echo "formKey. "" /> ";

Maintenant, nous allons ajouter la clé de formulaire à notre formulaire de connexion pour le sécuriser. Nous devons inclure la classe dans notre index.php fichier. Nous devons également démarrer la session car notre classe utilise des sessions pour stocker la clé générée. Pour cela, nous ajoutons le code suivant au-dessus du doctype et de la balise head:

 

Le code ci-dessus est assez explicite. Nous commençons la session (parce que nous stockons la clé de formulaire) et chargeons le fichier de classe PHP. Après cela, nous commençons la classe avec nouveau formulaire (), cela va créer notre classe et le stocker dans $ formKey. Il ne nous reste plus qu'à éditer notre formulaire pour qu'il contienne la clé de formulaire:

 
outputKey (); ?>
type d'entrée = "mot de passe" name = "mot de passe" />

Et c'est tout! Parce que nous avons créé la fonction outputKey (), il suffit de l'inclure dans notre formulaire. Nous pouvons utiliser des clés de formulaire dans chaque formulaire en ajoutant simplement outputKey (); ?> Maintenant, il suffit de passer en revue la source de votre page Web et vous pouvez voir qu’une clé de formulaire est attachée au formulaire. La seule étape restante consiste à valider les demandes.

Étape 4: validation

Nous ne validerons pas l'intégralité du formulaire. seulement la clé de formulaire. La validation du formulaire est une base de PHP et des tutoriels peuvent être trouvés sur tout le web. Valorisons la clé de formulaire. Comme notre fonction "generateKey" écrase la valeur de la session, nous ajoutons un constructeur à notre classe PHP. Un constructeur sera appelé lorsque notre classe sera créée (ou construite). Le constructeur va stocker la clé précédente dans la classe avant nous en créons un nouveau; nous aurons donc toujours la clé de formulaire précédente pour valider notre formulaire. Si nous ne le faisions pas, nous ne pourrions pas valider la clé de formulaire. Ajoutez la fonction PHP suivante à votre classe:

 // Le constructeur stocke la clé de formulaire (s'il en existe une) dans notre variable de classe. function __construct () // Nous avons besoin de la clé précédente pour la stocker si (isset ($ _SESSION ['form_key'])) $ this-> old_formKey = $ _SESSION ['form_key']; 

Un constructeur doit toujours être nommé __construction(). Lorsque le constructeur est appelé, nous vérifions si une session est définie et, le cas échéant, nous la stockons localement dans notre répertoire. old_formKey variable.

Nous pouvons maintenant valider notre clé de formulaire. Nous créons une fonction de base dans notre classe qui valide la clé de formulaire. Cette fonction devrait également être publique car nous allons l'utiliser en dehors de notre classe. La fonction validera la valeur POST de la clé de formulaire par rapport à la valeur stockée de la clé de formulaire. Ajoutez cette fonction à la classe PHP:

 // Fonction qui a validé la clé de formulaire POST data public function validate () // Nous utilisons l'ancien formKey et non la nouvelle version générée if ($ _ POST ['form_key'] == $ this-> old_formKey) // la clé est valide, retourne vrai. retourne vrai;  else // La clé n'est pas valide, retourne false. retourne faux; 

Dans index.php, nous validons la clé de formulaire en utilisant la fonction que nous venons de créer dans notre classe. Bien entendu, nous ne validons qu'après une demande POST. Ajoutez le code suivant après $ formKey = new formKey ();

 $ error = 'Pas d'erreur'; // est la demande? if ($ _ SERVER ['REQUEST_METHOD'] == 'post') // Valide la clé du formulaire if (! isset ($ _ POST ['form_key']) ||! $ formKey-> validate ()) // Form la clé n'est pas valide, affichez une erreur $ error = 'Erreur de clé de formulaire!';  else // Faites le reste de votre validation ici $ error = 'No form key error!'; 

Nous avons créé une variable $ error qui stocke notre message d'erreur. Si une demande POST a été envoyée, nous validons notre formulaire avec $ formKey-> validate (). Si cela retourne false, la clé de formulaire est invalide et nous affichons une erreur. Notez que nous ne validons que la clé du formulaire. Vous êtes censé valider vous-même le reste du formulaire..

Dans votre code HTML, vous pouvez placer le code suivant pour afficher le message d'erreur:

 

Cela fera écho à la $ error variable si elle est définie.

Si vous démarrez votre serveur et allez à index.php, vous verrez notre formulaire et le message 'Aucune erreur'. Lorsque vous soumettez un formulaire, le message "Aucune erreur de clé de formulaire" s'affiche car il s'agit d'une demande POST valide. Essayez maintenant de recharger la page et acceptez lorsque votre navigateur demande que les données POST soient renvoyées. Vous verrez que notre script déclenche un message d'erreur: "Erreur de clé de formulaire!" Votre formulaire est maintenant protégé contre les entrées d'autres sites Web et contre les erreurs de rechargement de page! L'erreur est également affichée après une actualisation, car une nouvelle clé de formulaire a été générée après l'envoi du formulaire. C'est bien parce que, maintenant, l'utilisateur ne peut plus envoyer accidentellement un formulaire deux fois..

Code complet

Voici l'intégralité du code PHP et HTML:

index.php

 validate ()) // La clé de formulaire n'est pas valide, affichez une erreur $ error = 'Erreur de clé de formulaire!';  else // Faites le reste de votre validation ici $ error = 'No form key error!'; ?>     Sécurisation des formulaires avec des clés de formulaire   
outputKey (); ?>

fomrkey.class.php

 old_formKey = $ _SESSION ['form_key'];  // Fonction permettant de générer la clé de formulaire fonction privée generateKey () // Récupère l'adresse IP de l'utilisateur $ ip = $ _SERVER ['REMOTE_ADDR']; // Nous utilisons mt_rand () au lieu de rand () car il est préférable de générer des nombres aléatoires. // Nous utilisons 'true' pour obtenir une chaîne plus longue. // Voir http://www.php.net/mt_rand pour une description précise de la fonction et d'autres exemples. $ uniqid = uniqid (mt_rand (), true); // Retourne le hash return md5 ($ ip. $ Uniqid);  // Fonction permettant d'afficher la clé de formulaire public function outputKey () // Génère la clé et la stocke dans la classe $ this-> formKey = $ this-> generateKey (); // Stocke la clé de formulaire dans la session $ _SESSION ['form_key'] = $ this-> formKey; // Affiche la clé de formulaire echo "formKey. "" /> "; // Fonction qui a validé la clé de formulaire POST data public function validate () // Nous utilisons l'ancien formKey et non la nouvelle version générée if ($ _ POST ['form_key'] == $ this-> old_formKey) // La clé est valide, renvoie vrai. renvoie vrai; else // La clé est invalide, renvoie faux. renvoie faux;?>>

Conclusion

L'ajout de ce code à tous les formulaires importants de votre site Web augmentera considérablement la sécurité de votre formulaire. Comme nous l'avons vu à l'étape 4, il arrête même l'actualisation des problèmes. Comme la clé de formulaire n'est valide que pour une requête, une double publication n'est pas possible..

C'était mon premier tutoriel, j'espère que vous l'aimerez et que vous l'utiliserez pour améliorer votre sécurité! S'il vous plaît laissez-moi savoir vos pensées, via les commentaires. Avoir une meilleure méthode? Laissez nous savoir.

Lectures complémentaires

  • WordPress utilise également des clés de formulaire (le nommant Nonces): Wordpress Nonces
  • Sept habitudes pour écrire des applications PHP sécurisées
  • Suivez-nous sur Twitter ou abonnez-vous au fil RSS NETTUTS pour plus d'articles et de sujets sur le développement Web quotidiens.