Protection contre les données malveillantes

Lorsqu'un usager soumet du texte à partir d'un formulaire HTML, il faut s'assurer que ce texte ne comprend pas d'instructions malveillantes. Sans entrer dans les détails de la sécurité informatique, vous devez être conscients des dangers potentiels face aux informations entrées dans un formulaire.

Les mêmes problèmes peuvent se présenter pour toutes informations pouvant être entrées par l'usager : paramètre dans l'URL, information tirée d'un cookie, etc.

▼Publicité

Protection contre les attaques XSS : htmlentities()

Un utilisateur malveillant pourrait entrer des balises <script> dans une boîte de saisie de texte. On appelle ce type d'attaque « Attaque XSS » ou « Cross-Site Scripting ».

Pour éviter cela, la fonction htmlentities() permet entre autres de convertir les balises < et > en &lt; et &gt; donc le texte entré ne pourra en aucun cas faire exécuter un script à votre insu. Ainsi, si un utilisateur entre <script> dans la boîte de saisie, ceci sera converti en &lt;script&gt; donc ce sera du texte tout à fait inoffensif.

Ex :

PHP

echo htmlentities($_POST['texte']);

La fonction htmlentities() est donc utile pour augmenter la sécurité des données qui seront affichées à l'écran.

Protection contre les injections SQL : addslashes()

Si les données saisies dans un formulaire ont pour but de préciser une requête dans votre base de données, il faut prendre certaines précautions pour empêcher les utilisateurs malveillants de trafiquer la requête.

Par exemple, pour traiter un formulaire d'authentification, on pourrait utiliser la requête suivante pour vérifier la correspondance entre le code d'usager et le mot de passe :

MySQL

SELECT * FROM user WHERE user_login = '$usager' AND user_password = '$motdepasse';

Si l'utilisateur a entré le texte suivant comme code d'usager : 1' OR 1=1 -- suivi d'un espace, la requête exécutée sera la suivante :

MySQL

SELECT * FROM user WHERE user_login = '1' OR 1=1 -- ' AND user_password = ' ';

La section user_login = '1' OR 1=1 retournera toujours vrai et la section AND user_password = ' ' sera considérée comme du commentaire. L'utilisateur pourra donc accéder aux informations sensibles même s'il n'a pas une authentification valide.

On appelle ce type d'attaque « Injection SQL ».

La fonction addslashes() permet de prévenir certains types d'injections SQL en ajoutant un caractère d'échappement ( \ ) devant certains caractères. Ceci permet d'éviter qu'ils ne soient interprétés alors qu'on souhaite qu'ils soient considérés comme du texte. Dans l'exemple précédent, addslashes() aurait ajouté un caractère d'échappement devant l'apostrophe. Ce dernier n'aurait donc pas pu être interprété comme le caractère terminant une chaîne.

Ex :

PHP

$usagersecure = addslashes($_POST['usager']);

$motdepassecrypte = sha1($_POST['motdepasse']);

$requete = "SELECT * FROM user WHERE user_login = '$usagersecure' AND user_password = '$motdepassecrypte';";

$resultat = mysql_query($requete);

Cette fois, si l'utilisateur entre 1' OR 1=1 -- suivi d'un espace comme code d'usager, la requête envoyée au serveur sera la suivante :

MySQL

SELECT * FROM user WHERE user_login = '1\' OR 1=1 -- ' AND user_password = ' ';

Aucun enregistrement ne sera retourné et l'utilisateur malveillant restera sur sa faim.

La fonction addslashes() est donc utile pour augmenter la sécurité des données utilisées dans une requête SQL.

Blague sur les injections SQL

Blague tirée de : http://xkcd.com/327/

addslashes() vs mysql_real_escape_string() vs mysqli_real_escape_string()

Il existe un débat parmi les programmeurs PHP à savoir quelle fonction est la plus sécuritaire contre les injections SQL : addslashes()mysql_real_escape_string() ou mysqli_real_escape_string().

Tout d'abord, il semblerait que ces fonctions aient été écrites pour assurer que les données soient correctement traitées par le serveur lors de l'enregistrement. Par extension, elles sont aussi utilisées pour se protéger contre certaines injections SQL. Aucune ne peut cependant à elle seule garantir que les données soit complètement protégées. Leur utilisation constitue un minimum de sécurité à mettre en place.

