FlawOpen

flawopen.com/SQL Injection/L’échappement suffit-il ?

Échapper les guillemets empêche-t-il SQL Injection ?

CWE-89: SQL InjectionReference page
Réponse courte

En général, non. Une fonction d’échappement dépend de la base de données, du jeu de caractères de la connexion, du mode SQL et du contexte exact des guillemets. Les requêtes paramétrées maintiennent les valeurs hors de la syntaxe SQL via l’API du pilote. Paramétrez les valeurs ; pour les identifiants dynamiques non paramétrables, choisissez une option dans une liste blanche définie par l’application.

Pourquoi l’échappement est fragile en pratique

Le jeu de caractères de connexion influe sur l’échappement

L’échappement n’est pas un remplacement de texte indépendant du contexte. MySQL précise que mysql_real_escape_string() utilise le jeu de caractères de la connexion et que SET NAMES ne met pas à jour l’état de la bibliothèque cliente utilisé par cette fonction. Un décalage peut invalider les hypothèses sur le texte échappé. Préférez les API paramétrées ; si du code ancien doit encore échapper des valeurs, utilisez l’API du pilote avec le jeu de caractères configuré par la fonction prise en charge et gérez les erreurs.

Un appel oublié fragilise toute la défense

L’échappement doit être appliqué correctement à chaque interpolation, avec le bon pilote, jeu de caractères, mode SQL et contexte de littéral. Les API paramétrées rendent la séparation valeur/donnée explicite et évitent de construire manuellement une chaîne entre guillemets.

Les guillemets ne couvrent pas tous les contextes SQL

L’échappement des guillemets ne traite que les caractères d’un littéral de chaîne donné. Il ne construit pas sûrement un nom de colonne ou de table, un mot-clé ou un sens de tri, et ne protège pas une entrée dans une expression numérique non citée. Paramétrez les valeurs et associez la structure dynamique à des options fixes de l’application.

VULNERABLE
// L’entrée utilisateur est interpolée dans la syntaxe SQL
query = f"SELECT id FROM users WHERE name = '{name}'"
cursor.execute(query)
HARDENED
// Le pilote lie name comme valeur de données
cursor.execute(
    "SELECT id FROM users WHERE name = ?",
    (name,),
)

Ce que change la liaison des paramètres

Une requête paramétrée transmet la structure SQL et les valeurs comme entrées séparées via l’API de base de données. Les pilotes peuvent utiliser des instructions préparées natives ou une autre implémentation sûre ; ne présumez pas d’un échange précis sur le protocole. La garantie est que la valeur reste une donnée et n’est pas réinterprétée comme syntaxe SQL. Avec Python DB-API, utilisez le marqueur propre au pilote et transmettez les valeurs séparément ; ne construisez pas la requête par formatage de chaîne.

Liste de contrôle technique

Questions fréquentes

L’échappement peut-il encore être approprié ?

Pour les identifiants ou fragments SQL non paramétrables, utilisez uniquement une API de citation prise en charge par le pilote avec une liste blanche fixe de l’application. Évitez l’échappement générique de valeurs arbitraires.

Une fonction d’échappement maintenue par le pilote est-elle sûre ?

Elle peut aider dans le contexte documenté, mais dépend encore du moteur, des paramètres de connexion, du contexte de citation et de son usage à chaque appel. Les requêtes paramétrées restent le choix par défaut le plus sûr pour les valeurs.

Références

À voir aussi Injection SQL (CWE-89) : fonctionnement et prévention dans chaque langage — flawopen.com Utiliser un ORM suffit-il à prévenir l'injection SQL ? Knex.js protège-t-il contre les injections SQL ? MyBatis ${} et #{} : prévenir la SQL Injection MySQLi vs PDO : prepared statements sûres NHibernate protège-t-il contre les injections SQL ? Injection NoSQL MongoDB : filtres sûrs