This page has been robot translated, sorry for typos if any. Original content here.

Quelques vulnérabilités de ressources web en utilisant SQL


La note traite de la vulnérabilité de SQL, liée à la pénétration dans le corps de la requête.

L'essence de la vulnérabilité

Considérez le fonctionnement d'un système simple avec WEB-interface, qui permet aux utilisateurs de sauvegarder aussi pour changer les informations sur eux-mêmes. De tels systèmes sont parmi les plus courants dans le réseau. Il peut également s'agir d'un livre d'or, d'un salon de discussion, d'une galerie de photos et d'un service postal.

La requête générée vers la base de données est obligée d'avoir le login de l'utilisateur et le mot de passe entré par l'utilisateur. Pour ces champs, la base de données doit trouver l'entrée correspondante dans la table. Après avoir terminé la requête, la base de données affiche les informations sur l'utilisateur, que le script PHP crée sous la forme de HTML, donne également à l'utilisateur.

Regardons un fragment de script PHP assez typique qui utilise la requête SQL pour accéder à la base de données:

<? php
$ result = mysql_db_query ("base de données", "select * from userTable où login = '$ userLogin' et password = '$ userPassword'");
while ($ row = mysql_fetch_array ($ result)) {
echo $ row ["nom complet"];
echo $ row ["email"];
echo $ row ["mot de passe"];
}
mysql_free_result ($ result);
?>

Comme nous l'observons, le login aussi le mot de passe entré par l'utilisateur est contenu dans les variables $ userLogin également $ userPassword . Le contenu de ces variables est inséré dans la requête pour filtrer les informations sur cet utilisateur. Le filtre est spécifié à l'aide de l'option where de la commande select SQL. Dans ce cas, la requête ressemble à ceci: select * from userTable login = '$ userLogin' et password = '$ userPassword' où userTable est le nom de la table contenant les informations requises. Si la modification du nom de connexion du mot de passe contient également les valeurs vanya, respectivement vasya, alors la requête envoyée par la base de données prendra la forme suivante: select * from userTable login = 'vanya' et password = 'vasya' . Il est clair que s'il y a une entrée dans la base de données où le login est vanya, alors le mot de passe est vasya , jusqu'à ce que la requête n'envoie pas une seule ligne de la base, et le script ne retournera rien. Ainsi, le système ci-dessus fournit un accès à l'information uniquement à l'utilisateur qui a un mot de passe sans erreur également se connecter.

Il semblerait qu'un tel système ne comporte pas de défauts. Dans la classe elle-même, ce n'est pas le cas. La logique des programmes qui ont créé l'exemple ci-dessus suppose que le login entré par l'utilisateur est également un mot de passe qui sera contenu dans des guillemets simples qui sont codés en dur dans le corps de la requête. Cependant, voyons ce qui se passe si le mot de passe lui-même, entré par l'utilisateur, contient un guillemet. Laissez-lui posséder la valeur de vas'ya , tandis que la requête ressemblera à ceci: select * from userTable login = 'vanya' et password = 'vas'ya' . Lors de l'exécution d'une telle requête, il y aura certainement une erreur, car la citation du mot de passe, a fermé la citation d'ouverture de la requête, aussi la fin du mot de passe ya ' reste' à suspendre 'en dehors de l'expression conditionnelle.

Et si vous insérez la ligne suivante comme mot de passe: 'ou 1 = 1' , la requête deviendra :: select * de userTable login = 'vanya' et password = '' ou 1 = 1 '' n'a pas non plus d'erreurs de syntaxe . Mais l'expression logique sera identique à l'identique, également dans une objection à cette requête, SQL publiera la base de données entière d'utilisateur 8-).

Ainsi, en utilisant le symbole apostrophe, nous pouvons priknjut dans le corps de la requête SQL aussi faire en sorte que la condition vérifiée soit vraie. Si nous sommes intéressés par un utilisateur particulier de vanya , alors pour recevoir des informations à son sujet, il est permis d'utiliser une telle ligne de mot de passe: 'ou login =' vanya . La requête devient: select * from userTable login = 'vanya' et password = '' ou login = 'vanya' . Comme vous le comprenez, nous recevrons des informations sur Vanya .

La vulnérabilité décrite des services basés sur SQL ne se limite pas à la réception non autorisée d'informations. Puisque MySQL est utilisé dans de tels systèmes, il est possible non seulement de modifier l'expression conditionnelle dans la commande select, mais aussi d'aller au-delà de cette commande, et aussi d'exécuter une autre commande de base de données. Parce que MySQL autorise plusieurs commandes dans une requête, séparées ; , puis nous pouvons exécuter l'une de ces commandes en tapant le code suivant dans le champ mot de passe: '; <Commande SQL> dans quel endroit la <commande SQL> est autorisée à spécifier toute commande valide. Ainsi, par exemple un tel code: '; drop table 'userTable détruit simplement la table userTable de la base de données.

Utilisation pratique de la vulnérabilité

Malgré la simplicité, l'utilisation pratique des erreurs de requête SQL est très difficile.

