Portail de l'informatique
Objectif de ce knol
Qu’est-ce que l’injection SQL ?
Une manière de travailler consiste à concaténer, c’est-à-dire à assembler morceau par morceau ces instructions.
Lorsqu’un utilisateur se connecte à un site web, ou clique sur un lien dynamique, des informations précises sont passées à la base de données par ce moyen:
- Login, mot de passe et diverses informations de connections.
- Numéro de compte, identifiants divers.
- Mots clés dans un moteur de recherche.
Or, le SQL, comme tout langage informatique, considère certains caractères comme spéciaux.
Lorsque le risque « injection SQL » n’a pas été traité lors de la conception d’un site web, ces caractères spéciaux sont interprétés comme des éléments d’instruction pour la base de données.
On a donc la possibilité que ce que saisie un utilisateur du site modifie ponctuellement le programme du site Web.
Quels sont les risques ?
Le risque fondamental est donc le suivant : un utilisateur peut se retrouver en situation de modifier le code, le programme du site. Ce risque fondamental se décline en plusieurs cas de figures.
Dans la très grande majorité des cas, l’interprétation des caractères spéciaux donne lieu à une erreur, l’application « plante ». C’est d’abord un risque de fiabilité dont l’origine peut être accidentelle.
Si l’opérateur est suffisamment adroit, le code fonctionne et il modifie le comportement de l’application. On a alors des risques de vulnérabilité liée à un comportement malveillant ou intrusif :
- Usurpation d’identité
- Contournement de règles de gestion
- Altération de données.
Enfin on verra que l’affichage des erreurs en production est un facteur aggravant.
Le risque de non fiabilité du site
Un des caractères spécifiques de l’injection SQL est l’apostrophe « ’ ». On trouve ce caractère dans le langage courant, ainsi que dans de nombreux patronymes.
Lorsque la faille d’injection SQL est présente, la simple utilisation d’un patronyme tel que « N’Guyen » ou « d’Astorg » provoque une erreur. Soit le site ne fonctionne pas du tout soit les données saisies sont mal enregistrées.
Dans tout les cas c’est un dysfonctionnement et généralement perçu comme tel par les utilisateurs.
Ce cas se produit rarement parce qu’un tel dysfonctionnement donne rapidement lieu à réclamation des utilisateurs. En fait, ce genre de problème est généralement découvert lors des tests.
Si ce type de problèmes apparaît lors de tests il doit inciter à se poser la question d’un éventuel problème plus grave de sécurité.
Si un tel bug est présent sur un site production, c’est une indication forte pour un éventuel acteur malveillant.
Usurpation d’identité
Lorsque la page d’authentification d’un site est sensible à l’injection SQL, il est très facile de se connecter sans aucun droit ni autorisation.
Une chaîne de quelques caractères le permet le plus souvent. Cf. Exemples techniques en fin d'article.
Contournement des règles de gestions.
Supposons qu’une page qui fournit des informations différentes selon les utilisateurs soit vulnérable à l’injection SQL. Dans ce cas un opérateur malveillant peut obtenir des informations qu’il n’est pas sensé avoir. Cf. Exemples techniques
Alteration de données.
Toujours dans le cas d’une page sensible à l’injection SQL, et dans le cas l’application est conçue pour mettre à jour certaines données. Un opérateur peut se servir de la faille pour modifier ou supprimer des données de ce type de manière arbitraire. Cf. Exemples techniques
Les risques agravants: l’affichage d’erreurs
L’affichage d’erreur est une technique en principe réservée à la période de développement d’une application. Lorsque elle est présente en production elle augmente les risques liés à l’injection SQL car elle donne des informations à un éventuel utilisateur malveillant.
Qu’est ce que l’affichage d’erreur sur un site web?
Sur un site web les erreurs ou encore exceptions, se produisent nécessairement à un moment ou a un autre, la nature même de l’architecture web oblige à les prendre en compte.
En phase de développement de nombreuses erreurs se produisent, cela fait partie intégrante du cycle de développement. Pour gérer ces erreurs, les développeurs mettent en place des systèmes qui permettent de mieux les comprendre :
Lorsqu’une erreur se produit on affiche un texte qui décrit cette erreur et dans quel les condition elle s’est produite.
Par nature il s’agit d’informations :
- Sur le programme et la technologie précise utilisée.
- La chaîne SQL dans le cas de l’utilisation d’une base de donnée.
- L’état du serveur de web.
Il est tout à fait normal de mettre en place un tel système, pendant les phases de développement et de recette d’un site web. Cependant, c’est une erreur et une faille de sécurité de laisser ce dispositif en place lorsque l’application est en production.
En phase de production d’un site web la bonne gestion d’une erreur n’est pas d’afficher des informations la concernant à l’utilisateur.
La bonne démarche est de rediriger ces informations vers la personne qu’elle concerne : le responsable technique du site. Cela se fait couramment à l'aide d' un fichier journal ou « log ».
Pourquoi est-ce particulièrement aggravant dans le cas de l’injection SQL ?
Dans le cas de l’injection SQL, imaginons qu’un utilisateur vienne de saisir volontairement ou non un caractère spécial SQL. Il se retrouve devant une telle page d’erreur.
Quelqu’un qui ignore tout de la programmation aura juste une mauvaise impression et un avis défavorable sur le site.
Quelqu’un avec des connaissances SQL et au courant de l’existence de cette faille, obtient des informations précises sur la manière dont l’opération qu’il vient de faire est traitée par le site.
D’une part, en répétant cette opération en divers point de l’application, il peut obtenir une vue globale de l’application, sa structure et ses ressources.
D’autre part il obtient des informations sur la syntaxe exacte SQL utilisée. Cette information lui permet de comprendre comment seront interprétées les caractères spéciaux qu’il saisis et même de « déboguer » sont propre code injecté.
Comment s’en protéger ?
Pertinence d’une demarche sur ce risque
Pertinence selon la technologie du site.
Plus que la technologie utilisée, ce sont les méthodes de programmation et le comportement d’exploitation qui font la robustesse ou la faiblesse des sites dans ce domaine.
Ce qui donne le paradoxe que des sites web programmés en PHP ou en ASP ancienne génération, technologies sensées être plus permissives sont parfois plus robustes que d’autres qui utilisent des API plus modernes mais à mauvais escient.
Pertinence selon la typologie du site.
La sécurité d’une application doit être à l’aune de l’importance de l’application elle-même.
Il convient donc avant toute chose de bien cibler l’intérêt d’une démarche de sécurité de ce type.
Peut être que le l’analyse devrait se borner à la page d’authentification ou à une portion du site.
D’autre part la sécurité d’une application est un ensemble peut être que d’autre aspects sont prioritaires du fait par exemple du mode de connexion et de la population visée.
En cours d’analyse fonctionnelle
Lorsqu’une application est en court de conception et que l’on souhaite explicitement éviter l’injection SQL, il est souhaitable d’exprimer cette exigence dans le cahier des charges, par exemple de cette manière:
« Robuste à l’injection SQL , notamment les caractères de types « ‘ » , « -- » (non exhaustivement) saisis par les utilisateurs ne sont pas interprétés par le SGBD comme des délimiteurs de chaîne ou comme des délimiteur de commentaire SQL., ou tout autre opérateur du langage SQL »
Cette démarche peut compléter tout autre exigence sur la sécurité et ne saurait s’y substituer.
En cours de développement
Deux cas de figure se présentent.
Premier cas. L’environnement technique fourni à l’équipe de développement des outils logiciels qui traite le problème. Par exemple ADO .Net de Microsoft et Hibernate sous JAVA permettent de passer les informations saisies par les utilisateurs via un système de paramètres.
La simple bonne utilisation de ces systèmes exclue la quasi-totalité des problèmes d’injection. Il suffit d’exclure la concaténation pour l’insertion de paramètres dans les chaînes SQL et d’utiliser les objets de paramètres.
Deuxième cas. Le langage ou la technologie utilisés n’intègrent pas cette problématique.
Dans ce cas, la concaténation de chaîne SQL ou des pratiques équivalentes sont incontournables. Il faut donc avoir une démarche active lors de la programmation.
Cette démarche active passe par la maîtrise des types de données :
Les solutions sont variées et peuvent dépendre étroitement du SGBD et de la localisation de l’application. La logique en sera cependant toujours la même et répondra aux questions suivante.
- Qu’est sensé contenir ce paramètre passé par l’utilisateur?
- Que faire des caractères spécifiques qui pourraient altérer son traitement ?
En phase de test
On pourra inclure dans le plan de test l’élément suivant :
« Tester que l’utilisation des caractères spéciaux ne provoque ni erreur ni comportement imprévu » sur toutes les pages concernées.
Un exemple de liste de caractères à tester (liste non exhaustive que l’on adaptera en fonction des SGBD):
‘
--
/*
*/
%
.
Attention dans le cas ou ces test échouent, ils peuvent altérer les données. Il convient donc de les effectuer précautionneusement et en connaissance de cause.
En phase de production
En production la première chose à faire est de s’assurer que les erreurs et exceptions ne sont pas retournées à l’utilisateur. Au contraire ces informations doivent être à la disposition unique du web master. On pourra mettre en place des journaux d’erreur et les consulter régulièrement. On pourra aussi mettre en œuvre l’envoi de mails automatisés lors d’erreurs particulières.
Remarque :
En cours de production, il n’est pas du tout recommandé d’effectué des tests tel que ceux évoqués dans le paragraphe précédent.
Si la saisie accidentelle d’un caractère spécial provoque une erreur ou si un doute existe, il convient de faire analyser le code et d’effectuer des tests dans un environnement dédié ou l’altération des données est tolérable.
Exemples techniques
Usurpation d’identité
Imaginons que l’authentification se passe de la manière suivante sur un site :
- Les login & mot de passe sont stockés dans une table « utilisateur » de la base de donnée.
- Lorsque l’on se connecte au site, une chaîne SQL est construite à partir du login et du mot de passe que l’utilisateur saisi. Elle peut ressembler à ceci :
« select NiveauDeDroit from Utilisateur where login=’LoginSaisi’ and MotDePasse =’MotDepasseSaisi’ »
Imaginons a présent que l’on saisisse le couple login mot de passe suivant :
Login : ’ or ’’=’
Mot de Passe : UneChaineQuelconque
La chaîne SQL générée est alors
« select NiveauDeDroit from Utilisateur where login=’’ or ’’=’’ and MotDePasse =’UneChaineQuelconque’ »
Cette instruction SQL renvoie toutes les lignes de la table « utilisateur » ce qui se traduit par le fait que le premier utilisateur renvoyé de la base est attribué arbitrairement.Contournement des règles de gestions.
Supposons qu’un site web d’informations mette à disposition de tout le monde certains articles et que seul les abonnés puissent accéder aux articles de plus d’une semaine.
Une page permet de rechercher les articles par un mot clé sur le titre.
Une requête SQL générée sur cette page pourrait être :
« Select titre, contenu, date from articles where date >‘4-06-2009’ and titre like ’%MotcleSaisi%’»
Imaginons que l’on saisisse le « mot clé » suivant :
’ or ’’ %’=’
La chaîne SQL générée est la suivante :
« Select titre, contenu, date from articles where date >'4-06-20092008’ and titre like ’’ %’ or ’’ %’=’%’»
Alteration de données.
Supposons qu’une page du site permette la mise a jour d’informations par exemple modifier les noms et prénom d’un utilisateur.
Une syntaxe générée peut être :
« update Utilisateur set nom = ’NouveauNomSaisi’, prenom = ’NouveauPrenomSaisi’ Where id_utilisateur = 3924 »
On suppose encore que cette chaîne soit sans retour chariot.
Imaginons à présent que les nouveaux nom et prénom saisis soient les suivants :
Nom : ‘ -–
Prénom : ChaineQuelconque
Le SQL généré est le suivant :
« update Utilisateur set nom = ’’ --’, prenom = ’NouveauPrenomSaisi’ Where id_utilisateur = 3924 »
Cette chaîne, contrairement aux apparences ne met pas a jour une ligne dans la base. En fait, à cause du double tiret « -- » elle est équivalente à :
« update Utilisateur set nom = ’’ »
Ce qui met à vide le nom de tous les utilisateurs.





Guillaume Gaubert
Inviter en tant qu'auteur
Majuscules
Par contre, il serait préférable de mettre les instructions SQL (SELECT, UPDATE, INSERT, ...) en majuscules, pour un code plus propre.
Emilien Mayot
Inviter en tant qu'auteur
Article intéressant
La dernière requête fait vraiment peur !
Quand je programmerai je ferai dorénavant attention à deux choses :
- utiliser des fonctions pour prévenir ce risque d'injection...
- utiliser des noms de tables et d'attributs peu communs !
@+.
ModifierEnregistrerAnnulerSupprimerSupprimerBloquer cet utilisateurSignaler des commentaires inappropriésMasquer la fenêtre de rapport