Après les deux premiers tutoriaux au sujet des attaques de type SQL Injection, le billet d'aujourd'hui sera dédié à un vecteur d'attaque un peu particulier, si vous ne connaissez pas les principes d'une injection sql, je vous invite vivement à lire les deux premiers articles avant de passer à la suite ;)
Je rappelle que la série de ces tutoriaux est dans le but de donner une idée sur les différents aspects et vecteurs d'attaque d'une injection SQL, j'espère que ça vous aidera à mieux vous protéger et percevoir les risques en codant, n'hésitez pas à me faire part de vos remarques ;)
Qu'est ce que Blind SQL Injection?
Blind SQL Injection est un vecteur d'attaque dont l'approche est très différente de celle des injections classiques, elle permet comme ses ascendants d'injecter des données à partir d'une base d'une application vulnérable. Repérer une faille de ce type n'est pas toujours facile et demande une série de tests.
Les Injections blind se caractérisent par l'absence d'un message d'erreur (qui généralement permet de repérer la faille), ce qui impose une serie de tests " à l'aveuglette " afin d'identifier la présence d'une faille (ou pas) !
Prenant un exemple :
On considère une application web avec une page profile.php avec le code ci-dessous :
//... $user_id = $_GET['user_id']; while(stristr($user_id, '#union#i')) $user_id = stri_replace('union','',$_GET['user_id']); $query = "SELECT * FROM profile WHERE user_id = $user_id" ; if(!@mysql_query($query)){ echo "Ce membre n'existe pas"; } else{ //Affichage des données du profil }
Ce code semble sécurisé contre les injections classiques puisqu'il remplace le mot clé " union ", donc pas de possibilité de sélectionner une nouvelle ligne et détourner la requête, toute-fois un attaquant malveillant peut l'exploiter!
Analysons cette requête :profile.php?user_id=1
Cet appel affichera le profile de l'utilisateur ayant l'id 1 (généralement l'administrateur du site)
Que se passera t'il avec :
profile.php?user_id=1 AND 1=2
Logiquement 1 != 2, si le script n'affiche pas le profil c'est que la condition rajoutée a été exécutée dans la requête, on peut vérifier ça on rajoutant une condition qui retourne toujours true (profile.php?user_id=1 AND 4=4). Si avec cet appel le profil de l'utilisateur ayant user_id=1 s'affiche, c'est que le script est vulnérable à une injection de type " Blind SQL Injection ", alors là! La bonne nouvelle c'est que l'attaquant ne voit aucune information affichée, la mauvaise c'est qu'il peut facilement bruteforcer l'information en rajoutant des conditions dans l'url. Ainsi suivant l'affichage ou le non-affichage du profil, l'attaquant peut comprendre si la condition qu'il a mis est remplie, et enfin extraire les informations caractère par caractère
Exemple permettant de vérifier que la version de mysql est 5:
profile.php?user_id=1 AND version() MATCH 5
Voyant ce qu'un attaquant malveillant peut faire pour exploiter cette faille :
profile.php?user_id=1 and length(password)=32
Cet appel illuste un test sur la longueur du champ password, généralement les passes sont cryptés en md5, si c'est le cas le profil s'affiche et ça facilite à l'attaquant la poursuite de son exploitation ! Un md5 est une chaine de caractère en hexadécimal [09-af] donc 16 possibilités pour chaque caractères, du coup le nombre des possibilités n'est pas énormes, 16 tests au maximum peuvent permettre d'injecter un caractère du champ password, ce qui donne 16×15 = 512 requêtes maximum en total pour extraire le hash md5 de l'utilisateur ayant user_id = 1
profile.php?user_id=1 AND substr(password,0,1)= 0×66
Pour tester si le premier caractère est un " f " (0×66 correspond au code hexadécimal de la lettre f) ainsi selon l'affichage (ou non) du profil utilisateur l'attaquant peut facilement extraire le reste de la chaine de caractère du mot de passe, évidement sans aucun message d'erreur affiché sur son écran !
Pour résumer: Une Blind SQL Injection est toujours exploitée grâce à un bruteforce à l'aveuglette en se servant d'une page vulnérable qui affiche une donnés X, selon l'affichage ou non de cette dernière on peut deviner les données se cachant derrière.
Comment sécuriser son application ?
Les bonnes pratiques à adopter pour éviter de se faire pirater son site sont généralement les mêmes que j'ai cité dans les deux premier tutoriaux : de manière générale : Ne jamais se contenter de cacher les messages d'erreur, pensez toujours à filtrer les entrées, rajouter toujours les " signles quotes " aux variables que vous usez dans vos requêtes SQL et filtrer toujours avec la fonction mysql_real_escape_string
Leave a Reply