Injection SQL en PHP 2025 : comment se protéger ? Guide complet

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi l'injection SQL est-elle toujours d'actualité en 2025 ?



Imaginez : vous avez créé un super site en PHP, ajouté un formulaire de contact, une recherche de produits, et une semaine plus tard, vous découvrez qu'un attaquant a téléchargé toute la base de données clients. Cela ressemble à une histoire d'horreur des années 2010 ? Hélas, selon l'OWASP, l'injection SQL (SQL injection) fait toujours partie du top 3 des vulnérabilités les plus dangereuses des applications web. Et oui, en 2025, les développeurs commettent encore cette erreur.



La question "How can I prevent SQL injection in PHP?" sur Stack Overflow a recueilli des milliers de vues et des centaines de réponses. Mais le problème ne vient pas d'un manque d'informations — le problème est que beaucoup utilisent encore des méthodes obsolètes comme les fonctions mysql_* (supprimées dès PHP 7.0) ou comptent naïvement sur mysqli_real_escape_string() comme sur une solution miracle.



Dans cet article, nous allons passer en revue les meilleures pratiques de protection contre les injections SQL en PHP en 2025. Vous apprendrez pourquoi les requêtes préparées (prepared statements) sont la norme de l'industrie, comment travailler correctement avec PDO et mysqli, et quels pièges attendent encore les développeurs inexpérimentés. C'est parti !



Qu'est-ce qu'une injection SQL en termes simples ?



L'injection SQL est une attaque où un attaquant "injecte" du code SQL malveillant dans une requête via une saisie utilisateur (formulaires, URL, cookies). Au lieu de simplement transmettre un nom d'utilisateur, le pirate peut envoyer : ' OR '1'='1 — et obtenir l'accès à toutes les données.



Voici un exemple classique de code vulnérable :



// Ne JAMAIS faire ceci !$username = $_POST['username'];$password = $_POST['password'];$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";$result = mysqli_query($conn, $query);


Si l'attaquant saisit dans le champ username : admin' --, la requête devient :



SELECT * FROM users WHERE username = 'admin' --' AND password = '...'


Tout ce qui suit -- est un commentaire. L'authentification est réussie. La base de données est à nous. Bonjour la fuite de données !



Méthode n°1 (et la plus importante) : Requêtes préparées (Prepared Statements)



En 2025, c'est la seule méthode recommandée pour se protéger des injections SQL. Les requêtes préparées séparent la logique SQL des données. Vous dites d'abord à la base de données : "Voici le modèle de requête, voici les emplacements pour les variables", puis vous transmettez les données séparément. La base de données échappe elle-même tout ce qui est nécessaire.



Option A : PDO (PHP Data Objects) — le standard moderne



PDO prend en charge 12 SGBD différents (MySQL, PostgreSQL, SQLite et autres). Si vous écrivez un nouveau projet en 2025 — utilisez PDO.



<?php// Connexion à la base de données via PDO$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';$user = 'root';$password = '';

try { $pdo = new PDO($dsn, $user, $password); // Important : lever des exceptions en cas d'erreur $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);} catch (PDOException $e) { die('Erreur de connexion : ' . $e->getMessage());}

// Requête préparée avec des placeholders nommés$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status = :status');$stmt->execute([ ':email' => $_POST['email'], ':status' => 'active']);$user = $stmt->fetch(PDO::FETCH_ASSOC);

// Alternative avec des placeholders positionnels (?)$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND status = ?');$stmt->execute([$_POST['email'], 'active']);$user = $stmt->fetch();?>


Pourquoi est-ce sécurisé ? Parce que les données ne sont jamais insérées directement dans la chaîne SQL. Même si l'utilisateur transmet ' OR '1'='1, PDO le transmet comme un littéral de chaîne, et la base de données l'interprète exactement comme une chaîne, et non comme une partie de la commande SQL.



Option B : MySQLi (MySQL Imp

Blogs

Book Recommendations