TL;DR
\-- The application accepts input, in this case 'Nancy', without attempting to
-- sanitize the input, such as by escaping special characters
school=> INSERT INTO students VALUES ('Nancy');
INSERT 0 1
-- SQL injection occurs when input into a database command is manipulated to
-- cause the database server to execute arbitrary SQL
school=> INSERT INTO students VALUES ('Robert'); DROP TABLE students; --');
INSERT 0 1
DROP TABLE
-- The student records are now gone - it could have been even worse!
school=> SELECT \* FROM students;
ERROR: relation "students" does not exist
LINE 1: SELECT \* FROM students;
^
Cela supprime la table des étudiants.
( Tous les exemples de code dans cette réponse ont été exécutés sur un serveur de base de données PostgreSQL 9.1.2. )
Pour bien comprendre ce qui se passe, essayons avec un tableau simple contenant uniquement le champ nom et ajoutons une seule ligne :
school=> CREATE TABLE students (name TEXT PRIMARY KEY);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "students\_pkey" for table "students"
CREATE TABLE
school=> INSERT INTO students VALUES ('John');
INSERT 0 1
Supposons que l'application utilise le SQL suivant pour insérer des données dans la table :
INSERT INTO students VALUES ('foobar');
Remplacer foobar
avec le nom réel de l'étudiant. Une opération d'insertion normale ressemblerait à ceci :
\-- Input: Nancy
school=> INSERT INTO students VALUES ('Nancy');
INSERT 0 1
Lorsque nous interrogeons la table, nous obtenons ceci :
school=> SELECT \* FROM students;
name
-------
John
Nancy
(2 rows)
Que se passe-t-il quand on insère le nom de Little Bobby Tables dans le tableau ?
\-- Input: Robert'); DROP TABLE students; --
school=> INSERT INTO students VALUES ('Robert'); DROP TABLE students; --');
INSERT 0 1
DROP TABLE
L'injection SQL ici est le résultat du nom de l'étudiant terminant la déclaration et incluant un séparé DROP TABLE
Les deux tirets à la fin de l'entrée sont destinés à commenter tout code restant qui pourrait causer une erreur. La dernière ligne de la sortie confirme que le serveur de la base de données a abandonné la table.
Il est important de noter que pendant la INSERT
l'application ne vérifie pas la présence de caractères spéciaux dans la saisie et autorise donc la saisie de données arbitraires 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 ainsi qu'un code SQL arbitraire pour que le système de base de données l'exécute, d'où SQL injection .
Le résultat ?
school=> SELECT \* FROM students;
ERROR: relation "students" does not exist
LINE 1: SELECT \* FROM students;
^
L'injection SQL est l'équivalent pour la base de données d'une attaque à distance exécution de code arbitraire vulnérabilité dans un système d'exploitation ou une application. L'impact potentiel d'une attaque par injection SQL réussie ne doit pas être sous-estimé. Selon la configuration du système de base de données et de l'application, un attaquant peut l'utiliser pour provoquer une perte de données (comme dans le cas présent), obtenir un accès non autorisé aux données, voire exécuter un code arbitraire sur la machine hôte elle-même.
Comme l'indique la bande dessinée XKCD, l'un des moyens de se protéger contre les attaques par injection SQL consiste à nettoyer 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 donc provoquer l'exécution d'un code SQL arbitraire. Cela peut être fait au niveau de l'application, et certaines implémentations de requêtes paramétrées fonctionnent en aseptisant les entrées.
Cependant, l'assainissement des entrées au niveau de l'application peut ne pas arrêter les techniques d'injection SQL plus avancées. Par exemple, il existe des moyens de contourner le mysql_real_escape_string
Fonction PHP . Pour une protection supplémentaire, de nombreux systèmes de bases de données prennent en charge déclarations préparées . Si elles sont correctement mises en œuvre 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 séparées du reste de la commande.
18 votes
Si vous écoutez Podcast Stack Overflow n°31 (27 novembre 2008), ils en parlent en fait.
102 votes
Dans MySQL,
'
n'est pas pour commentaires . Même s'il l'était, il n'y a pas d'espace avant lui, il ne peut donc que terminer la chaîne qui le précède.52 votes
En ce qui concerne XKCD, si vous avez des questions sur certains des comics, vous pouvez toujours aller sur Expliquer XKCD et vous aurez votre réponse. Il y a même un XKCD wiki ce qui est très utile pour certaines bandes dessinées difficiles comme XKCD geohashing
0 votes
Une façon d'éviter cela serait d'échapper tous les caractères spéciaux avant de les utiliser dans la requête. Une autre solution consiste à utiliser des instructions préparées ou à s'assurer que vous exécutez une seule et unique requête à la fois.
16 votes
Je crois que ce lien doit être enregistré ici : bobby-tables.com
1 votes
L'édition récente est tout à fait erronée, car elle a retiré le mot clé XKCD du titre.
0 votes
C'est une injection SQL. Ils finissent la première instruction puis en exécutent une seconde qui supprime la table.
5 votes
beta.companieshouse.gov.uk/company/10542519 est l'enregistrement d'une société de conseil nommée ; DROP TABLE "COMPANIES";-- LTD
3 votes
Le comique est légèrement grinçant parce que tu ne devrais pas désinfecter les entrées de la base de données, vous devez paramétrer pour que ça n'ait pas d'importance ce que ils le sont. Les Sanitzers peuvent avoir des bogues. Les requêtes paramétrées contournent toute la question.