Chapitre 24 : Sécurité des requêtes
Protégez vos bases de données contre les injections SQL avec PDO et les bonnes pratiques
1. Pourquoi la sécurité des requêtes est-elle essentielle ?
Une application PHP qui interagit avec une base de données est vulnérable aux attaques par injection SQL si elle ne filtre pas correctement les données d'entrée. Ces attaques peuvent permettre à un utilisateur malveillant de manipuler les requêtes SQL pour lire, modifier ou supprimer des données.
2. Exemple d'injection SQL
$login = $_GET['login'];
$sql = "SELECT * FROM utilisateurs WHERE login = '$login'";
Si l'utilisateur saisit : ' OR '1'='1, la requête devient valide pour tous les utilisateurs.
3. Solution : Requêtes préparées
$login = $_GET['login'];
$sql = "SELECT * FROM utilisateurs WHERE login = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$login]);
?>
Les requêtes préparées empêchent l'injection SQL car les valeurs sont liées en tant que paramètres.
4. Valider les données
Avant d'envoyer des données à la base, vérifiez leur type, leur format et leur longueur. Par exemple :
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
die("Email invalide.");
}
?>
5. Assainir les données
Pour afficher des données dans une page web, utilisez htmlspecialchars() :
echo htmlspecialchars($utilisateur['nom']);
?>
6. Bonnes pratiques supplémentaires
- Utilisez des rôles utilisateurs limités dans MySQL
- Ne stockez jamais de mots de passe en clair : utilisez
password_hash() - Utilisez HTTPS pour les transmissions sécurisées
- Affichez les erreurs uniquement en mode développement
7. Exercice pratique : Formulaire sécurisé
Créez un petit formulaire de recherche sécurisé permettant d'afficher un utilisateur à partir de son identifiant.
Structure de la table
id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL
);
Formulaire HTML
<label>ID du membre :</label>
<input type="number" name="id" required>
<button type="submit">Rechercher</button>
</form>
Code PHP sécurisé
$pdo = new PDO('mysql:host=localhost;dbname=ma_base;charset=utf8', 'root', '');
if (isset($_GET['id']) && is_numeric($_GET['id'])) {
$id = (int) $_GET['id'];
$stmt = $pdo->prepare("SELECT * FROM membres WHERE id = ?");
$stmt->execute([$id]);
$membre = $stmt->fetch(PDO::FETCH_ASSOC);
if ($membre) {
echo "Nom : " . htmlspecialchars($membre['nom']) . "<br>";
echo "Email : " . htmlspecialchars($membre['email']);
} else {
echo "Aucun membre trouvé.";
}
}
?>
➡️ Objectif : Protéger la requête contre toute injection SQL, valider les données entrantes et assainir les sorties HTML.
8. Résumé
- ✅ Toujours utiliser les requêtes préparées
- ✅ Valider les données d'entrée
- ✅ Assainir les sorties HTML
- ✅ Appliquer des règles de sécurité générales
Ces bonnes pratiques sont essentielles pour créer des applications PHP fiables et sûres.