July 25, 2026
“SSTI-1” | PicoCTF Walkthrough | CyLab writeup | DAY — 03
Lets start our 3rd Web Exploitation Challenge.

By Roni Hasan
3 min read
In this blog post, I'll provide a detailed solution for the SSTI1 challenge from Cylab or picoCTF.
Platform : PicoCTF | CyLab
Category : Web Exploitation
Difficulty : Easy
Lets start….
INTRODUCTION : What is Server-Side Template ?
Server-Side Template Injection (SSTI) is a web vulnerability that occurs when user input is unsafely embedded into a server-side template engine, allowing an attacker to inject and execute template expressions, potentially leading to sensitive data exposure, arbitrary code execution, or remote command execution.
There are 2 steps for SSTI
1-Identify the Template Engine
First, determine which template engine the application uses. Common engines include:
- Jinja2 (Python): Uses {{ }} or {% %}.
- Twig (PHP): Uses {{ }}.
- Freemarker (Java): Uses ${} or
<#assign>. - Velocity (Java): Uses ${} or
#set(). - Handlebars (JavaScript): Uses {{ }}.
- ERB (Ruby): Uses <%= %>.
1.1-Probing Techniques:
- Submit simple arithmetic expressions to see if they're evaluated:
{{7*7}}→ If the output is49, it suggests SSTI (Jinja2/Twig).
2-Exploiting SSTI
Once you've confirmed the presence of an SSTI vulnerability, the next step is crafting a proper payload tailored to the detected engine in order to exploit it — ranging from reading files to achieving full command execution depending on the context.
According to the description, the developer has built a website where users can publish announcements. Let's explore the application's functionality and look for potential vulnerabilities.
To understand the application's behavior, let's enter a sample string. As we can see, whatever we type into the input field is rendered on the website below.
As the challenge is titled SSTI, we first need to confirm that the application is vulnerable to Server-Side Template Injection before attempting to exploit it.
Before verifying the SSTI vulnerability, we first need to determine which server-side template engine the application is running. Once identified, we can use template-specific payloads to test for SSTI.
Running this command reveals the server-side template engine used by the application, allowing us to choose the appropriate SSTI payloads.
curl -I http://rescued-float.picoctf.net:52993/curl -I http://rescued-float.picoctf.net:52993/
The response indicates that the application is running on a Python-based template engine. Let's test it with a Python/Jinja2 SSTI payload to confirm whether the vulnerability exists.
Let's input the payload {{ 7 * 7 }}. If the application evaluates the expression and returns 49, it confirms that the template engine is processing user input, indicating that the application is vulnerable to SSTI. There are many SSTI detection payloads available online, and you can use any suitable payload depending on the template engine.
Now that we have confirmed the application is vulnerable to SSTI, the next step is to attempt code execution using an appropriate payload. Since different template engines support different payloads, there is no single payload that works in every case. Numerous SSTI payloads are available online, so you may need to test several of them to identify the one that is compatible with the target application's template engine.
After inject the code in announcement section we found this ,
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
The response confirms that the payload executed successfully, as it returned the uid and gid of the running process. This indicates that our command was executed on the server.
Now, let's replace the previous command with ls to list the contents of the current directory and see what files are available.
{{request.application.__globals__.__builtins__.__import__('os').popen('ls').read()}}{{request.application.__globals__.__builtins__.__import__('os').popen('ls').read()}}
From the directory listing, we can see a file named flag. Let's use the cat command to read its contents and retrieve the flag.
{{request.application.__globals__.__builtins__.__import__('os').popen('cat flag').read()}}{{request.application.__globals__.__builtins__.__import__('os').popen('cat flag').read()}}
Here is the flag we found
FLAG : picoCTF{s4rv3r_s1d3_t3mp14t3_1nj3ct10n5_4r3_c001_f5438664}
The Point of This Lab
Nothing difficult here — just a simple step forward in learning how Server-Side Template Injection (SSTI) works.
THANK YOU :)