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

// MAUVAIS CODE (vulnérable)
$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

<?php
$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 :

<?php
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() :

<?php
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

CREATE TABLE membres (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nom VARCHAR(100) NOT NULL,
  email VARCHAR(100) NOT NULL
);

Formulaire HTML

<form method="get" action="">
  <label>ID du membre :</label>
  <input type="number" name="id" required>
  <button type="submit">Rechercher</button>
</form>

Code PHP sécurisé

<?php
$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.