PDO et faille de sécurité - david-alpha/gdn GitHub Wiki
Ce projet démontre une faille d'injection SQL via PDO mal utilisé en PHP, et propose une version sécurisée utilisant les requêtes préparées.
-
insecure.php
: version vulnérable à l'injection SQL -
secure.php
: version sécurisée avecprepare()
etexecute()
-
init.sql
: script SQL pour créer une base de test avec une tableusers
-
README.md
: documentation
<?php
// Connexion PDO (vulnérable)
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');
// Récupère les données de l'utilisateur via GET
$username = $_GET['username'];
// ⚠️ Requête vulnérable à l'injection SQL
$sql = "SELECT * FROM users WHERE username = '$username'";
$stmt = $pdo->query($sql);
echo "<h2>Résultat :</h2>";
foreach ($stmt as $row) {
echo "Nom d'utilisateur : " . htmlspecialchars($row['username']) . "<br>";
}
?>
URL utilisée :
http://localhost:8000/insecure.php?username=' OR '1'='1
Cela permet de contourner la logique de sécurité et d'afficher tous les utilisateurs de la table.
<?php
// Connexion PDO sécurisée
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');
// Requête préparée sécurisée
$username = $_GET['username'] ?? '';
$sql = "SELECT * FROM users WHERE username = :username";
$stmt = $pdo->prepare($sql);
$stmt->execute(['username' => $username]);
echo "<h2>Résultat :</h2>";
foreach ($stmt as $row) {
echo "Nom d'utilisateur : " . htmlspecialchars($row['username']) . "<br>";
}
?>
- Paramètres liés via
prepare()
etexecute()
: empêche les injections SQL - Plus lisible, plus sûr, recommandé en production
CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL
);
INSERT INTO users (username) VALUES
('alice'),
('bob'),
('charlie');
- Toujours utiliser des requêtes préparées (
prepare()
+execute()
) - Ne jamais interpoler directement les variables dans les requêtes SQL
- Échapper les affichages avec
htmlspecialchars()
- Ne pas afficher les erreurs PDO en production
- Restreindre les droits MySQL : pas d’admin pour une simple lecture
- Activer le mode d’exception PDO :
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
mysql -u root -p < init.sql
php -S localhost:8000
-
Fichier vulnérable :
[http://localhost:8000/insecure.php?username=' OR '1'='1](http://localhost:8000/insecure.php?username=' OR '1'='1) -
Fichier sécurisé :
http://localhost:8000/secure.php?username=alice
Ce projet a été conçu à titre pédagogique pour illustrer les failles courantes dans les applications web PHP/MySQL.