# Injection SQL

> Faille où une donnée non filtrée insérée dans une requête permet à un attaquant de modifier le comportement de cette requête envers la base.

- Auteur : Clément Hadrot
- Publié le : 2026-09-25
- Mis à jour le : 2026-09-25
- URL : https://wpmoderne.dev.wordpress-developpement.fr/lexique/injection-sql/

Quand une requête SQL est construite en concaténant directement une valeur saisie par l'utilisateur, cette valeur peut contenir des fragments de syntaxe SQL qui altèrent la requête d'origine, un peu comme glisser une phrase supplémentaire dans un formulaire administratif pour qu'elle soit lue comme une instruction officielle plutôt qu'une simple donnée.

## Protection dans WordPress

La classe `$wpdb` fournit la méthode `prepare()`, qui sépare strictement la structure de la requête des valeurs qui y sont injectées, ces dernières étant automatiquement échappées selon leur type (`%s` pour une chaîne, `%d` pour un entier). C'est la méthode recommandée dès qu'une requête personnalisée intègre une donnée externe.

## Exemple

```
global $wpdb;

// vulnérable : concaténation directe
$wpdb->query("SELECT * FROM {$wpdb->posts} WHERE post_title = '$titre'");

// sécurisé : requête préparée
$sql = $wpdb->prepare(
    "SELECT * FROM {$wpdb->posts} WHERE post_title = %s",
    $titre
);
$wpdb->get_results($sql);
```

## Pièges fréquents

Beaucoup pensent à protéger le champ texte évident d'un formulaire, mais oublient un paramètre d'URL utilisé tel quel dans une clause `ORDER BY` ou `LIMIT` : ces emplacements échappent parfois au réflexe d'échappement car ils ne semblent pas provenir « directement » d'une saisie utilisateur. Toute valeur qui entre dans une requête SQL sans passer par `prepare()` doit être considérée comme un point d'entrée potentiel, quelle que soit son origine apparente, y compris un identifiant de colonne dynamique qui ne peut pas être substitué par un simple marqueur `%s` et doit être validé contre une liste blanche de noms autorisés.
