Unsafe Deserialization
Description
Unsafe Deserialization (also referred to as Insecure Deserialization) is a vulnerability wherein an application insecurely deserializes malformed and untrusted data input. It is exploited to hijack the logic flow of the application and may result in the execution of arbitrary code. Although this isn’t exactly a simple attack to employ, it featured in OWASP’s Top 10 most recent iteration as part of the Software and Data Integrity Failures risk, due to the severity of impact upon compromise.
Converting an object state or data structure into a storable or transmissible format is called serialization. Deserialization is the opposite; it’s the process of extracting the serialized data to reconstruct the original object version.
Unsafe Deserialization issues arise when an attacker can pass ad hoc malicious data into user-supplied data to be deserialized. This could result in arbitrary object injection into the application, potentially influencing its intended behavior.
Gadget Chains
To exploit deserialization bugs, gadget chains are usually leveraged. A gadget chain is a sequence of existing classes and methods available at runtime that, when instantiated or invoked during deserialization, produce side effects that an attacker wants (file operations, command execution, network calls, etc.).
Each gadget is normally benign, but when combined, they form a pipeline that turns attacker-controlled data into harmful actions. Gadget chains require no new code; they rely only on the presence of such patterns in the application or its libraries.
Impact
A successful Unsafe Deserialization attack can result in the full compromise of the confidentiality, integrity, and availability of the target system, and the oft-cited Equifax breach is an example of the worst-case outcome. In Equifax’s case, an unsafe Java deserialization attack leveraging the Struts 2 framework resulted in Remote Code Execution, which, in turn, led to the largest data breach in history.
Prevention
It is important to consider any development project from an architectural standpoint to determine when and where serialization is necessary. If it is unnecessary, consider using a simpler format when passing data.
In cases where it is impossible to forgo serialization without disrupting the application’s operational integrity, developers can implement a range of defense-in-depth measures to mitigate the chances of being exploited.
- Use serialization that permits only primitive data types.
- Use a serialization library that provides cryptographic signature and encryption features to ensure serialized data is untainted.
- Identify and minimize available gadgets by first locating components that could act as gadgets, and then removing or patching them to reduce the attack surface.
- Use low-privilege environments to isolate and run code that deserializes.
Finally, if possible, replace object serialization with data-only serialization formats, such as JSON.
Testing
Verify that serialization is not used when communicating with untrusted clients. If this is not possible, ensure that adequate integrity controls (and possibly encryption if sensitive data is sent) are enforced to prevent deserialization attacks, including object injection.
- OWASP ASVS: 1.5.2, 5.5.1, 5.5.3