À cet égard, tenez compte des problèmes suivants lors de l'utilisation de la vulnérabilité décrite:
  • Déterminer l'utilisation de SQL dans le système.
  • Identifier l'existence d'une vulnérabilité Élucidation de la réponse de script aux erreurs.
  • Définissez les noms des champs dans la table.
  • Définir les noms des tables existantes.

    Cette vulnérabilité est inhérente à toutes les requêtes SQL, quel que soit le script ou le programme à partir duquel elles sont appelées. Pourtant, nous allons considérer les systèmes basés sur PHP. Cela est dû au fait que le flux d'erreur PHP en tant qu'emplacement (par défaut) est envoyé à l'utilisateur final. Alors que les applications Perl ou Exe n'informent généralement pas l'utilisateur sur la nature des erreurs.

    Déterminer l'utilisation de SQL dans le système.

    Lorsque vous recherchez un système particulier, vous devez d'abord savoir s'il utilise SQL.
    Ce fait peut être détecté indirectement (en regardant les noms des fichiers utilisés, les liens vers les outils utilisés, etc.), ou directement - en amenant le SQL à faire ses preuves. Si nous travaillons avec PHP, il n'y a qu'un seul outil pour identifier de façon unique l'utilisation de SQL - ceci provoque une erreur dans son exécution. Si une erreur survient lors de l'exécution de la requête, cependant, le script PHP n'indique aucune erreur explicite, le message concernant l'erreur de PHP sera directement affiché sur la page de l'utilisateur.
    Comment provoquer une erreur dans l'exécution d'une requête SQL dépend du système spécifique du système en question. Dans la plupart des cas, l'erreur peut être provoquée en entrant des données incorrectes dans le système.

    Identifier l'existence d'une vulnérabilité Élucidation de la réponse de script aux erreurs.

    Le moyen le plus simple de détecter la présence d'une vulnérabilité, mais aussi d'utiliser SQL, est le suivant: Dans tout champ implicitement impliqué dans la création d'une requête SQL (par exemple, le champ Login ou Mot de passe ), entrez le caractère guillemet simple. Nous remplissons les champs restants avec les données correctes (ou laissons-les vides si cela est autorisé par le système). Après avoir envoyé les données du formulaire, nous examinons la réaction du système. Si, par conséquent, le script PHP nous donne l'erreur SQL, nous pouvons nous féliciter: le système utilise SQL et le script ne filtre pas le guillemet simple. C'est de manger le système contient une vulnérabilité.
    Une erreur de requête SQL ressemblera alors à ceci sur la page:

    Formulaire d'entrée:


    Par conséquent, une erreur de requête SQL:


    S'il n'y a pas de code d'erreur SQL sur la page, cela pourrait signifier ce qui suit:
    1) Le système contient une vulnérabilité, mais le script PHP gère les erreurs. Dans ce cas, le système est autorisé à pirater, mais vous devrez agir "touch", car nous ne saurons pas à quel moment la syntaxe de SQL sera correcte, mais à quelle heure elle ne l'est pas.
    2) Le script filtre également le guillemet, donc il n'y a pas d'erreur. Dans ce cas, le système ne contient aucune vulnérabilité.
    3) Le système n'utilise pas SQL de quelque façon que ce soit.
    Dans les derniers cas, il est clair qu'une étude plus approfondie de SQL n'a aucune signification.

    Définissez les noms des champs dans la table.

    Afin d'obtenir des informations de la base de données avec des données spécifiques, nous devons déterminer les valeurs de certains champs de la requête (par exemple, pour définir la connexion de l'utilisateur). Cependant, vous devez connaître le nom des champs correspondants. Directement pour trouver ces noms n'est pas possible. Par conséquent, ici, il est nécessaire de rechercher les noms donnés par une méthode de recherche. Ces noms peuvent coïncider avec les noms des champs dans le formulaire envoyé au serveur, et peuvent également ne pas coïncider de quelque façon que ce soit. Une bonne leçon est que les noms des champs en tant que position sont standard, et qu'il n'y a pas tellement de variantes pour les écrire. Par exemple, le nom du champ pour le nom d'utilisateur est susceptible d'être login, soit utilisateur ou pseudo . Il est similaire pour le mot de passe: password soit pwd soit pass .
    Pour déterminer l'existence d'un champ spécifique, nous proposons une méthode simple: Voulons vérifier s'il existe un champ pwd dans la table. Nous introduisons dans chaque champ de la forme une ligne 'pwd =' . Si le champ pwd existe dans la table, alors SQL traitera correctement la requête, s'il n'y a pas un tel champ, alors l'erreur d'exécution SQL apparaîtra à nouveau. Ainsi, en substituant des valeurs différentes pour les noms de champs, en examinant également le résultat de la fin de la requête, nous pouvons trouver quels champs existent dans la table, mais lesquels ne le sont pas.

    Définir les noms des tables existantes.

    Similaire à la méthode de recherche des noms de champs dans les tables, il est également possible de rechercher les noms des tables existantes dans la base de données. Voyons s'il y a une table adminList dans la base de données. Pour ce faire, nous entrons dans le champ de formulaire le formulaire '; select * from adminList . Si, à la suite de l'erreur, SQL ne démarre pas du tout, la table adminList existe. Pour l'exactitude de ce test, il est nécessaire d'entrer cette ligne dans le champ qui apparaît dans la requête SQL finale. Cela est nécessaire pour garantir que l'erreur de syntaxe n'est pas due à la "queue" restante de la requête d'origine, qui sera présente plus tard, sélectionnez * dans adminList . Notez que si le formulaire de la requête est la propriété d'une paire du champ Login est également Password , alors le champ mot de passe apparaîtra probablement en dernier dans la requête.

    PS

    En utilisant cette vulnérabilité, le site http://www.bigmir.net (plus précisément sa galerie de photos a aussi bavardé) a été piraté. Nous avons écrit sur la vulnérabilité des propriétaires de sites. Le trou a été réparé. Mais maintenant, nous avons de nouveau vérifié le formulaire d'inscription du chat. Plus trouvé toute la vulnérabilité bla bla 8-).