Dans ce cas, vous faites face à une vulnérabilité d’injection SQL basique. Décomposons ce qui se passe à chaque étape et pourquoi cela fonctionne.
Inspecter le Code
Tout d’abord, vous inspectez le code source de la page. C’est une étape courante lorsqu’on essaie d’identifier comment les entrées des utilisateurs (comme le nom d’utilisateur et le mot de passe) sont traitées. Dans ce cas, vous remarquez un formulaire qui envoie des données, et vous découvrez également la requête SQL qui est exécutée pour authentifier l’utilisateur. Le code source révèle quelque chose comme :
SELECT * FROM users WHERE username="admin" AND password="poloska"
Cette requête cherche une ligne dans la table users où à la fois le username et le password correspondent aux valeurs entrées dans le formulaire. Cela est typique pour des formulaires de connexion simples.
Identifier la Vulnérabilité
La vulnérabilité ici réside dans le fait que l’application web insère directement les entrées des utilisateurs (username
et password
) dans la requête SQL sans les sanitiser correctement.
Cela rend l’application vulnérable à une injection SQL.
Dans un système sécurisé, les paramètres comme le username
et le password
devraient être paramétrés ou échappés pour empêcher les utilisateurs malveillants de modifier la structure de la requête.
Cependant, dans ce cas, les valeurs sont directement injectées dans la chaîne de la requête.
Exploiter la Vulnérabilité
Maintenant, vous connaissez la structure de la requête, donc vous pouvez la manipuler.
L’astuce consiste à utiliser la syntaxe de commentaire SQL (--
) pour ignorer le reste de la requête après votre entrée, ce qui vous permet de contourner la vérification du mot de passe.
Votre payload :
admin"--
Voici comment cela fonctionne :
admin
est le nom d’utilisateur avec lequel vous essayez de vous connecter.--
est un commentaire en SQL, ce qui signifie que tout ce qui suit sur cette ligne est ignoré.
La requête envoyée à la base de données ressemble alors à ceci :
SELECT * FROM users WHERE username="admin" --" AND password="test"
Explications :
- Après le
--
, la base de données traitera tout comme un commentaire. - Donc, la partie
AND password="test"
est ignorée par le moteur SQL. - La requête vérifie maintenant seulement si une ligne existe avec
username="admin"
. - Puisque vous n’avez pas besoin de fournir un mot de passe valide (car la vérification du mot de passe est “commentée”), vous êtes connecté en tant qu’utilisateur
admin
.
Contourner la vérification du mot de passe
En injectant admin"--
, vous avez effectivement ignoré la validation du mot de passe, car la requête SQL vérifie maintenant uniquement le username
, et la partie du mot de passe est mise en commentaire.
Tant que le nom d’utilisateur admin
existe dans la base de données, vous serez authentifié sans avoir besoin de connaître le mot de passe correct.
Résultat final
Lorsque vous soumettez le formulaire avec ce payload, l’application envoie la requête SQL modifiée à la base de données, et la base de données retourne les données correspondantes à l’utilisateur admin sans vérifier le mot de passe.
Comme vous avez contourné la vérification du mot de passe, vous accédez au compte admin
(ou à tout autre compte que représente admin
).
Et voilà, le flag ou l’accès vous est accordé !
Points clés
- L’injection SQL se produit lorsque les entrées des utilisateurs sont directement utilisées dans une requête SQL sans être correctement sécurisées, ce qui permet aux attaquants de manipuler la structure de la requête.
- Les commentaires en SQL (
--
) sont utilisés pour ignorer une partie de la requête, ce qui, dans ce cas, vous permet de contourner la validation du mot de passe. - Il s’agit d’une injection SQL basique où l’attaquant n’a pas besoin de voir les erreurs ou les messages de la base de données, mais peut toujours manipuler la structure de la requête.
Mitigations
Pour éviter ce genre d’attaque, il faut sanitiser correctement les entrées des utilisateurs. La méthode la plus efficace consiste à utiliser des requêtes préparées ou paramétrées où les entrées des utilisateurs sont traitées comme des données, pas du code exécutable. De cette manière, même si un attaquant tente d’injecter du SQL, cela ne modifiera pas la logique de la requête.
Si vous écriviez ce code de manière sécurisée, cela pourrait ressembler à ceci :
cursor.execute("SELECT * FROM users WHERE username=? AND password=?", (username, password))
Cela garantit que les entrées des utilisateurs ne peuvent pas modifier la structure de la requête.