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

Quelques vulnérabilités dans les ressources Web utilisant SQL


Cet article couvre une vulnérabilité SQL liée à la pénétration du corps de la demande.

L'essence de la vulnérabilité

Considérez le travail du système le plus simple avec une interface Web qui permet aux utilisateurs d’enregistrer aussi les informations de changement les concernant. De tels systèmes sont parmi les plus courants du réseau. Cela peut également inclure un livre d'or, une discussion en ligne, une galerie de photos et un service postal.

La requête générée à la base de données est forcée pour que le nom d'utilisateur et le mot de passe soient entrés par l'utilisateur. Pour ces champs, la base de données doit trouver l'entrée correspondante dans la table. Une fois la requête terminée, la base de données fournit les informations trouvées sur l'utilisateur, que le script PHP dessine sous forme de HTML donne également à l'utilisateur.

Analysons un fragment assez typique d’un script PHP utilisant une requête SQL pour accéder à la base de données:

<? php
$ result = mysql_db_query ("database", "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 le constatons, le nom d'utilisateur et le mot de passe entrés par l'utilisateur sont contenus dans les variables $ userLogin et $ userPassword . Le contenu de ces variables est inclus dans la demande de filtrage des informations sur cet utilisateur particulier. Le filtre est défini à l'aide de l'option where de la commande select SQL. Dans ce cas, la requête ressemble à ceci: sélectionnez * à partir de la table utilisateur login = '$ userLogin' et mot de passe = '$ utilisateurPassword' où tableTable est le nom de la table contenant les informations nécessaires. Si les variables de connexion du mot de passe contiennent également les valeurs de vanya et vasya , la requête envoyée à la base de données ressemblera à ceci: select * from userTable login = 'vanya' et password = 'vasya' . Il est clair que si dans la base de données, il n'y a pas d'enregistrement dans lequel l'identifiant est égal à vanya, cependant le mot de passe est vasya , jusqu'à la requête n'enverra pas une seule ligne à partir de la base de données, et le script ne produira rien. Ainsi, le système donné ne donne accès aux informations qu'à l'utilisateur, qui dispose d'un mot de passe et d'une connexion sans erreur.

Il semblerait qu'un tel système ne contient pas de défauts. En pratique, ce n'est pas le cas. La logique des programmeurs qui ont créé l'exemple ci-dessus implique que le nom d'utilisateur et le mot de passe entrés par l'utilisateur soient contenus entre guillemets simples et codés en dur dans le corps de la demande. Cependant, voyons ce qui se passe si le mot de passe lui-même, saisi par l'utilisateur, contient un guillemet. Laissez-le posséder la valeur de vas'ya , alors que la requête ressemblera à ceci: sélectionnez * à partir de la table utilisateur login = 'vanya' et mot de passe = 'vas'ya' . Lors de l'exécution d'une telle requête, une erreur va certainement se produire, car la citation du mot de passe ferme la citation d'ouverture de la requête, la fin du mot de passe ya ' restant "à bloquer" en dehors de l'expression conditionnelle.

Et si vous insérez une telle ligne en tant que mot de passe: 'ou 1 = 1' , la requête deviendra la suivante: select * from userTable login = 'vanya' et password = '' ou 1 = 1 '' ne comporteront pas non plus d'erreur de syntaxe. . Mais l'expression logique deviendra identiquement vraie, également en objection à cette requête, SQL générera la totalité de la base de données des utilisateurs 8-).

Ainsi, en utilisant le caractère apostrophe, nous pouvons également insérer le corps de la requête SQL afin que la condition vérifiée soit vraie. Si nous sommes intéressés par un utilisateur spécifique de vanya , pour obtenir des informations à son sujet, il est autorisé d'utiliser la chaîne de mot de passe suivante: 'ou login =' vanya . Cela fera la demande: sélectionnez * à partir de userTable login = 'vanya' et password = '' ou login = 'vanya' . Vous comprenez donc que nous recevrons des informations sur vanya .

La vulnérabilité décrite des services basés sur SQL n'est en aucun cas limitée à la réception non autorisée d'informations. Dans la mesure où MySQL est généralement utilisé dans de tels systèmes, il est possible non seulement de modifier l'expression conditionnelle dans la commande select, mais également d'aller au-delà de cette commande et d'exécuter une autre commande DB. Depuis MySQL permet plusieurs commandes dans une seule requête, séparés ; , alors nous pouvons exécuter n’importe laquelle de ces commandes en entrant le code suivant dans le champ mot de passe: '; <Commande SQL> à quel endroit il est permis de spécifier une commande valide en tant que <commande SQL> . Ainsi, par exemple, le code suivant: '; drop table 'userTable va simplement détruire le 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.

