Spring Boot Actuators
Last updated
Last updated
Spring Boot includes a number of additional features called 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 (or 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 .
exposes properties from Spring's ConfigurableEnvironment
.
eureka.client.serviceUrl.defaultZone
requires the following conditions:
/refresh
endpoint is available
An application uses spring-cloud-starter-netflix-eureka-client
dependency
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 from attacker-website.com
logs
References:
It requires Eureka-Client
version < 1.8.7
.
You can gain RCE with the following steps:
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
requires /restart
is available.
How to exploit:
Host logback
config XML file with the following context:
Set logging.config
properties:
Restart an application:
Resource:
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
from logback-classic
determines whether the URL groovy
ends with
Groovy code from the configuration file is executed
References:
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
from spring-boot
determines whether the URL groovy
ends with
Groovy code from the configuration file is executed
References:
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
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
can be used to gain RCE if the following coditions are met:
/restart
is available
h2database
and spring-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 (to T6
) 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
from spring-boot-autoconfigure
uses the runScripts
method to execute the h2 database SQL code that leads to RCE
References:
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
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
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
requires the following conditions:
/refresh
endpoint is available
spring-cloud-starter
version < 1.3.0.RELEASE
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:
spring.cloud.bootstrap.location
allows loading an external config in YAML format. You can gain code execution with the next steps:
Host config.yml
at http://attacker-website.com/config.yml
with the following content:
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
uses java.net.URL
to pull the malicious jar from the remote server
SnakeYAML
searches for a class in the jar that implements the javax.script.ScriptEngineFactory
interface and creates an instance of it
The instance creation leads to malicious code execution
References:
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
property
The T5
method in the payload must be renamed (to T6
) 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 the connectionTestQuery
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:
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
.
Send refresh request to apply new route:
References:
Check the following articles with details:
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.
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
. Catch jsessionid
value.
Compile in such a way that it is compatible with earlier JDK versions:
Host compiled JNDIObject.class
at http://attacker-website.com/
Trigger JNDI injection:
References:
References:
Exposes JMX beans over HTTP (when Jolokia is on the classpath, not available for WebFlux). Requires a dependency on jolokia-core
.
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:
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.
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.
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:
the logging configuration can be reload from an external URL:
Logback
uses XML configuration parsed by the SAXParser
XML parser with external entities enabled. You can exploit this feature to trigger an Out-Of-Band XXE:
References:
In this case, the env-entry-name
attribute will be passed to the DirContext.lookup()
method. Providing an arbitrary name to the lookup
method can lead to remote code execution via remote class loading.
You can gain code execution with the following steps:
Get the /jolokia/list
to check if ch.qos.logback.classic.jmx.JMXConfigurator
class and reloadByURL
method are available
Host the logback configuration at http://attacker-website.com/logback.xml
:
Compile in such a way that it is compatible with earlier JDK versions:
Host the compiled JNDIObject.class
at http://attacker-website.com/
Load the log configuration from an external URL with the following request:
If an application successfully requests logback.xml
and marshalsec
receives the target request, but an application does not request JNDIObject.class
, it is likely that an application's JDK version is too high, causing JNDI usage to fail.
It is possible due to the following steps:
Direct access to the URL that could cause the vulnerability is equivalent to calling the ch.qos.logback.classic.jmx.JMXConfigurator
class method via jolokia reloadByURL
An application requests a XML configuration file from an external URL
XML configuration is parsed by saxParser.parse
, it leads to XXE vulnerability
The external JNDI server address is specified using the insertFormJNDI
tag in the Logback XML configuration file
An application requests a malicious JNDI server, it leads to JNDI injection and RCE
References:
One of the MBeans of Tomcat (embedded into Spring Boot) is createJNDIRealm
. createJNDIRealm
allows creating JNDIRealm that is vulnerable to JNDI injection. You can expoit with the next steps:
Get the /jolokia/list
to check if type=MBeanFactoryand
and createJNDIRealm
are in place
Compile the code and host the compiled class at http://attacker-website.com/
It is possible due to the following chain:
Create JNDIRealm
with createJNDIRealm
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
References:
References:
Set up a website that responds with a malicious XStream payload, check
logging.config
can lead to RCE via Logback JNDI, check .
Host a malicious LDAP service, check the how to prepare a payload and start the service
Create a payload with :
Use to host payload.ser
Host payload.jar
with the code that will be executed, check and for how to prepare the payload
The 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.
Full SSRF if do not require administrative permissions. The next request will create a route to localhost:
Applications using Spring Cloud Gateway in the version prior to 3.1.0
and 3.0.6
, are vulnerable to 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.
displays a collated list of all @RequestMapping
paths.
allows retrieval and deletion of user sessions from a Spring Session-backed session store. Requires a Servlet-based web application using Spring Session.
lets an application be gracefully shutdown. Disabled by default.
Prepare a Java code for execution, you can reuse the
Set up a LDAP service with :
returns a hprof heap dump file that may contain sensitive data, such as env
properties. To retrieve data from a prof heap dump use tool, check .
The Logback
configuration has the feature . In the XML configuration file you can include a tag like:
Prepare a Java code for execution, you can reuse the
Set up LDAP server, use to set up the server:
Prepare a Java code for execution, you can reuse the
Set up a RMI service with :
Send the payload using
returns the contents of the logfile (if logging.file.name
or logging.file.path
properties have been set). Supports the use of the HTTP Range header to retrieve part of the log file's content.
version before 0.2.13
is vulnerable to path traversal that allows you to retreive arbitrary files.
performs a thread dump from the application's JVM.