Skip to main content
Category: Vulnerability Management

Deserialization Attacks

Also known as: Insecure Deserialization, Deserialization Vulnerabilities, Object Deserialization Attacks
Simply put

Deserialization attacks occur when an application converts externally supplied data back into objects without adequately verifying that the data is safe or legitimate. An attacker can manipulate or inject malicious content into this process to abuse the application's logic. This may result in unauthorized code execution, privilege escalation, or other harmful outcomes.

Formal definition

Deserialization attacks exploit vulnerabilities that arise when untrusted or user-controllable serialized data is consumed by an application's deserialization process without sufficient validation or integrity checking. Because deserialization typically reconstructs objects by invoking application logic, an attacker who can manipulate the serialized payload may abuse existing class behaviors, inject malicious data, or trigger unintended code paths. Exploitation outcomes may include remote code execution, injection of malicious code or data analogous to SQL injection, and logic abuse, depending on the target language runtime, available classes, and how deserialized objects are subsequently used. The vulnerability class is distinct from purely static code flaws in that exploitability typically depends on runtime context, including which classes are available on the deserialization path and how the application processes the resulting objects.

Why it matters

Deserialization attacks represent one of the more severe vulnerability classes in modern application security because successful exploitation can yield remote code execution, privilege escalation, or deep injection of malicious data into application logic. Unlike many vulnerabilities that affect only a narrow layer of an application, deserialization flaws can affect any component that consumes externally supplied serialized data, including APIs, session mechanisms, message queues, and inter-service communication channels. This broad attack surface means that a single vulnerable deserialization endpoint can expose an entire application or backend system.

The nature of deserialization makes these vulnerabilities particularly difficult to address through surface-level controls. Because the application's own class library and runtime are typically leveraged during exploitation, attackers can often abuse legitimate code paths rather than injecting shellcode or foreign logic. This means that input filtering alone is generally insufficient as a defense, and that exploitability is highly dependent on runtime context, including which classes are loaded and how deserialized objects are subsequently consumed by the application.

The Apache Commons Collections gadget chain vulnerability, which was publicly detailed around 2015, demonstrated how widely deployed Java libraries could be chained together to achieve remote code execution through insecure deserialization in numerous enterprise products. That incident brought significant attention to how transitive dependencies and available class libraries expand the exploitability of deserialization vulnerabilities far beyond what application developers may anticipate. OWASP has recognized insecure deserialization as a critical risk category, reflecting the severity and prevalence of this vulnerability class across technology stacks.

Who it's relevant to

Application Developers
Developers who build or maintain applications that accept serialized input from users, external services, or message brokers are directly responsible for implementing safe deserialization practices. This includes avoiding deserialization of untrusted data where possible, using safer data formats, and applying integrity checks such as digital signatures to serialized payloads before processing them.
Security Engineers and AppSec Teams
Security engineers need to understand the scope and limitations of controls applied to deserialization risks. Static analysis tools can typically flag potentially unsafe deserialization calls in source code but cannot reliably determine exploitability without runtime context, including available class libraries and downstream object usage. AppSec teams should complement static analysis with dynamic testing and manual code review focused on how deserialized objects are consumed.
Penetration Testers
Penetration testers assessing web applications and APIs should evaluate all data ingestion points for insecure deserialization, including session tokens, API request bodies, and inter-service communication channels. Effective testing typically requires understanding the target language runtime and identifying available gadget chains or downstream object handling logic, as exploitability depends heavily on runtime context rather than the deserialization call in isolation.
Software Architects
Architects designing systems that exchange data between components or expose APIs should consider whether serialization formats that support rich object graphs are necessary, or whether simpler, safer formats such as plain JSON with explicit schema validation are preferable. Architectural decisions about which libraries are included in a deployment also affect the exploitability of any deserialization vulnerabilities present, since available classes expand the potential gadget chain surface.
Third-Party Risk and Supply Chain Security Teams
Because exploitability of deserialization vulnerabilities often depends on which third-party libraries are available on the application's classpath or runtime path, supply chain and dependency management practices directly affect risk. Teams responsible for software composition analysis should track dependencies that have known gadget chains or unsafe deserialization behaviors, as these can amplify the impact of vulnerabilities elsewhere in the application.

Inside Deserialization Attacks

Serialization
The process of converting an in-memory object or data structure into a format (such as binary, JSON, XML, or YAML) that can be stored or transmitted across a network boundary.
Deserialization
The reverse process of reconstructing an in-memory object from a serialized byte stream or text representation, typically restoring the original object's state and type.
Gadget Chain
A sequence of existing classes or methods within an application's classpath or runtime environment that an attacker assembles to achieve malicious behavior, such as remote code execution, when triggered during deserialization of attacker-controlled data.
Attacker-Controlled Input
Serialized data supplied by an untrusted source, such as a cookie, HTTP request body, message queue payload, or inter-service communication, that is passed directly into a deserialization routine without sufficient validation.
Type Confusion
A condition that may arise during deserialization when the runtime instantiates an object of a type different from what the application expects, potentially bypassing application logic or triggering unintended behavior in loaded classes.
Remote Code Execution (RCE)
A common high-severity outcome of successful deserialization attacks, in which the attacker's gadget chain causes the target system to execute arbitrary operating system commands or application code.
Allowlist-Based Deserialization
A defensive control that restricts the set of types permitted to be instantiated during deserialization to a predefined, explicitly approved list, reducing the available gadget surface.
Integrity Verification
A control such as HMAC signing or digital signatures applied to serialized payloads before transmission, used to detect tampering and reject modified or forged payloads prior to deserialization.

Common questions

Answers to the questions practitioners most commonly ask about Deserialization Attacks.

