Securi-toile

Vous êtez sur : Blog Documentations Programmation Protection contre le SQL Injection

Protection contre le SQL Injection

Envoyer Imprimer PDF
Index de l'article
Protection contre le SQL Injection
Présentation du problème
Les variables qui contiennent des chaînes
La sécurité
Explication
Les variables numériques
Toutes les pages

Les SQL Injection sont parmi les failles les plus répandus et dangereux en PHP.
Ce tutorial va expliquer clairement le concept de SQL Injection et comment les éviter, une fois pour toutes.


01.Le probléme !

Il existe deux types d'injection SQL:

  • L'injection dans les variables qui contiennent des chaînes.
  • L'injection dans les variables numériques.

Ce sont deux types très différents et à éviter, il agira différemment pour chacun de ces types.



Les variables qui contiennent des chaînes :
Imaginez qu'un script PHP qui récupère l'âge d'un membre conformément à son
surnom. Ce surnom est parti d'une page à l'autre via l'URL
(en $ _GET). Ce script devrait ressembler à ceci :
1
2
$ pseudo = $ _GET [ 'pseudo'];
$ requete = mysql_query ( "SELECT age FROM membres WHERE pseudo = '$ pseudo'");

Ce script est une grande vulnérabilité par injection SQL. Il suffit qu'une personne malveillante en mettant en place le nom d'utilisateur dans l'URL d'une requête comme ceci :

1
'Password UNION SELECT FROM membres WHERE id = 1

Ceci est juste une demonstration, par exemple le mot de passe le membre ayant l'ID 1.



02.La sécurité

Pour sécuriser ce type d'injection est simple. Vous utilisez la fonction mysql_real_escape_string ().
What is ? Cette fonction ajoute le caractère "\" pour les caractères suivants :
1
NULL, \ x00, \ n, \ r, \, ', "et \ X1A

Comme vous l'avez remarqué dans l'injection précédente, le pirate utilise la citation (pour fermer la 'Around $ nick): si elle est empêchée de le faire, le pirate iras voir ailleurs. Cela signifie que si l'on applique un mysql_real_escape_string () pour le nom de variable comme ça ...

1
2
$ pseudo = mysql_real_escape_string ($ _GET [ 'pseudo']);
$ requete = mysql_query ( "SELECT age FROM membres WHERE pseudo = '$ pseudo'");

L'application est entièrement sécurisé.


Explication
1
'Password UNION SELECT FROM membres WHERE id = 1

Eh bien, si nous appliquons mysql_real_escape_string () à la variable $ nom utilisé dans la requête est ce qui va de l'injection :

1
\ 'Union de passe Sélectionnez membres WHERE id = 1

Cela signifie que nous ne viennent pas même en dehors des quotes autour de $ nick dans la requête car la \ a été ajoutée. Il existe une autre fonction quelque peu semblable à mysql_real_escape_string () est addslashes (), pourquoi ne pas avoir utilisé ? Eh bien récemment, une faille de sécurité a été découvert à ce sujet si il est utilisé sur une installation de PHP 4.3.9 avec magic_quotes_gpc est activé.



Variables numériques:

Ce type d'injection est moins connue que la précédente, ce qui en fait plus fréquentes, et il commence comme tout à l'heure avec un exemple. Cette fois, c'est affichage de l'âge d'un membre en fonction de son id, et en le faisant passer par un formulaire ($ _POST) à changer:

$ id = $ _POST [ 'id'];
$ requete = mysql_query ( "SELECT age FROM membres WHERE id = $ id");
mysql_real_escape_string () ne servirait à rien ici, car si un attaquant veut injecter du code SQL, il n'aura pas besoin d'utiliser des guillemets, parce que la variable $ id n'est pas entourée de guillemets. Simple exemple d'une
exploitation :
1
1 UNION DE passe Sélectionnez membres WHERE id = 1

Cette injection fait exactement la même que la précédente, sauf qu'ici, pour l'éviter, il y a deux solutions:

  • Changer le contenu de la variable si elle contient uniquement des chiffres
  • Vérifiez si la variable contient en réalité un certain nombre avant de l'utiliser dans une requête.

Méthode 1:

Nous allons utiliser une fonction intval () Cette fonction retourne quel que soit le contenu d'une variable sa valeur numérique. Par exemple:

1
2
e10 variable = '1 '; / / $ variable vaut '1 e10'
valeur_numerique $ = intval ($ variable); / / $ vaut valeur_numerique 1

1
2
3
$ id = intval ($ _POST [ 'id']);
$ requete = mysql_query ( "SELECT age FROM membres WHERE id = $ id");
)

Cela signifie que vous pouvez y passer est plus que suffisante, mais je vous recommande decontinuer à trouver une autre méthode, ou si vous avez l'air bête si vous trouvez cetteméthode sur un code qui n'est pas le vôtre sans le comprendre.

Méthode 2 :

Ici, nous utilisons une fonction qui renvoie TRUE si une variable ne contient quenombres et FALSE si elle n'est pas le cas cette fonction is_numeric (),nous allons l'utiliser dans une condition qui vérifie si la fonction is_numeric () retourne TRUE bien
$ id = $ _POST [ 'id'];
if (is_numeric ($ id))
(
$ requete = mysql_query ( "SELECT age FROM membres WHERE id = $ id");
)
autre
(
echo "Essayer de me hack ?";

Quelle est la meilleure, en fonction entre intval () et is_numeric () ?

Les deux sont tout aussi efficaces, mais je conseil inval () car avec la fonction is_numeric () écrire plus de code, et si la variable ne contient pas seulement des chiffres, la demande est annulée (en principe, mais bien sûr vous pouvez exécuter la même requête en choisissant une Valeur par défaut de la variable utilisée). Well that's it!

Vous savez tout pour sécuriser vos applications.

Si vous appliquez ces méthodes, il y a absolument aucun risque d'avoir un type de faille d'injection SQL sur son site web (ou PHP).

A propos

Sécurite informatique Eric Seguinard
Securi-Toile
9 Bd de la République
Istres 13800 France
06 10 81 62 02
Du lundi au vendredi de 9h à 19h.

Label Orange b2b site web partenaire