The Problem with Untrusted Data
Deserialization is a fundamental process in modern software development. It involves converting serialized data—often a byte stream or text format—back into an object or data structure that an application can use. This is essential for tasks like maintaining application state across requests, inter-process communication, caching, and data storage. However, when applications deserialize data originating from untrusted or attacker-controlled sources without adequate validation, they introduce a significant security risk.
The core of the problem lies in the deserialization process itself. Many serialization mechanisms, particularly native language-specific ones, reconstruct objects by invoking constructors, setters, and even "magic" or special methods (like __destruct or __wakeup in PHP, or readObject in Java) as part of the reconstruction. If an attacker can control the serialized input, they can craft it to instantiate malicious classes or trigger these special methods, leading to unintended and potentially dangerous behavior. This effectively transforms a data handling operation into an arbitrary code execution vulnerability [1] [2] [3].
The OWASP Top Ten consistently highlights insecure deserialization as a critical risk. In the 2017 list, it was ranked #8, and in the 2021 list, it was subsumed into the broader category of "Software and Data Integrity Failures" [4] [1]. This signifies its pervasive and high-impact nature.
The danger is amplified by the vast ecosystem of libraries and frameworks applications depend on. These dependencies often introduce "gadgets"—classes or methods that, when chained together during deserialization, can achieve arbitrary code execution. Attackers don't need to inject new code; they leverage existing, legitimate code to achieve malicious ends [5] [6] [7]. This makes mitigation challenging, as simply removing known dangerous classes is often impractical due to transitive dependencies and the constant discovery of new gadget chains [8] [2].
Core Mechanics: How Deserialization Becomes Exploitable
At its heart, insecure deserialization occurs when an application trusts serialized data to the point where it allows the reconstruction of arbitrary objects, often without verifying the object's origin, integrity, or type. The exploitability hinges on several key factors:
- Untrusted Data Input: The attacker must be able to influence the serialized data that the application deserializes. This can come from various sources, including HTTP requests (headers, body, cookies), API endpoints, message queues, or even file uploads [9] [10] [11] [12] [3].
- Deserialization Sink: The application must have a code path that calls a deserialization function (e.g.,
pickle.loads()in Python,unserialize()in PHP,ObjectInputStream.readObject()in Java,BinaryFormatter.Deserialize()in .NET) with user-controllable data [13] [10] [14] [15]. - Gadget Chains: The application's classpath or environment must contain vulnerable classes (gadgets) that can be chained together during the deserialization process to perform malicious actions. These chains often leverage reflection or special methods that are invoked automatically during object reconstruction [16] [8] [5] [17] [18] [19].
When these conditions align, the deserialization process itself becomes the attack vector. Instead of merely reconstructing data, it can be manipulated to trigger code execution, manipulate application state, cause denial-of-service conditions, or escalate privileges.
Notable Techniques and Attack Vectors
Deserialization vulnerabilities manifest across numerous programming languages and platforms, with specific techniques evolving based on the underlying serialization libraries and runtime environments.
Java Deserialization
Java's native serialization mechanism, particularly via ObjectInputStream.readObject(), is a well-known source of vulnerabilities [17] [20] [2]. The availability of powerful libraries like Apache Commons Collections, Spring, and Groovy provides a rich source of gadgets.
Gadget Chains: Attackers construct sequences of method calls from available classes that, when triggered by deserialization, lead to arbitrary code execution. A classic example involves LazyMap and ChainedTransformer from Apache Commons Collections, which can be chained to call Runtime.exec() [17] [21] [11] [22]. Tools like ysoserial automate the generation of these payloads [23] [21] [19].
Specific Libraries:
- Jackson Databind: Prior to version 2.10.0, Jackson's support for polymorphic type handling (PTH) allowed attackers to instantiate arbitrary classes, leading to RCE via gadget chains like
TemplatesImpl[24] [22]. - SnakeYAML: Versions prior to 2.0 were vulnerable because, by default, SnakeYAML allowed the instantiation of arbitrary Java classes from untrusted YAML sources [25].
- XStream: Older versions of XStream, particularly prior to 1.4.15, were vulnerable to RCE via deserialization of untrusted XML or JSON data, often through gadget chains abusing core Java classes or framework libraries [26] [8] [22].
- Fastjson: Known for its vulnerability to RCE through autoType support, allowing arbitrary class instantiation and execution if not properly configured [27] [22].
PHP Deserialization
PHP's unserialize() function is a common target. Vulnerabilities often arise from classes with "magic methods" like __wakeup() or __destruct(), which are automatically called during deserialization and can be manipulated to execute arbitrary code or perform file operations [28] [10] [29] [30] [15].
PHAR Deserialization: A specific PHP technique abuses the phar:// stream wrapper. When file operations are performed on PHAR archives using this wrapper, the metadata (which can contain serialized objects) is automatically deserialized, potentially leading to RCE via Property-Oriented Programming (POP) chains [31] [29] [15].
POP Chains: Attackers construct serialized objects that leverage magic methods and controllable object properties to hijack control flow and achieve code execution [32] [30]. Tools like phpggc can generate payloads for various PHP frameworks.
Python Deserialization
Python's pickle module is notoriously insecure. The documentation explicitly warns against unpickling untrusted data due to its ability to execute arbitrary code via the __reduce__ method [33] [13] [34] [1] [35] [36].
Model Loading in ML: A significant attack surface exists in AI/ML frameworks that use pickle for model serialization. Maliciously crafted model files can execute arbitrary code when loaded, posing a supply chain risk [37] [38] [34]. Tools like PickleScan aim to detect malicious pickles, but have themselves been found to have bypasses [38] [39].
YAML Deserialization: Libraries like PyYAML, when used with unsafe loaders (e.g., yaml.unsafe_load() or yaml.load(..., Loader=yaml.UnsafeLoader)), are also vulnerable to RCE [13] [40] [41].
.NET Deserialization
In the .NET ecosystem, several serialization formats are susceptible:
- BinaryFormatter: This is widely recognized as insecure and dangerous, especially with untrusted data. It allows for unrestricted polymorphic deserialization and is a common vector for RCE [42] [14] [43].
- ViewState: ASP.NET's ViewState mechanism, used for persisting page state, can be vulnerable if the machine key is compromised or validation is bypassed. Attackers can craft malicious ViewState payloads that lead to RCE [44] [45] [46].
- JSON.NET (Newtonsoft.Json): When
TypeNameHandlingis enabled without proper validation or aSerializationBinder, attackers can specify arbitrary .NET classes to be instantiated, leading to RCE [42] [47] [14]. DataContractSerializer,NetDataContractSerializer,XmlSerializer,LosFormatter,ObjectStateFormatter: These are also identified as potentially insecure deserialization methods, especially when handling untrusted input [42] [14].
Tools like ysoserial.net are used to generate .NET deserialization payloads leveraging gadget chains within common .NET libraries [42] [48] [19].
Other Languages and Formats
- Ruby: The
Marshalmodule in Ruby is susceptible to deserialization attacks. Gadget chains have been discovered that leverage standard library classes to achieve RCE, bypassing the need for external dependencies [49] [50] [51] [52] [7]. YAML deserialization usingYAML.loadis also a common vector [49] [52]. - Node.js: Insecure deserialization vulnerabilities can occur when handling untrusted data with libraries like
evalor certain JSON parsing contexts [10].
Detection and Prevention
Effectively detecting and preventing insecure deserialization requires a multi-layered approach focusing on code hygiene, input validation, and runtime monitoring.
Detection Strategies
- Code Auditing (SAST): Static analysis tools can identify the use of known vulnerable deserialization functions (e.g.,
pickle.loads,unserialize(),ObjectInputStream.readObject(),BinaryFormatter.Deserialize()) with user-controlled input [13] [30] [53] [15]. - Dynamic Analysis (DAST) and Penetration Testing: These methods simulate real-world attacks by sending crafted serialized payloads to identify vulnerable endpoints and data sinks [4] [11] [54] [15].
- Network Traffic Analysis: Monitoring network traffic for characteristic patterns of serialized data (e.g., Java's magic bytes
AC ED 00 05orrO0, PHP's serialized object format, Base64 encoding of known payloads) can help detect ongoing attacks [10] [55] [12] [15]. - Runtime Monitoring: Observing application behavior for anomalies during deserialization, such as unexpected process creation from the deserializing process, unusual resource consumption, or deserialization exceptions, can indicate exploitation attempts [56] [57] [58].
- Dependency Scanning: Identifying and analyzing the security posture of libraries and frameworks used by the application is crucial, as many gadget chains reside in these dependencies [59] [16] [37].
Prevention and Mitigation
The most robust mitigation strategy is to avoid deserializing untrusted data altogether. When unavoidable, stricter controls are necessary:
- Avoid Native Deserialization of Untrusted Data: Prefer language-agnostic data formats like JSON or XML, which typically reconstruct data structures rather than executable objects. If serialization is required, ensure it uses formats that do not allow arbitrary object instantiation [4] [9] [41] [54] [1] [12] [2] [3].
- Input Validation and Sanitization: Before deserializing, rigorously validate and sanitize all data originating from user input. This includes checking data types, lengths, and formats. However, complete sanitization against all gadget chains is extremely difficult [4] [9] [34] [54] [1].
- Integrity Checks and Digital Signatures: For critical serialized data, implement integrity checks using digital signatures or MACs (Message Authentication Codes) to ensure the data has not been tampered with. Verify these checks before deserialization [4] [9] [41] [54] [1].
- Serialization Filters/Allowlisting: For Java, use serialization filters (e.g., JEP 290) to define an explicit allowlist of classes that are permitted to be deserialized [41] [54] [60] [1]. Similarly, in .NET, use a
SerializationBinderto whitelist types [47] [14]. - Limit Privileges: Execute deserialization code in the least-privileged environment possible. If deserialization is compromised, this limits the attacker's ability to escalate privileges or execute system-wide commands [4] [61].
- Disable Dangerous Serializers: For .NET, explicitly avoid insecure serializers like
BinaryFormatter. Prefer safer alternatives likeSystem.Text.JsonorNewtonsoft.JsonwithTypeNameHandling.None[42] [14] [43] [47]. - Keep Libraries Updated: Regularly update all dependencies, including serialization libraries and frameworks, to patch known vulnerabilities [59] [4] [9] [57] [20].
- Secure Configuration: Ensure that serialization configurations are secure by default. For example, in Jackson, disable polymorphic type handling, and in PyYAML, use the
SafeLoader[24] [13] [47].
Tooling for Deserialization Security
A variety of tools assist in identifying, generating, and mitigating deserialization vulnerabilities:
ysoserial/ysoserial.net: Command-line tools for generating Java and .NET deserialization payloads, respectively, using known gadget chains [23] [21] [48] [19].Burp Suite: Extensions like Burp Scanner,SuperSerial, and integrations withysoserialcan help detect and exploit serialized data within HTTP traffic [55] [22] [15].marshalsec: A tool for Java deserialization that assists in creating payloads for various marshallers and formats [55] [22].phpggc: A tool for generating PHP deserialization payloads targeting various frameworks [29].jdeserialize: A utility for converting serialized Java objects into a human-readable format for analysis [11].- Radare2 with
r2pickledec: For reversing Python pickles, providing decompilation and analysis capabilities [36]. Spectre-bytes/GadgetProbe: Tools for discovering gadget chains within Java applications [22].- Static Analysis (SAST) tools: Tools like SonarQube can identify insecure deserialization patterns in code [30].
Recent Developments
The landscape of deserialization vulnerabilities is constantly evolving:
- Machine Learning and AI Models: The use of
picklefor serializing ML models has introduced new supply chain risks, with attackers embedding malicious code within model files. Research is ongoing to develop safer serialization formats (e.g., SafeTensors) and improved scanning tools [37] [38] [34]. - Framework-Specific Vulnerabilities: New vulnerabilities continue to be discovered in popular frameworks and libraries, such as React Server Components (CVE-2025-55182) [59], Wazuh (CVE-2026-25769) [58], IBM Langflow Desktop (CVE-2026-3357) [60], and various components within .NET and Java ecosystems [23] [62] [63] [64] [56] [57] [65] [66] [67] [68] [69].
- Gadget Chain Mining Automation: Advancements in automated discovery tools, like FLASH, are improving the precision and recall of finding gadget chains by employing deserialization-guided call graph construction [16].
- Shadow Vulnerabilities: Risks can emerge from indirect dependencies, making them hard to detect through traditional code scanning or dependency analysis. These "shadow vulnerabilities" become apparent only at runtime [40].
Where to Go Deeper
For those seeking to deepen their understanding and practical skills in dealing with deserialization vulnerabilities, the following resources are highly recommended:
- OWASP Deserialization Cheat Sheet: A comprehensive resource covering concepts, language-specific guidance, and mitigation strategies [2] [41].
- PortSwigger Web Security Academy: Offers detailed explanations and interactive labs for exploiting various deserialization vulnerabilities in PHP, Ruby, and Java [15] [70] [3].
ysoserialandysoserial.netGitHub Repositories: Provide exploit payloads and detailed information on common gadget chains for Java and .NET [23] [21] [48].PayloadsAllTheThingsGitHub Repository: A vast collection of security payloads, including extensive sections on deserialization for various languages [42] [13] [49] [29] [55] [22].- Research Papers and Blog Posts: Numerous academic papers and security blogs offer in-depth analyses of specific vulnerabilities, exploit techniques, and defense mechanisms (e.g., articles on Medium, Snyk, SentinelOne, Praetorian, Bishop Fox, and many others cited in this document) [71] [72] [73] [26] [74] [33] [75] [76] [8] [31] [77] [44] [45] [37] [9] [5] [56] [46] [57] [25] [40] [38] [78] [79] [49] [50] [17] [80] [6] [21] [48] [10] [51] [81] [65] [29] [32] [82] [30] [14] [43] [66] [47] [83] [39] [84] [34] [11] [18] [41] [20] [55] [54] [58] [67] [60] [85] [61] [68] [69] [53] [52] [86] [1] [87] [7] [12] [19] [22] [2] [15] [35] [36] [70] [3].
- CVE Databases and Advisories: Regularly check resources like the National Vulnerability Database (NVD), CISA's Known Exploited Vulnerabilities (KEV) catalog, and vendor security advisories for the latest information on disclosed vulnerabilities [59] [88] [62] [63] [45] [56] [57] [68].