Spring Boot Actuators
Spring Boot actuators overview
Spring Boot includes a number of additional features called actuators to help monitor and control an application when it is pushed to production. Actuators allow controling and monitoring an application using either HTTP or JMX endpoints. Auditing, health and metrics gathering can also open a hidden door to the server if an application has been misconfigured.
Spring Boot includes a number of built-in
endpoints
(or
endpoints
for Spring Boot 1.x) and lets developers add their own. For example, the
health
endpoint provides basic application health information.
Each individual endpoint can be enabled or disabled and exposed over HTTP or JMX. An endpoint is considered to be available when it is both enabled and exposed. The built-in endpoints will only be auto-configured when they are available. Most applications choose exposure via HTTP, where the ID of the endpoint along with a prefix of
/actuator
is mapped to a URL. For example, by default, the health endpoint is mapped to
/actuator/health
.
To learn more about the actuator's endpoints and their request and response formats check Spring Boot Actuator Web API Documentation .
env
env
exposes properties from Spring's
ConfigurableEnvironment
.
Spring Boot 2.x uses
json
instead of
x-www-form-urlencoded
for property change requests via the
env
endpoint
Information returned by the
env
and
configprops
endpoints can be somewhat sensitive so keys matching a certain pattern are
sanitized
(replaced by
*
) by default. However, below you can find several ways to retrieve these values
eureka.client.serviceUrl.defaultZone
eureka.client.serviceUrl.defaultZone
requires the following conditions:
-
/refresh
endpoint is available -
An application uses
spring-cloud-starter-netflix-eureka-client
dependency
Retrieving env properties
You can get
env
property value in plaintext with the next steps:
-
Set the
eureka.client.serviceUrl.defaultZone
property: -
Refresh the configuration
-
Retrive the property value from
Authorization
header fromattacker-website.com
logs
References:
XStream deserialization RCE
It requires
Eureka-Client
version
< 1.8.7
.
You can gain RCE with the following steps:
-
Set up a website that responds with a malicious XStream payload, check springboot-xstream-rce.py
-
Set the
eureka.client.serviceUrl.defaultZone
property: -
Refresh the configuration:
-
Code will be executed
It is possible because:
-
The
eureka.client.serviceUrl.defaultZone
property is set to the external eureka server URL -
Refresh triggers a request to the fake eureka server that will return a malicious payload
-
Response parsing triggers XStream deserialization that leads to code execution
References:
logging.config
logging.config
requires
/restart
is available.
Logback JDNI RCE
logging.config
can lead to RCE via Logback JNDI, check
Logback JNDI RCE
.
How to exploit:
-
Host
logback
config XML file with the following context: -
Host a malicious LDAP service, check the article how to prepare a payload and start the service
-
Set
logging.config
properties: -
Restart an application:
Resource:
Groovy RCE
How to exploit:
-
Host the
payload.groovy
file with the following content: -
Set
logging.config
: -
Restart an application:
The chain contains the following steps:
-
An attacker sets the Logback configuration file using the
logging.config
property -
An application requests the configuration after restarting
-
ch.qos.logback.classic.util.ContextInitializer.java
fromlogback-classic
determines whether the URLgroovy
ends with -
Groovy code from the configuration file is executed
References:
spring.main.sources
spring.main.sources
requires
/restart
is available.
How to exploit:
-
Host the
payload.groovy
file with the following content: -
Set
logging.config
: -
Restart an application:
The chain contains the following steps:
-
Set
spring.main.sources
as an external URL with a payload -
An application requests the URL after restarting
-
org.springframework.boot.BeanDefinitionLoader.java
fromspring-boot
determines whether the URLgroovy
ends with -
Groovy code from the configuration file is executed
References:
spring.datasource.tomcat.validationQuery
spring.datasource.tomcat.validationQuery
allows specifying any SQL query, that will be automatically executed against the current database. It could be any statement, including insert, update, or delete.
spring.datasource.tomcat.url
spring.datasource.tomcat.url
allows modifying the current JDBC connection string.
The problem here is that when the application establishing the connection to the database is already running, just updating the JDBC string has no effect. But you can try using
spring.datasource.tomcat.max-active
to increase the number of simultaneous database connections.
Thus, you can change the JDBC connection string, increase the number of connections, and then send many requests to the application to simulate a heavy load. Under load, the application will create a new database connection with an updated malicious JDBC string.
spring.datasource.data
spring.datasource.data
can be used to gain RCE if the following coditions are met:
-
/restart
is available -
h2database
andspring-boot-starter-data-jpa
dependencies are used
How to exploit:
-
Host
payload.sql
file with the following content:The
T5
method in the payload must be renamed (toT6
) after the command is executed before it can be recreated and used. Otherwise, the vulnerability will not trigger the next time an application is restarted. -
Set the
spring.datasource.data
: -
Restart an application:
The exploitaion chain contains the following steps:
-
An attacker set
spring.datasource.data
as the URL of the JDBC DML SQL file -
An application requests the URL after restarting
-
org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.java
fromspring-boot-autoconfigure
uses therunScripts
method to execute the h2 database SQL code that leads to RCE
References:
spring.datasource.url
spring.datasource.url
is database connection string that is used only for the first connection. You can chain it with JDBC deserialization vulnerability in MySQL to gain RCE. The vulnerability requires the following conditions:
-
/refresh
is available -
mysql-connector-java
dependency is used
Changing
spring.datasource.url
will temporarily disable all normal database services
How to exploit:
-
Use the
/actuator/env
endpoint to fetch the next values:-
mysql-connector-java
version number (5.x or 8.x) -
Common deserialization gadgets, such as
commons-collections
-
spring.datasource.url
value to facilitate later crafting of its normal JDBC URL
-
-
Create a payload with ysoserial :
-
Use springboot-jdbc-deserialization-rce.py to host
payload.ser
-
Set the
spring.datasource.url
property:mysql-connector-java
version 5.x:mysql-connector-java
version 8.x: -
Refresh the configuration:
-
Try to access an endpoint that will trigger a database query, for example
/product/list
, or find other ways to query the database and trigger the vulnerability
The exploitaion chain contains the following steps:
-
spring.datasource.url
is set to the external MySQL JDBC URL -
Refresh the configuration
-
An application establishes a new DB connection using the malicious MySQL JDBS URL when performing a DB query
-
The malicious MySQL server returns a payload at the appropriate stage of establishing the connection
-
mysql-connector-java
deserialize the payload and execute arbitrary code
References:
spring.cloud.bootstrap.location
spring.cloud.bootstrap.location
requires the following conditions:
-
/refresh
endpoint is available -
spring-cloud-starter
version< 1.3.0.RELEASE
Retrieving env properties
You can get
env
property value in plaintext with the next steps:
-
Set the
spring.cloud.bootstrap.location
property: -
Refresh the configuration
-
Retrive the property value from
attacker-website.com
logs
References:
SnakeYML RCE
spring.cloud.bootstrap.location
allows loading an external config in YAML format. You can gain code execution with the next steps:
-
Host
config.yml
athttp://attacker-website.com/config.yml
with the following content: -
Host
payload.jar
with the code that will be executed, check marshalsec research and artsploit/yaml-payload for how to prepare the payload -
Set the
spring.cloud.bootstrap.location
property: -
Refresh the configuration:
-
Code will be executed
It is possible because:
-
The
spring.cloud.bootstrap.location
is set to the URL with the external malicious config -
Refresh triggers a request for the config file on a remote server and retrieves its content
-
SnakeYAML
completes the specified action when parsing the malicious config due to a deserialization vulnerability -
SnakeYAML
usesjava.net.URL
to pull the malicious jar from the remote server -
SnakeYAML
searches for a class in the jar that implements thejavax.script.ScriptEngineFactory
interface and creates an instance of it -
The instance creation leads to malicious code execution
References:
spring.datasource.hikari.connection-test-query
spring.datasource.hikari.connection-test-query
sets a query that will be executed before granting a connection from a pool. It can lead to RCE if the following conditions are met:
-
/restart
endpoint is available -
com.h2database.h2
dependency is used
You can gain code execution with the following steps:
-
Set the
spring.datasource.hikari.connection-test-query
propertyThe
T5
method in the payload must be renamed (toT6
) after the command is executed before it can be recreated and used. Otherwise, the vulnerability will not trigger the next time an application is restarted. -
Restart the application:
How it works:
-
spring.datasource.hikari.connection-test-query
is set to a malicious SQL statement that use CREATE ALIAS to create a custom function -
spring.datasource.hikari.connection-test-query
correspondes to theconnectionTestQuery
configuration of the HikariCP database connection pool and define the SQL statement to be executed before a new database connection -
Restart establishes a new database connection
-
The custom function is executed
References:
gateway
The
gateway
actuator endpoint lets you monitor and interact with a Spring Cloud Gateway application. In other words, you can define routes for the application and use
gateway
actuator to trigger requests according to these routes.
SSRF
There are at least the following issues:
-
Routes can provide access to hidden or internal endpoints, which can be misconfigured or vulnerable. You can fetch all available routes via
GET
-request to/actuator/gateway/routes
. -
Full SSRF if adding routes do not require administrative permissions. The next request will create a route to localhost:
Send refresh request to apply new route:
References:
SpEL code injection
Applications using Spring Cloud Gateway in the version prior to
3.1.0
and
3.0.6
, are vulnerable to
CVE-2022-22947
that leads to a code injection attack when the Gateway Actuator endpoint is enabled, exposed and unsecured. A remote attacker could make a maliciously crafted request that could allow arbitrary remote execution on the remote host.
Check the following articles with details:
trace or httptrace
Displays HTTP trace information (by default, the last 100 HTTP request-response exchanges). It may disclose details about requests of internal applications as well as user cookies and JWT tokens.
trace
requires an
HttpTraceRepository
bean.
mappings
mappings
displays a collated list of all
@RequestMapping
paths.
sessions
sessions allows retrieval and deletion of user sessions from a Spring Session-backed session store. Requires a Servlet-based web application using Spring Session.
shutdown
shutdown lets an application be gracefully shutdown. Disabled by default.
h2-console
It requires the following conditions:
-
com.h2database.h2
dependency is used -
h2 console is enabled in Spring configuration
spring.h2.console.enabled=true
You can gain RCE via JDNI in h2 database console:
-
Access the h2 console
/h2-console
. An application will refirect to/h2-console/login.jsp?jsessionid=xxxxxx
. Catchjsessionid
value. -
Prepare a Java code for execution, you can reuse the JNDIObject.java
-
Compile in such a way that it is compatible with earlier JDK versions:
-
Host compiled
JNDIObject.class
athttp://attacker-website.com/
-
Set up a LDAP service with marshalsec :
-
Trigger JNDI injection:
References:
heapdump
heapdump
returns a hprof heap dump file that may contain sensitive data, such as
env
properties. To retrieve data from a prof heap dump use
Eclipse Memory Analyzer
tool, check
Find password plaintext in spring heapdump using MAT
.
References:
jolokia
Exposes JMX beans over HTTP (when Jolokia is on the classpath, not available for WebFlux). Requires a dependency on
jolokia-core
.
Extract env properties
You can invoke relevant MBeans to retrive
env
property values in plaintext. Below you can find MBeans that can be used for this purpose. However, the situation may differ and the Mbeans listed may not be available. However, you can search methods that can be called by keywords like
getProperty
.
References:
org.springframework.boot
You can get
env
property value in plaintext using the following request:
org.springframework.boot
MBean calls the
getProperty
method of the
org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar
class instance.
org.springframework.cloud.context.environment
You can get
env
property value in plaintext using the following request:
org.springframework.cloud.context.environment
MBean calls the
getProperty
method of the
org.springframework.cloud.context.environment.EnvironmentManager
class instance.
Logback::reloadByURL
You can list all available MBeans actions using the
/jolokia/list
endpoint. Most MBeans actions just expose some system data, but if the
reloadByURL
action provided by the
Logback
library exists: