Menu

Injection SQL : Qu'est-ce que c'est ?

6 min de lecture Mis à jour le 02 Avr 2026

Définition

L'injection SQL est une attaque qui exploite des failles dans la gestion des entrées utilisateur pour exécuter des commandes SQL arbitraires sur la base de données d'une application. L'ORM de Django protège nativement contre cette vulnérabilité en paramétrant automatiquement les requêtes, mais la vigilance reste nécessaire avec les requêtes SQL brutes.

Qu'est-ce que l'injection SQL ?

L'injection SQL (SQLi) est une technique d'attaque qui consiste à insérer du code SQL malveillant dans les champs de saisie d'une application web pour manipuler la base de données sous-jacente. Cette vulnérabilité survient lorsque les données fournies par l'utilisateur sont intégrées directement dans une requête SQL sans validation ni échappement approprié. L'attaquant peut alors lire, modifier ou supprimer des données, voire prendre le contrôle complet du serveur de base de données.

L'injection SQL est classée en première position du Top 10 OWASP des vulnérabilités web les plus critiques depuis des années. Malgré l'ancienneté de cette menace et l'existence de protections efficaces, elle reste l'une des failles les plus couramment découvertes lors d'audits de sécurité. La raison est simple : toute application qui interagit avec une base de données relationnelle (PostgreSQL, MySQL, SQLite) est potentiellement exposée si les requêtes ne sont pas correctement paramétrées.

Dans le contexte belge et européen, une injection SQL réussie peut entraîner une fuite massive de données personnelles, constituant une violation du RGPD avec des conséquences juridiques et financières lourdes. Les bases de données contiennent souvent les actifs les plus sensibles d'une entreprise : informations clients, données financières, propriété intellectuelle.

Pourquoi l'injection SQL est importante

L'injection SQL représente l'une des menaces les plus graves pour les applications web et les systèmes d'information. Ses conséquences potentielles justifient une attention particulière.

  • Accès non autorisé aux données : un attaquant peut extraire l'intégralité des tables de la base de données, y compris les identifiants, mots de passe hachés, informations personnelles et données financières.
  • Modification et suppression de données : les instructions INSERT, UPDATE et DELETE injectées peuvent corrompre ou détruire des données métier critiques, sans possibilité de récupération si les sauvegardes ne sont pas en place.
  • Contournement d'authentification : une injection classique comme ' OR 1=1 -- dans un champ de connexion peut contourner la vérification du mot de passe et donner accès à n'importe quel compte utilisateur.
  • Escalade de privilèges : depuis la base de données, un attaquant peut parfois exécuter des commandes système (via xp_cmdshell sur SQL Server ou COPY sur PostgreSQL), compromettant le serveur entier.
  • Protection native par l'ORM Django : l'ORM (Object-Relational Mapping) de Django paramètre automatiquement toutes les requêtes, séparant strictement le code SQL des données utilisateur, ce qui élimine le risque d'injection dans les requêtes standard.

Comment ça fonctionne

Le mécanisme d'une injection SQL repose sur la confusion entre le code SQL et les données utilisateur. Prenons une requête vulnérable construite par concaténation de chaînes : query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'". Si un attaquant entre admin' -- comme nom d'utilisateur, la requête devient SELECT * FROM users WHERE username = 'admin' --' AND password = ''. Le double tiret commente le reste de la requête, annulant la vérification du mot de passe.

