100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Security

Insecure Deserialization

Learn how deserializing untrusted data can lead to remote code execution, object injection, and denial of service, and how to safely handle serialized data.

Data & DependenciesAdvanced10 min readJul 10, 2026
Analogies

What Insecure Deserialization Is

Serialization converts an in-memory object into a byte stream or string for storage or transmission (session state, caching, inter-service messages), and deserialization reverses that process to reconstruct the object. Insecure deserialization happens when an application deserializes data from an untrusted source — a cookie, a form field, a message queue payload — without verifying its integrity or restricting what types can be reconstructed. Because many serialization formats (Java's native serialization, Python's pickle, PHP's unserialize, .NET's BinaryFormatter) allow the byte stream to specify arbitrary classes to instantiate, an attacker can craft a payload that triggers unintended code execution the moment it is deserialized, often before any application logic even runs.

🏏

Cricket analogy: It is like a franchise blindly trusting a courier-delivered sealed team-sheet envelope without checking the tamper seal, only to find the opposition swapped in a forged sheet that changes the batting order to sabotage the innings.

How Deserialization Attacks Achieve Code Execution

Attackers rarely need a direct 'execute shell command' hook; instead they chain together existing classes already present on the classpath — so-called 'gadget chains' — where the side effects of normal methods like constructors, finalizers, or getters, when invoked in sequence during deserialization, ultimately trigger something dangerous like reflection-based method invocation or file writes. Tools such as ysoserial for Java automate discovery and generation of these gadget chains against common libraries (Commons Collections, Spring, Hibernate), which is why insecure deserialization vulnerabilities have historically enabled remote code execution in widely used enterprise software like Jenkins, WebLogic, and Apache Struts.

🏏

Cricket analogy: A gadget chain is like a fielder relay throw: no single fielder does anything unusual, but the sequence — wicketkeeper to bowler to a diving mid-on — combines into a run-out nobody expected from any single throw alone.

Real-World Impact and Detection

The impact of insecure deserialization ranges from denial of service (triggering excessive resource allocation during object reconstruction) to full remote code execution, as seen in the 2017 Apache Struts vulnerabilities used in the Equifax breach and repeated Jenkins plugin CVEs involving XStream and Java serialization. Detection involves auditing code for calls like ObjectInputStream.readObject() in Java, pickle.loads() in Python, or unserialize() in PHP that operate on data originating from HTTP requests, cookies, or message queues, and checking whether any type/class whitelisting or integrity verification (HMAC signatures) is applied before deserialization occurs.

🏏

Cricket analogy: It is like the aftermath review after a controversial no-ball call: officials trace back through every step of the delivery (front-foot landing, bowler's arm angle) to find exactly where the process broke down, just as security teams trace exactly which deserialization call was reachable from untrusted input.

python
# Bad: deserializing untrusted data with pickle allows arbitrary code execution
import pickle
data = request.get_data()
obj = pickle.loads(data)  # DANGEROUS: attacker-controlled bytes can execute code

# Good: use a safe, data-only format and validate structure/schema
import json
from jsonschema import validate

SCHEMA = {
    "type": "object",
    "properties": {"user_id": {"type": "integer"}, "items": {"type": "array"}},
    "required": ["user_id", "items"],
    "additionalProperties": False
}

data = request.get_json()
validate(instance=data, schema=SCHEMA)  # rejects unexpected structures
cart = build_cart_from_dict(data)  # explicit, controlled reconstruction

Never call native deserialization functions (pickle.loads, ObjectInputStream.readObject, unserialize, BinaryFormatter.Deserialize) directly on data that originates from a user, cookie, or external service. If native serialization must be used internally, sign payloads with an HMAC and verify the signature before deserializing, and restrict deserialization to an explicit class whitelist.

Preventing Insecure Deserialization

The strongest mitigation is avoiding native binary serialization formats for anything touching untrusted input, favoring data-only formats like JSON or Protocol Buffers that cannot carry executable class instructions, combined with strict schema validation. When native serialization is unavoidable (legacy interop, specific performance needs), apply integrity checks such as HMAC signatures on the serialized blob so tampered payloads are rejected before deserialization even begins, enforce type/class whitelisting (Java's ObjectInputFilter, look-ahead deserialization), run the deserializing process with least-privilege permissions in a sandboxed environment, and keep libraries patched since most real-world exploits rely on known gadget chains in outdated dependencies.

🏏

Cricket analogy: Using JSON instead of native serialization is like replacing a sealed, unverifiable envelope team-sheet with a publicly witnessed announcement read aloud at the toss — there's no room for a hidden, tamperable payload.

OWASP's Deserialization Cheat Sheet recommends, in order of preference: (1) avoid native deserialization of untrusted data entirely, (2) use data-only formats with schema validation, (3) if native serialization is required, apply integrity checks and class whitelisting, and (4) run deserialization in a low-privilege, sandboxed context as a last line of defense.

  • Insecure deserialization occurs when untrusted data is reconstructed into objects without validation, often enabling remote code execution.
  • Gadget chains combine benign existing classes' side effects to achieve unintended, dangerous behavior during deserialization.
  • Native binary formats (Java serialization, pickle, unserialize, BinaryFormatter) are especially risky because they can instantiate arbitrary classes.
  • Prefer data-only formats (JSON, Protocol Buffers) with strict schema validation for untrusted input.
  • If native serialization is unavoidable, apply HMAC integrity checks and class/type whitelisting before deserializing.
  • Real-world breaches (Equifax via Apache Struts, multiple Jenkins CVEs) trace directly back to insecure deserialization.
  • Keep serialization libraries patched, since most exploits rely on known gadget chains in outdated dependencies.

Practice what you learned

Was this page helpful?

Topics covered

#Security#WebSecurityOWASPStudyNotes#CyberSecurity#InsecureDeserialization#Insecure#Deserialization#Attacks#Achieve#StudyNotes#SkillVeris