Mais laquelle de ces fonctions offre la meilleure protection ? Il semblerait que ce soit mysqli_real_escape_string(). Cependant, addslashes() est elle aussi très acceptable. Certaines injections permettront cependant de traverser les  barrières de chacune de ces fonctions.

addslashes() permet d'échapper quatre caractères :

  • apostrophe ( ' )
  • guillemets ( " )
  • barre oblique inverse, ou backslash ( \ )
  • le caractère NULL

mysql_real_escape_string(), quant à elle, permet d'échapper les caractères suivants :

  • apostrophe ( ' )
  • guillemets ( " )
  • barre oblique inverse, ou backslash ( \ )
  • NULL
  • le saut de ligne ( \n)
  • le retour de charriot ( \r )
  • autre représentation de la valeur nulle (caractère hexadécimal \x00)
  • fin de fichier ou Control-Z (caractère hexadécimal \x1a)

La fonction mysql_real_escape_string() fait partie de extension MySQL (ext/mysql). Comme cette extension ne sera éventuellement plus supportée, PHP conseille l'utilisation de mysqli_real_escape_string() plutôt que mysql_real_escape_string(). Le i tient pour improved.

La fonction mysqli_real_escape_string() échappe les caractères suivants :

  • apostrophe ( ' )
  • guillemets ( " )
  • barre oblique inverse, ou backslash ( \ )
  • le caractère NULL (ASCII 0)
  • le saut de ligne ( \n)
  • le retour de charriot ( \r )
  • Control-Z

Protection avec les variables numériques

Prenons l'exemple d'une requête SQL travaillant avec des données numériques :

MySQL

UPDATE user SET user_password = '$motdepasse' WHERE user_id = $id;

Si l'usager entre 1234 OR TRUE dans la variable $id, la requête deviendra :

MySQL

UPDATE user SET user_password = '...' WHERE user_id = 1234 OR TRUE;

L'utilisation d'une fonction d'échappement, comme addslashes() ou mysqli_real_escape_string(), ne permettrait pas de protéger contre cette injection SQL. Tous les usagers de la BD recevraient un nouveau mot de passe, connu des utilisateurs malveillants. Oups !

Lorsqu'une requête SQL utilise une variable numérique, on doit toujours s'assurer que le contenu de la variable est effectivement numérique. On pourrait pour cela utiliser la fonction is_numeric(). Cependant, sachant qu'un nombre hexadécimal peut représenter autre chose qu'un nombre (ex : 0x1a = fin de fichier), on préférera faire une conversion de type.

Ex :

PHP

$id = (int)$id;

$requete = "UPDATE user SET user_password = '$motdepassecrypte' WHERE user_id = $id;";

Pour plus d'information

« Injection SQL ». PHP. http://php.net/manual/fr/security.database.sql-injection.php

« SQL injection ». MySQL. http://dev.mysql.com/tech-resources/articles/guide-to-php-security-ch3.pdf

« Sécurisation des variables entrantes ». PHP Boost. http://www.phpboost.com/wiki/securisation-des-variables-entrantes

« addslashes() vs mysql_real_escape_string()...the final debate ». sitepoint. http://www.sitepoint.com/forums/showthread.php?337881-addslashes()-vs-mysql_real_escape_string()-the-final-debate

« addslashes() Versus mysql_real_escape_string() ». Chris Shiflett. http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

« SQL injection, myths and fallacies ». Slideshare. http://fr.slideshare.net/billkarwin/sql-injection-myths-and-fallacies

« Tutoriel PHP - Fonction htmlentities ». PHP sources. http://www.phpsources.org/tutoriel-htmlentities.htm

« Quelques exemples basiques d’attaque sur une application web ». Australopitech. http://www.australopitech.com/187-quelques-exemples-basiques-d%E2%80%99attaque-sur-une-application-web

« Sécurité des applications Web ». PHPteam.net. http://www.phpteam.net/index.php/articles/securite-des-applications-web

« MySQL SQL Injection Cheat Sheet ». pentestmonkey. http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet

« SQL Injection ». hakipedia. http://hakipedia.com/index.php/SQL_Injection

Merci de partager ! Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInPin on PinterestShare on StumbleUponEmail this to someone
Catégories