Les injections plus avancées exploitent les opérateurs UNION pour combiner les résultats de requêtes additionnelles, les sous-requêtes pour extraire des données de tables non accessibles normalement, et les techniques d'injection aveugle (blind SQLi) qui déduisent des informations à partir du comportement de l'application (temps de réponse, messages d'erreur) sans voir directement les résultats.

La protection fondamentale est l'utilisation de requêtes paramétrées (prepared statements). Au lieu de concaténer les données dans la requête SQL, on utilise des marqueurs de position que le moteur de base de données remplit de manière sécurisée : cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", [username, password]). L'ORM de Django applique ce principe automatiquement : User.objects.filter(username=username) génère une requête paramétrée sans aucune possibilité d'injection. Le danger subsiste uniquement lorsque les développeurs utilisent raw(), extra() ou cursor.execute() avec des données non paramétrées.

Exemple concret

Chez Kern-IT, nous développons des plateformes métier avec Django et PostgreSQL pour des clients qui manipulent des données sensibles. Dans un projet pour le secteur de la santé (healthtech), la base de données contient des informations de patients protégées par le RGPD et le secret médical. L'ensemble des accès aux données passe par l'ORM Django, garantissant le paramétrage automatique de toutes les requêtes.

Pour les cas nécessitant des requêtes géospatiales complexes avec PostGIS (dans le cadre de KERN MAP), nous utilisons les fonctions spatiales de GeoDjango qui génèrent également des requêtes paramétrées. Lorsqu'une requête SQL brute est inévitable pour des raisons de performance, nous appliquons systématiquement le paramétrage via cursor.execute(sql, params) et jamais la concaténation de chaînes. Les revues de code incluent une vérification spécifique de toute utilisation de raw() ou extra() pour s'assurer que les paramètres sont correctement gérés.

Mise en oeuvre

  1. Utiliser l'ORM systématiquement : privilégiez les méthodes de l'ORM Django (filter, exclude, annotate, aggregate) pour toutes les interactions avec la base de données. Elles génèrent automatiquement des requêtes paramétrées.
  2. Paramétrer les requêtes brutes : si vous devez utiliser raw() ou cursor.execute(), passez toujours les données utilisateur via le paramètre params et jamais par concaténation ou formatage de chaînes.
  3. Valider les entrées : appliquez une validation stricte côté serveur sur toutes les données utilisateur (type, longueur, format, valeurs autorisées) avant de les utiliser dans une requête, même paramétrée.
  4. Appliquer le principe du moindre privilège : configurez l'utilisateur de base de données de l'application avec les permissions minimales nécessaires. Pas de droits DROP, GRANT ou d'exécution de commandes système.
  5. Activer le logging des requêtes : en développement, activez le logging SQL de Django pour détecter les requêtes non paramétrées. En production, surveillez les requêtes anormales via les logs PostgreSQL.
  6. Scanner avec sqlmap : utilisez sqlmap ou OWASP ZAP en environnement de test pour vérifier qu'aucun point d'entrée n'est vulnérable à l'injection SQL.

Technologies et outils associés

  • Django ORM : couche d'abstraction de base de données qui paramètre automatiquement les requêtes SQL, protection native contre l'injection.
  • PostgreSQL : SGBD relationnel qui supporte les requêtes préparées et offre un contrôle d'accès granulaire (Row Level Security).
  • sqlmap : outil open source de détection et d'exploitation automatisée des injections SQL, utilisé en test de pénétration.
  • OWASP ZAP : scanner de sécurité web qui détecte les points d'injection SQL dans les formulaires et paramètres d'URL.
  • django-debug-toolbar : outil de développement qui affiche les requêtes SQL exécutées, permettant de vérifier le paramétrage.
  • WAF (Web Application Firewall) : pare-feu applicatif qui filtre les requêtes contenant des motifs d'injection SQL avant qu'elles n'atteignent l'application.

Conclusion

L'injection SQL reste l'une des vulnérabilités les plus dévastatrices pour les applications web, mais les frameworks modernes comme Django offrent une protection native efficace via leur ORM. La clé est la discipline : utiliser l'ORM systématiquement, paramétrer scrupuleusement les requêtes brutes inévitables, et valider rigoureusement toutes les entrées utilisateur. Chez Kern-IT, nous appliquons ces principes dans toutes nos applications Django, de nos plateformes métier à KERN MAP, garantissant la sécurité des données de nos clients belges conformément aux standards OWASP et aux exigences du RGPD.

Conseil Pro

Activez LOGGING pour les requêtes SQL en développement avec 'django.db.backends' au niveau DEBUG. Cela vous permettra de voir exactement les requêtes générées par l'ORM et de repérer immédiatement toute requête construite par concaténation qui aurait échappé à la revue de code.

Un projet en tête ?

Discutons de comment nous pouvons vous aider à concrétiser vos idées.