Insecure Deserialization: Step-by-Step Attack Breakdown
Map the exact path from data input to code execution, identifying where validation fails and how to interrupt the chain before the system takes control.

Insecure deserialization occurs when an application processes untrusted data without verifying its integrity or structure. Attackers craft malicious serialized objects that, when reconstructed, execute arbitrary code. You can stop this by rejecting untrusted input, enforcing strict type checks, and using integrity checks like digital signatures.
The Foundation: Why Objects Become Data
Serialization is the process of converting a complex object in memory into a byte stream for storage or transmission. This allows applications to save state, send data over networks, or cache information for later use. The reverse process, deserialization, reconstructs the original object from that byte stream.
The vulnerability arises because many frameworks treat the incoming byte stream as trustworthy. The application assumes the data structure matches the expected object model. It does not verify whether the data was generated by a legitimate source or crafted by an adversary. This implicit trust is the foundation of the attack.
You might assume that because the data is internal or encrypted, it is safe. Encryption protects confidentiality, not integrity. If an attacker can modify the ciphertext or intercept the stream, they can alter the object structure before it reaches the application. The application decrypts and deserializes the tampered data, believing it to be valid.

Stage 1: Reconnaissance and Target Identification
The attacker begins by identifying where the application accepts serialized data. This is rarely obvious from the user interface. It often hides in API endpoints, cookie values, or hidden form fields. The attacker looks for indicators such as specific file extensions, content types, or base64-encoded strings.
They analyze the application’s technology stack to determine the serialization format. Java, PHP, Python, and .NET each have distinct serialization standards. Knowing the format allows the attacker to predict the structure of the byte stream. They may also look for error messages that reveal class names or library versions.
Imagine an attacker probing a login endpoint. They submit a malformed request and observe the error response. If the error mentions a specific class or library, it confirms the presence of a deserialization component. This information is critical for crafting a payload that the application will accept.
Stage 2: Payload Crafting
With the target identified, the attacker creates a malicious object. They do not need to write new code from scratch. They exploit existing classes within the application’s libraries. These classes often contain methods that execute logic when the object is created or modified.
The attacker chains these methods together to form a gadget chain. A gadget is a small piece of code that performs a specific action. By linking multiple gadgets, the attacker constructs a sequence that leads to arbitrary code execution. The goal is to make the deserialization process trigger these methods automatically.
This stage relies on the availability of vulnerable classes in the application’s dependencies. Even if your own code is secure, a third-party library might contain exploitable gadgets. The attacker searches for known gadget chains or uses automated tools to generate them. The resulting payload is a byte stream that looks like a legitimate object but contains hidden instructions.
Stage 3: Delivery and Input
The attacker sends the crafted payload to the vulnerable endpoint. This might be via an HTTP request, a file upload, or a network message. The payload is often encoded to bypass basic filters. Base64 encoding or URL encoding can mask the malicious structure from simple string checks.
The application receives the input and passes it to the deserialization engine. At this point, the data is still inert. It is just a sequence of bytes. The danger lies in what happens next. The application must decide whether to process this data or reject it.
If the application lacks input validation, it accepts the payload. It assumes the data is well-formed because it originated from a trusted channel or passed basic syntax checks. This assumption is the first point of failure. The attacker has successfully injected malicious data into the application’s trust boundary.
Stage 4: Deserialization and Object Reconstruction
The deserialization engine reads the byte stream and begins reconstructing the object. It allocates memory for the object and sets its properties based on the data. This process is automatic and often deep within the framework’s core.
As the object is rebuilt, the framework may invoke special methods. These methods, such as constructors or property setters, run automatically during reconstruction. If the attacker’s payload includes references to these methods, they execute without explicit permission from the application logic.
This is where the attack becomes active. The application is no longer just reading data; it is running code defined by the attacker. The gadget chain triggers a sequence of method calls. Each call leads to the next, moving closer to the final goal of code execution.
| Stage | What happens | Where it can be stopped |
|---|---|---|
| Reconnaissance | Attacker identifies serialization endpoints and formats. | Monitor for unusual input patterns and enforce strict API contracts. |
| Payload Crafting | Attacker builds a gadget chain using existing library classes. | Remove unnecessary classes and dependencies from the application. |
| Delivery | Malicious payload is sent to the application. | Validate input format and reject unexpected data structures. |
| Deserialization | Framework reconstructs the object and executes methods. | Implement integrity checks and restrict object types allowed for deserialization. |
See also: API Vulnerabilities: Definition, Mechanics, and Mitigation Strategies · Mass Assignment Vulnerabilities: How Unchecked Inputs Break Logic
Stage 5: Execution and Impact
The final stage is the execution of the attacker’s code. The gadget chain culminates in a command that runs on the server. This could be a shell command, a file read operation, or a network request to an external server.
The impact depends on the permissions of the application process. If the application runs with high privileges, the attacker gains significant control. They may access sensitive files, modify data, or pivot to other systems. The breach is often silent, as the code executes within the application’s normal flow.
Imagine a web application that deserializes a user session object. The attacker crafts a payload that includes a gadget chain to execute a system command. When the user logs in, the application deserializes the session, triggering the command. The attacker gains a reverse shell, allowing them to interact with the server remotely.
Interrupting the Chain
You can interrupt this process at several points. The most effective defense is to avoid deserializing untrusted data altogether. Use safer data formats like JSON or XML, which do not support automatic code execution. If you must use serialization, enforce strict type checks.
Validate the data before deserialization. Check the length, structure, and expected class types. Reject any data that does not match the expected schema. Use digital signatures or HMACs to ensure the data has not been tampered with. This adds a layer of integrity that attackers cannot bypass without the key.
Hidden Costs and Unexpected Failures
A common mistake is assuming that removing known vulnerable classes fixes the problem. New libraries may introduce new gadget chains. You must continuously monitor your dependencies for vulnerabilities. Automated tools can help, but they are not foolproof.
Another hidden cost is the performance overhead of strict validation. Checking every input can slow down the application. You must balance security with usability. However, the cost of a breach far exceeds the performance impact of validation.
Beyond Basic Validation
Deserialization vulnerabilities are complex because they exploit the trust between the application and its data. You cannot simply patch a single flaw. You must change how the application handles data. This requires a shift in mindset from trusting input to verifying it.
Consider using capability-based security models. Restrict what the deserialized objects can do. Limit their access to files, networks, and system commands. This reduces the impact of a successful attack. Even if the attacker executes code, their ability to cause damage is limited.
Key takeaways
- Serialization converts objects into a byte stream, but the process often preserves executable metadata that applications trust implicitly.
- Attackers do not need to guess passwords; they only need to find an input field that accepts serialized data and reconstructs it.
- Validation must happen before the deserialization engine processes the data, as post-processing checks are often too late to prevent execution.
Insecure deserialization exploits the automatic execution of code during data reconstruction, turning trusted data into a backdoor. You must validate input integrity and restrict deserialization to trusted, well-defined object types to prevent execution.
Frequently asked questions
Can encryption prevent insecure deserialization attacks?
No, encryption only protects confidentiality. If an attacker can modify the encrypted data or intercept it, they can still alter the object structure. You need integrity checks like digital signatures to prevent tampering.
Is JSON safe from deserialization attacks?
JSON is generally safer because it does not support automatic code execution. However, if the application uses a JSON deserializer that supports polymorphic types or custom hooks, it may still be vulnerable. Always validate JSON input strictly.
How do I know if my application is vulnerable?
Look for endpoints that accept serialized data formats like Java objects, PHP serialized strings, or .NET binary streams. Check if these inputs are validated before processing. If you see error messages revealing class names, you may be vulnerable.
What is the difference between deserialization and injection?
Injection involves inserting malicious code into a query or command. Deserialization involves reconstructing an object that contains executable logic. Deserialization is often harder to detect because the code is embedded within the data structure itself.
How this guide was produced: written by the RedTeam Tribune editorial team with AI assistance, checked against the public references listed below, and reviewed when the facts change. See our editorial policy or report an error.