Does switching to a text-based format like JSON automatically make deserialization safe?
No. While JSON libraries are generally safer than native binary serialization formats such as Java's ObjectInputStream or Python's pickle, text-based formats are not inherently immune to deserialization attacks. JSON parsers can still be vulnerable if they support type coercion, polymorphic type handling, or automatic object instantiation features. Libraries such as Jackson (with certain modules enabled) have had documented deserialization vulnerabilities despite operating on JSON. The safety of any deserialization operation depends on the library's configuration and the degree to which it allows the input to influence object construction, not solely on whether the format is text or binary.
Is input validation on the receiving end sufficient to prevent deserialization attacks?
Not on its own. Input validation applied before or during deserialization is a useful defense layer, but it typically cannot catch all malicious payloads. Many deserialization vulnerabilities are exploited through gadget chains, where individually benign class instances are assembled into a sequence that produces harmful behavior when the object graph is resolved. Validating field values or checking superficial structure does not prevent the instantiation and linking of these classes. Effective defense requires additional controls such as allowlisting permitted classes, disabling dangerous deserialization features at the library or runtime level, and isolating deserialization operations.
How should an application restrict which classes can be instantiated during deserialization?
Applications should implement allowlist-based class filtering rather than attempting to blocklist known dangerous classes. Blocklists are brittle because new gadget chains are regularly discovered. In Java, this can be implemented using ObjectInputFilter (available since Java 9) to permit only expected classes. In other ecosystems, equivalent controls may be available at the library configuration level. The allowlist should be defined as narrowly as possible, permitting only the specific types the application legitimately deserializes. This approach requires understanding the full set of types involved in normal operation before deployment.
What should security teams look for when reviewing code for deserialization vulnerabilities during a static analysis or code review?
Reviewers should identify all entry points where serialized data enters the application, including network sockets, HTTP request bodies, message queues, cookies, and file inputs. Key indicators include use of native deserialization mechanisms such as ObjectInputStream in Java, pickle.loads in Python, or unserialize in PHP, particularly when operating on data from untrusted sources. Reviewers should also check whether deserialization libraries are configured with type restrictions, whether any custom readObject or similar methods perform unsafe operations, and whether deserialized objects are used in sensitive operations such as reflection, process execution, or database access before validation. Static analysis can identify the presence of these patterns but typically cannot confirm exploitability without understanding runtime data flow.
How can developers test whether their application is vulnerable to deserialization attacks?
Testing typically combines static analysis, dynamic testing, and known-payload probing. Tools such as ysoserial (for Java) generate payloads that exercise known gadget chains and can be used in controlled environments to test whether an endpoint is vulnerable. Dynamic application security testing (DAST) tools may include deserialization payload checks for common frameworks. Penetration testers commonly manipulate serialized objects found in cookies or request bodies to assess whether type manipulation is possible. It is important to note that the absence of a known exploit payload triggering a vulnerability does not confirm safety, since new gadget chains may apply to the target environment even if currently unpublished.
What logging and monitoring controls are most useful for detecting deserialization attacks in production?
Effective monitoring focuses on detecting anomalous behavior that deserialization exploits commonly produce, since the exploit itself may not be directly observable in application logs. Useful signals include unexpected process spawning from application server processes, outbound network connections initiated by application processes to unknown hosts (often associated with out-of-band payload delivery), deserialization errors or class-not-found exceptions at unusual rates, and access to file paths or system resources inconsistent with normal application behavior. Runtime application self-protection (RASP) tools, where available, can intercept deserialization operations at the library level and provide more direct visibility. Logs from these controls should be correlated with network and endpoint telemetry for more reliable detection.

Common misconceptions

Only Java or .NET applications are vulnerable to deserialization attacks.
Deserialization vulnerabilities affect many languages and frameworks, including Python (pickle), Ruby (Marshal), PHP (unserialize), and others. The specific exploitation techniques and gadget chains differ by platform, but the underlying risk of processing untrusted serialized data is broadly applicable.
Encrypting serialized data fully prevents deserialization attacks.
Encryption protects data confidentiality in transit but does not prevent deserialization attacks on its own. If an attacker can obtain or derive the encryption key, or if the application decrypts and deserializes attacker-supplied data before validating its integrity or type, exploitation may still be possible. Integrity controls such as authenticated encryption or separate HMAC signing are necessary complements.
Static analysis tools can reliably detect all exploitable deserialization vulnerabilities in an application.
Static analysis can typically identify dangerous deserialization sinks and flag use of unsafe APIs at the code level, but determining whether a complete, exploitable gadget chain exists in the runtime classpath generally requires dynamic analysis or manual review. False negatives are common because gadget chain reachability depends on runtime context, loaded dependencies, and attacker-controlled input paths that are not fully visible without execution context.

Best practices

Avoid deserializing data from untrusted sources whenever possible; prefer safer data exchange formats such as JSON or XML with schema validation rather than native serialization formats that support arbitrary object instantiation.
Implement allowlist-based type filtering during deserialization to restrict instantiable classes to only those explicitly required by the application, reducing the available gadget chain surface.
Apply integrity verification to serialized payloads using authenticated encryption or HMAC signing before transmission, and reject any payload that fails verification prior to deserialization.
Keep all third-party libraries and frameworks up to date, as many known gadget chains exploit vulnerabilities in widely used dependencies; monitor software composition analysis (SCA) tooling for components with known deserialization-related CVEs.
Run deserialization operations in isolated, least-privilege environments where possible, so that even a successful gadget chain execution is constrained in the damage it can cause to the broader system.
Include deserialization attack scenarios explicitly in threat modeling and security testing activities, using both static analysis to identify sinks and dynamic testing tools to probe for exploitable gadget chains in the runtime environment.