En regardant simplement:
(Source: https://xkcd.com/327/ )
Que fait ce SQL:
Robert'); DROP TABLE STUDENTS; --
Je connais les deux '
et je suis --
pour les commentaires, mais le mot n'est-il pas DROP
aussi commenté puisqu'il fait partie de la même ligne?
security
validation
sql-injection
Blankman
la source
la source
'
n'est pas pour les commentaires . Même si c'était le cas, il n'y a pas d'espace avant, donc il ne peut que terminer la chaîne qui le précède.Réponses:
Il laisse tomber la table des étudiants.
Le code d'origine du programme de l'école ressemble probablement à quelque chose comme
C'est la façon naïve d'ajouter une entrée de texte dans une requête, et c'est très mauvais , comme vous le verrez.
Après que les valeurs du prénom, de la zone de texte du deuxième prénom FNMName.Text (qui est
Robert'); DROP TABLE STUDENTS; --
) et du nom de la zone de texte LName.Text (appelons-leDerper
) sont concaténées avec le reste de la requête, le résultat est maintenant en fait deux requêtes séparées par le terminateur d'instruction (point-virgule). La deuxième requête a été injectée dans la première. Lorsque le code exécute cette requête sur la base de données, il ressemblera à ceciqui, en anglais simple, se traduit grosso modo par les deux requêtes:
et
Tout ce qui est passé la deuxième requête est marqué comme un commentaire :
--', 'Derper')
Le nom
'
de l'élève n'est pas un commentaire, c'est le délimiteur de la chaîne de fermeture . Étant donné que le nom de l'élève est une chaîne, il est nécessaire syntaxiquement pour terminer la requête hypothétique. Les attaques par injection ne fonctionnent que lorsque la requête SQL qu'elles injectent aboutit à un SQL valide .Modifié à nouveau selon le commentaire astucieux de dan04
la source
INSERT
, alors la parenthèse aurait plus de sens. Cela expliquerait également pourquoi la connexion à la base de données n'est pas en mode lecture seule.INSERT
. En y repensant, leSELECT
ne fonctionnerait pas de toute façon car l'insertion des petites tables Bobby dans le tableau aurait déjà laissé tomber le tableau.Students
attend plus qu'une seule colonne (l'instruction d'origine / correcte a fourni deux colonnes). Cela dit, la présence de la deuxième colonne est utile pour montrer pourquoi les commentaires sont nécessaires; et comme on ne peut pas changer le nom de Bobby, il vaut probablement mieux laisser tel quel avec un peu plus que cette observation en note de bas de page.Disons que le nom a été utilisé dans une variable
$Name
.Vous exécutez ensuite cette requête :
Le code place par erreur tout ce que l'utilisateur a fourni comme variable.
Vous vouliez que le SQL soit:
Mais un utilisateur intelligent peut fournir ce qu'il veut:
Vous obtenez:
Le
--
seul commentaire le reste de la ligne.la source
Comme tout le monde l'a déjà souligné, le
');
ferme la déclaration d'origine, puis une deuxième déclaration suit. La plupart des frameworks, y compris des langages comme PHP, ont désormais des paramètres de sécurité par défaut qui ne permettent pas plusieurs instructions dans une même chaîne SQL. En PHP, par exemple, vous ne pouvez exécuter que plusieurs instructions dans une chaîne SQL en utilisant lamysqli_multi_query
fonction.Vous pouvez cependant manipuler une instruction SQL existante via l'injection SQL sans avoir à ajouter une deuxième instruction. Disons que vous avez un système de connexion qui vérifie un nom d'utilisateur et un mot de passe avec cette simple sélection:
Si vous fournissez
peter
le nom d'utilisateur etsecret
le mot de passe, la chaîne SQL résultante ressemblera à ceci:Tout va bien. Imaginez maintenant que vous fournissiez cette chaîne comme mot de passe:
La chaîne SQL résultante serait alors la suivante:
Cela vous permettrait de vous connecter à n'importe quel compte sans connaître le mot de passe. Vous n'avez donc pas besoin de pouvoir utiliser deux instructions pour utiliser l'injection SQL, bien que vous puissiez faire des choses plus destructrices si vous êtes en mesure de fournir plusieurs instructions.
la source
Non, ce
'
n'est pas un commentaire en SQL, mais un délimiteur.Maman a supposé que le programmeur de base de données avait fait une demande ressemblant à ceci:
(par exemple) pour ajouter le nouvel étudiant, où le
$xxx
contenu de la variable a été directement extrait d'un formulaire HTML, sans vérifier le format ni échapper les caractères spéciaux.Donc, si
$firstName
contientRobert'); DROP TABLE students; --
le programme de base de données exécutera la demande suivante directement sur la base de données:c'est à dire. il terminera tôt l'instruction d'insertion, exécutera tout code malveillant souhaité par le pirate, puis commentera le reste du code.
Mmm, je suis trop lent, je vois déjà 8 réponses avant les miennes dans la bande orange ... :-) Un sujet populaire, semble-t-il.
la source
TL; DR
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:
Supposons que l'application utilise le SQL suivant pour insérer des données dans la table:
Remplacez
foobar
par le nom réel de l'élève. Une opération d'insertion normale ressemblerait à ceci:Lorsque nous interrogeons la table, nous obtenons ceci:
Que se passe-t-il lorsque nous insérons le nom de Little Bobby Tables dans la table?
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?
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.la source
Disons que vous avez naïvement écrit une méthode de création d'élève comme celle-ci:
Et quelqu'un entre le nom
Robert'); DROP TABLE STUDENTS; --
Ce qui s'exécute sur la base de données est cette requête:
Le point-virgule termine la commande d'insertion et en démarre une autre; le - commente le reste de la ligne. La commande DROP TABLE est exécutée ...
C'est pourquoi les paramètres de liaison sont une bonne chose.
la source
Une citation simple correspond au début et à la fin d'une chaîne. Un point-virgule est la fin d'une instruction. Donc, s'ils faisaient une sélection comme celle-ci:
Le SQL deviendrait:
Sur certains systèmes, le
select
serait exécuté en premier, suivi de l'drop
instruction! Le message est le suivant: NE PAS EMBALLER DE VALEURS DANS VOTRE SQL. Utilisez plutôt des paramètres!la source
La
');
termine la requête, elle ne démarre pas de commentaire. Ensuite, il supprime la table des étudiants et commente le reste de la requête qui devait être exécutée.la source
L'auteur de la base de données a probablement
Si nom_étudiant est celui donné, cela fait la sélection avec le nom "Robert", puis supprime le tableau. La partie "-" transforme le reste de la requête donnée en commentaire.
la source
Dans ce cas, «n'est pas un caractère de commentaire. Il est utilisé pour délimiter les littéraux de chaîne. L'artiste de bande dessinée mise sur l'idée que l'école en question a un sql dynamique quelque part qui ressemble à ceci:
Alors maintenant, le caractère 'termine la chaîne littérale avant que le programmeur ne s'y attende. Combiné avec le; pour terminer la déclaration, un attaquant peut maintenant ajouter le sql qu'il veut. Le commentaire - à la fin est de s'assurer que tout sql restant dans l'instruction d'origine n'empêche pas la requête de se compiler sur le serveur.
FWIW, je pense également que la bande dessinée en question contient un détail important: si vous songez à assainir vos entrées de base de données, comme le suggère la bande dessinée, vous le faites toujours mal. Au lieu de cela, vous devriez penser en termes de mise en quarantaine des entrées de votre base de données, et la bonne façon de le faire est via des requêtes paramétrées.
la source
Le
'
caractère dans SQL est utilisé pour les constantes de chaîne. Dans ce cas, il est utilisé pour terminer la constante de chaîne et non pour commenter.la source
Voici comment cela fonctionne: Supposons que l'administrateur recherche des dossiers d'étudiant
Étant donné que le compte administrateur dispose de privilèges élevés, la suppression de la table de ce compte est possible.
Le code pour récupérer le nom d'utilisateur de la demande est
Maintenant, la requête serait quelque chose comme ça (pour rechercher la table des étudiants)
La requête résultante devient
Étant donné que l'entrée utilisateur n'est pas filtrée, la requête ci-dessus a été manipulée en 2 parties
Le double tiret (-) ne fera que commenter la partie restante de la requête.
Ceci est dangereux car il peut annuler l'authentification par mot de passe, le cas échéant
Le premier fera la recherche normale.
Le second supprimera l'élève de la table si le compte dispose de privilèges suffisants (généralement, le compte administrateur de l'école exécutera une telle requête et disposera des privilèges mentionnés ci-dessus).
la source
SELECT* FROM sutdents ...
- vous avez oublié un "s". C'est ce que vous abandonnez.DROP TABLE STUDENTS;
Vous n'avez pas besoin de saisir des données de formulaire pour effectuer une injection SQL.
Personne ne l'a signalé auparavant, alors je pourrais en avertir certains d'entre vous.
Généralement, nous essaierons de patcher l'entrée des formulaires. Mais ce n'est pas le seul endroit où vous pouvez être attaqué par injection SQL. Vous pouvez faire une attaque très simple avec une URL qui envoie des données via une requête GET; Prenons l'exemple de la jachère:
Votre URL ressemblerait à http://votresite.com/show?id=1
Maintenant, quelqu'un pourrait essayer quelque chose comme ça
Essayez de remplacer nom_table par le nom réel de la table. S'il obtenait le bon nom de votre table, ils videraient votre table! (Il est très facile de forcer brutalement cette URL avec un script simple)
Votre requête ressemblerait à quelque chose comme ceci ...
Exemple de code vulnérable PHP utilisant PDO:
Solution - utilisez les méthodes PDO prepare () et bindParam ():
la source