TL; DR
- L'application accepte l'entrée, dans ce cas «Nancy», sans tenter de - aseptiser l'entrée, par exemple en échappant les caractères spéciaux
école => INSÉRER LES VALEURS des élèves ( «Nancy» ); INSÉRER 0 1
- l' injection SQL se produit lorsque l' entrée dans une commande de base de données est manipulée pour - la cause du serveur de base de données pour exécuter SQL arbitraire
école => INSERT INTO étudiants VALEURS ( « Robert » ); Étudiants DROP TABLE ; - '); INSÉRER 0 1 TABLEAU DROP
- Les dossiers des étudiants ont maintenant disparu - cela aurait pu être encore pire!
école => CHOISIR * DES ÉTUDIANTS ;
ERREUR : relation « étudiants » ne pas exister
LIGNE 1 : CHOISIR * DES ÉTUDIANTS ; ^
Cela supprime (supprime) la table des étudiants.
( Tous les exemples de code de cette réponse ont été exécutés sur un serveur de base de données PostgreSQL 9.1.2. )
Pour clarifier ce qui se passe, essayons ceci avec un simple tableau contenant uniquement le champ de nom et ajoutons une seule ligne:
école => CREATE TABLE élèves ( nom TEXTE PRINCIPAL CLES );
AVIS : CREATE TABLE / PRIMAIRE KEY va créer implicite index "students_pkey" pour la table "élèves" CREATE TABLE
école => INSERT INTO étudiants VALEURS ( 'John' ); INSÉRER 0 1
Supposons que l'application utilise le SQL suivant pour insérer des données dans la table:
INSÉRER DANS LES VALEURS des élèves ( «foobar» );
Remplacez foobar
par le nom réel de l'élève. Une opération d'insertion normale ressemblerait à ceci:
- Input:
école de Nancy => INSÉRER LES VALEURS des élèves ( 'Nancy' ); INSÉRER 0 1
Lorsque nous interrogeons la table, nous obtenons ceci:
école => CHOISIR * DES ÉTUDIANTS ;
Nom
-------
John
Nancy
( 2 rangées )
Que se passe-t-il lorsque nous insérons le nom de Little Bobby Tables dans la table?
- Entrée: Robert '); Étudiants DROP TABLE; -
école => INSÉRER LES VALEURS des élèves ( «Robert» ); Étudiants DROP TABLE ; - '); INSÉRER 0 1 TABLEAU DROP
L'injection SQL ici est le résultat du nom de l'élève qui termine l'instruction et inclut une DROP TABLE
commande distincte ; les deux tirets à la fin de l'entrée sont destinés à commenter tout code restant qui autrement provoquerait une erreur. La dernière ligne de la sortie confirme que le serveur de base de données a supprimé la table.
Il est important de noter que pendant l' INSERT
opération, l'application ne vérifie pas la présence de caractères spéciaux dans l'entrée et permet donc la saisie arbitraire dans la commande SQL. Cela signifie qu'un utilisateur malveillant peut insérer, dans un champ normalement destiné à la saisie par l'utilisateur, des symboles spéciaux tels que des guillemets avec du code SQL arbitraire pour obliger le système de base de données à l'exécuter, d'où l' injection SQL .
Le résultat?
école => CHOISIR * DES ÉTUDIANTS ;
ERREUR : relation « étudiants » ne pas exister
LIGNE 1 : CHOISIR * DES ÉTUDIANTS ; ^
L'injection SQL est l'équivalent dans la base de données d'une vulnérabilité d' exécution de code arbitraire à distance dans un système d'exploitation ou une application. L'impact potentiel d'une attaque par injection SQL réussie ne peut pas être sous-estimé - selon le système de base de données et la configuration de l'application, il peut être utilisé par un attaquant pour provoquer une perte de données (comme dans ce cas), obtenir un accès non autorisé aux données, ou même exécuter code arbitraire sur la machine hôte elle-même.
Comme indiqué par la bande dessinée XKCD, une façon de se protéger contre les attaques par injection SQL consiste à assainir les entrées de la base de données, par exemple en échappant les caractères spéciaux, afin qu'elles ne puissent pas modifier la commande SQL sous-jacente et ne puissent donc pas provoquer l'exécution de code SQL arbitraire. Si vous utilisez des requêtes paramétrées, par exemple en utilisant SqlParameter
dans ADO.NET, l'entrée sera, au minimum, automatiquement filtrée pour se prémunir contre l'injection SQL.
Cependant, le nettoyage des entrées au niveau de l'application peut ne pas arrêter des techniques d'injection SQL plus avancées. Par exemple, il existe des moyens de contourner la mysql_real_escape_string
fonction PHP . Pour plus de protection, de nombreux systèmes de base de données prennent en charge les instructions préparées . Si elles sont correctement implémentées dans le backend, les instructions préparées peuvent rendre l'injection SQL impossible en traitant les entrées de données comme sémantiquement distinctes du reste de la commande.