Dans cette tête, nous examinons les problèmes suivants qui surviennent lors de l’utilisation de la vulnérabilité décrite:
  • Déterminer si SQL est utilisé dans le système.
  • Identifier l'existence d'une vulnérabilité. Clarification de la réaction du script aux erreurs.
  • Définition des noms de champs dans la table.
  • Identifiez les noms des tables existantes.

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

    Déterminer si SQL est utilisé dans le système.

    Lors de l'examen d'un système particulier, vous devez d'abord déterminer s'il utilise SQL.
    Ce fait peut être révélé soit indirectement (en regardant les noms des fichiers utilisés, les références aux outils utilisés, etc.), soit directement - en provoquant la manifestation du code SQL. Si nous travaillons avec PHP, il n'y a qu'un seul moyen d'identifier de manière unique l'utilisation de SQL: provoquer une erreur lors de son exécution. Si une erreur survient pendant l’exécution de la demande, le script PHP ne gère aucune erreur de façon explicite, alors PHP enverra un message d’erreur directement à la page de l’utilisateur.
    La cause d'une erreur dans l'exécution d'une requête SQL dépend du périphérique particulier du système en question. Dans la plupart des cas, l'erreur est autorisée à appeler en entrant des données incorrectes dans le système.

    Identifier l'existence d'une vulnérabilité. Clarification de la réaction du script aux erreurs.

    Le moyen le plus simple de détecter la présence d'une vulnérabilité, mais également le fait d'utiliser SQL, est le suivant: Dans tout champ censé générer une requête SQL (par exemple, le champ Login ou Password ), entrez un guillemet simple. Les champs restants sont remplis avec toutes les données valides (ou sont laissés vides, si le système le permet). Après avoir envoyé ces formulaires, nous examinons la réaction du système. Si, par conséquent, le script PHP génère une erreur SQL, nous pouvons nous en féliciter: le système utilise SQL et le script ne filtre en aucune façon le guillemet simple. Que manger le système contient une vulnérabilité.
    L'erreur de requête SQL ressemblera alors à ceci sur la page:

    Formulaire de saisie de données:


    Le résultat est une erreur de requête SQL:


    S'il n'y a pas de code d'erreur SQL sur la page, cela peut signifier que:
    1) Le système contient une vulnérabilité, mais le script PHP traite les erreurs. Dans ce cas, le système est autorisé à pirater, mais vous devez agir "au toucher", car nous ne saurons à tout moment à quelle heure la syntaxe SQL sera correcte, mais à quelle heure elle ne sera pas.
    2) Le script filtre la citation aussi parce que les erreurs ne se produisent pas du tout. Dans ce cas, le système ne contient aucune vulnérabilité.
    3) Le système général n'utilise pas SQL.
    Dans les deux derniers cas, il est clair que l'exploration ultérieure de SQL n'a aucune signification.

    Définition des noms de champs dans la table.

    Afin d'obtenir des informations de la base de données avec des données spécifiques, nous devons définir les valeurs de certains champs de la demande (par exemple, définir le nom d'utilisateur). Pourtant, pour cela, vous devez connaître le nom des champs correspondants. Découvrir directement ces noms n'est pas possible. Par conséquent, il est nécessaire de rechercher ces noms à l'aide de la méthode de recherche. Ces noms peuvent coïncider avec les noms des champs du formulaire envoyé au serveur, mais ils peuvent également ne pas coïncider. La bonne chose est que les noms des champs en tant que norme sont également des variantes standard de leur écriture. Ainsi, par exemple, le nom du champ pour le nom d'utilisateur est susceptible d'être login ou utilisateur ou pseudo . Similaire au mot de passe: password soit pwd ou pass .
    Pour déterminer l'existence d'un champ spécifique, nous proposons une méthode peu sophistiquée: supposons que nous voulions vérifier si le champ pwd existe dans la table. Entrons cette chaîne 'pwd =' dans n'importe quel champ de formulaire. Si le champ pwd existe dans la table, alors SQL traite correctement la demande. S'il n'existe pas de tel champ, l'erreur d'exécution SQL se reproduira. Ainsi, en substituant différentes valeurs aux noms de champs et en examinant également le résultat de la fin de la requête, nous pouvons déterminer quels champs existent dans la table, mais lesquels ne le sont pas.

    Identifiez les noms des tables existantes.

    Semblable à la méthode de recherche des noms de champs dans les tables, il est également permis de rechercher les noms des tables existantes dans la base de données. Supposons que nous voulions savoir si la table adminList existe dans la base de données. Pour ce faire, entrez la chaîne suivante dans le champ de formulaire avec le locuteur ', sélectionnez * depuis adminList . Si, par conséquent, l'erreur SQL ne démarre pas du tout, la table adminList existe. Pour l'exactitude de ce test, vous devez entrer cette chaîne dans le champ qui apparaît final dans la requête SQL. Cela est nécessaire pour éviter que l'erreur de syntaxe ne soit due au reste de la "queue" de la requête d'origine, qui devient présente ultérieurement. Sélectionnez * dans AdminList . Notez que si la vue de la demande appartient à une paire du champ de connexion et au mot de passe , le champ de mot de passe apparaîtra probablement en dernier dans la demande.

    PS

    En utilisant cette vulnérabilité, le site http://www.bigmir.net a été piraté (plus précisément, sa galerie de photos est aussi un chat). Nous avons annoncé une vulnérabilité pour les propriétaires de sites. Le trou était réparé. Mais maintenant, nous avons vérifié le formulaire de chat une fois de plus. Plus trouvé toute cette vulnérabilité bla bla 8-).