Fonction PHP contre les injections SQL

En sécurité informatique, une injection SQL est une faille peu compliquée à mettre en oeuvre et qui peut faire beaucoup de dégâts. Cet article présente rapidement ce type de faille et propose une fonction PHP pour se protéger contre se type de menace.

Injection SQL

Injection SQL

Présentation de ce type de faille

Les injections SQL consiste à utiliser des données qui vont modifier une requête SQL de bases pour un autre usage que celui prévu initialement. Ces failles sont possible lorsque les données d’entrées ne sont pas protégée. Imaginons par exemple une requête SQL qui permet de sélectionner l’identifiant d’un utilisateur à partir de son login et de son mot de passe.

SELECT identifiant
FROM utilisateur
WHERE login = 'nom_utilisateur' AND password = 'XC5AF32';

Cette requête permet de récupérer l’identifiant de l’utilisateur si le login et le mot de passe sont correct. S’ils ne sont pas correct, la requête ne renvoie rien et l’application peut donc indiquer à l’utilisateur qu’il a du se tromper de mot de passe.

Dans cette requête, le login est entré par l’utilisateur. Or, si celui ci indique que son login est « admin’ — » alors il peut se connecter même sans avoir le bon mot de passe. Voici à quoi ressemblera la requête avec un tel nom d’utilisateur:

SELECT identifiant
FROM utilisateur
WHERE login = 'admin' --' AND password = 'faux_password';

Les 2 tirets signifient que le reste de la requête est en commentaire. Dès lors, il est possible de se connecter sur le compte de l’administrateur et d’avoir accès à toutes les données sensibles d’un site ou d’une application.

Prévenir cette faille en PHP

Pour éviter de telles failles avec le langage PHP, il convient de nettoyer les données d’entrées avant de les utiliser dans des requêtes SQL. Il est possible d’utiliser PDO pour éviter ces erreurs, mais quand ce n’est pas possible il convient juste d’utiliser les fonctions mysqli_real_escape_string() ou mysqli_real_escape_string() (pour les anciennes versions de PHP). Ces fonctions protèges les caractères spéciaux d’une chaîne de caractères pour que cette chaîne puisse être utiliser dans une requête.

Ci-dessous on retrouve une fonction PHP qu’il convient d’appeler pour toutes les données à insérer dans une requête.

PHP 5

function sanitize_string($str) {
	if (get_magic_quotes_gpc()) {
		$sanitize = mysqli_real_escape_string(stripslashes($str));	 
	} else {
		$sanitize = mysqli_real_escape_string($str);	
	} 
	return $sanitize;
}

PHP 4 et PHP < 5.5

function sanitize_string($str) {
	if (get_magic_quotes_gpc()) {
		$sanitize = mysql_real_escape_string(stripslashes($str));	 
	} else {
		$sanitize = mysql_real_escape_string($str);	
	} 
	return $sanitize;
}

PHP < 4.3

Pour les vieilles versions de PHP il convient d’utiliser la fonction PHP addslashes(). Même si cette fonction n’est pas idéale, c’est mieux que rien.

function sanitize_string($str) {
	$sanitize = addslashes($str);	
	return $sanitize;
}

Avantages de la fonction

Cette fonction est à utiliser sur chaque $_GET ou $_POST qui iront dans une requête SQL. Elle transforme notamment le guillemet simple en son équivalent en entité HTML. Il est pratique d’utiliser une telle fonction car si un jour le système de base de données est modifié, il suffit juste de changer la fonction mysqli_real_escapte_string() à l’intérieur au lieu de faire des modifications dans tout le reste du code.

Ce contenu a été publié dans Bonnes pratiques.

A propos de l'auteur : Tony Archambeau

Fort de plusieurs années d'expérience dans le développement web, Tony partage ses connaissances sur des projets divers dont le site infowebmaster.fr. Il est possible de le suivre sur Twitter.
Partager

6 réflexions au sujet de « Fonction PHP contre les injections SQL »

  1. Guillermo dit :

    Salut,

    J’ai vu que t’a mis en place un beau site sur SQL. J’ai malheureusement déjà vu beaucoup de tutoriels a ce sujet. Bon je t’accorde qu’une référence en français est toujours la bienvenue.

    Pourrais tu faire une référence sur du nosql? Par exemple sous no.sql.sh :)

    Bonne continuation!

  2. Tony Archambeau dit :

    @Guillermo : merci pour ce commentaire. En effet il y a déjà de nombreux tutoriels en anglais, mais les tutoriels ont souvent une lacune : ils présentes uniquement les commandes ou les fonctions SQL de MySQL. J’essai autant que faire ce peu de préciser si les codes sont destinés à MySQL, PostgreSQL, SQL Server ou Oracle.
    C’est une très bonne idée le no.sql.sh. Malheureusement je ne m’y connaît pas trop pour le moment. Mais je vais tout de même commencer à créer ce site sous peu et commencer à intégrer du contenu. Il faut bien s’y mettre un jour où l’autre.

  3. xcombelle dit :

    L’idéal pour éviter des injections SQL est d’utiliser des prepared statements comme le propose PDO en PHP exemples dans http://fr2.php.net/manual/fr/class.pdo.php voire la fonction mysqli_prepared_statements voir http://fr2.php.net/manual/fr/mysqli.quickstart.prepared-statements.php

  4. youpi dit :

    Oui, PDO règle tout ça d’un coup ;o)

  5. AUVINET Franck dit :

    Bonjour,

    Oui pourquoi ne pas utiliser PDO directement?
    La séparation des données reste la meilleure solution aujourd’hui!

    Et si c’est juste pour une question de version de PHP, le fait de rester sur une version ancienne offre un risque plus important que l’injection SQL donc le meilleur conseil serait de changer de version et utiliser PDO non?

    Après chacun sa vision ;)

  6. dupas dit :

    En effet je voudrais juste savoir si cette fonction est sécurisé (si on comment la sécurisé):
    $req = $bdd->prepare(‘select * from deio where id=:id limit 1’);
    $req->execute(array(‘id’=> $_POST[‘id’]))
    $rep = $req->fetch();

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *