scanrub
Deserialization of Untrusted Datahigh prioritynot yet scanned

Insecure Deserialization

2 min read 47 reports analyzed ScanRub Research
Share

Summary

Reports cluster around language-specific deserialization-to-RCE: PHP Phar streams (concrete5 CVE-2021-36766), Ruby Marshal (RubyGems Bundler response), Java SnakeYAML (Kubernetes Java client), .NET Telerik UI BinaryFormatter (CVE-2019-18935), Python pickle in Django cache (CVE-2021-33026), Java JNDI in Log4Shell (CVE-2021-44228), and Java JMX exposing unauthenticated deserialization (Basecamp jabber server). Also Kafka Connect via JNDI in JAAS config. Detection is largely CVE-marker-driven plus surface signals (presence of base64-encoded blobs in cookies/body that decode to language-specific magic bytes).

◈ flow diagram
Attacker Pay…Serialized I…Deserializat…Gadget ChainArbitrary Co…
◈ chart
Critical
16
High
19
Medium
9
Low
2

Top Affected Components / Targets

  • Java apps with JNDI / Log4j / Spring
  • PHP CMS with file-existence checks on user paths (Phar)
  • Ruby/Python apps with cache or queue backends using native serialization
  • Telerik UI
  • Apache Kafka Connect / JMX-exposed services
  • Hadoop / Spark / Hive clusters

Common Attack Vectors

  • Submit Java serialized object (rO0AB...) in cookie / body / header
  • Submit pickle (gAS...) in Python apps
  • Submit Marshal-encoded (\x04\x08...) in Ruby apps
  • Submit YAML with !!python/object or !!java.* tags
  • Submit phar:// URL via file path
  • Submit JNDI URL in Log4j-bound fields
  • Hit JMX RMI endpoints unauthenticated

Common Payloads

  • ${jndi:ldap://<oast>/}
  • rO0AB... (Java serialized)
  • gAS (Python pickle magic)
  • \x04\x08... (Ruby Marshal magic)
  • !!python/object/apply:os.system ["id"]
  • !!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [...]]
  • phar:///tmp/uploaded.phar
  • Telerik DialogHandler payload

Detection Strategy

Stage 1: CVE marker via Nuclei

Ensure templates for Log4Shell, ProxyLogon, Telerik CVE-2017-11317/CVE-2019-18935, Confluence OGNL, Spring4Shell, JMX-RMI-no-auth.

Stage 2: Log4Shell probe

Same as in Command Injection synthesis - spray ${jndi:ldap://oast/} into headers and bodies.

Stage 3: deserialization-marker advisory

When Authorization cookies or body fields contain base64 strings whose decoded bytes match Java/Python/Ruby serialization magic bytes, emit advisory finding gated on whether the application accepts modified blobs without HMAC.

Stage 4: Phar advisory

If PHP application accepts file paths and exposes file_exists-style behaviour, emit advisory pointing to phar:// risk.

Stage 5: JMX/RMI port probe

In port-scan stage, flag exposed JMX (default ports 1099, 7199, 9999, 9997).

Tip: Testing tools that run these checks in parallel across every discovered endpoint can cut the time required substantially compared to fully manual testing, as long as they confirm findings with more than one signal to keep the false-positive rate down.

False-Positive Notes

  • Active deserialization exploitation is risky and dependent on language-specific gadget chains.
  • Stick to CVE markers + advisory signals.

How to Test

Manual Testing Methodology

Here is a systematic approach to identifying Insecure Deserialization vulnerabilities in a target application.

Step 1: Reconnaissance and Surface Mapping

Before testing, map all input vectors that could be affected. Identify parameters, headers, cookies, and request bodies that interact with the vulnerable component. A proxy such as Burp Suite or OWASP ZAP, paired with normal browsing of the target, is usually enough to build this list.

Step 2: Baseline Request

Send a legitimate request and record the normal response: status code, content length, response time, and any identifying tokens. This baseline matters because it's what you'll compare later responses against once payloads are involved.

Step 3: Payload Injection

Inject test payloads into each identified input vector one at a time. Start with benign detection payloads before escalating to anything that could actually trigger the vulnerability. For Insecure Deserialization specifically, identify every point where serialized data (native Java/PHP/Python/.NET serialization formats, or a framework's custom binary format) crosses a trust boundary, then submit a known public gadget-chain payload for the identified library/version, starting with an out-of-band callback payload to confirm execution safely before attempting anything destructive.

Step 4: Response Analysis

Compare the response against your baseline, looking specifically for an out-of-band callback (DNS/HTTP) confirming code execution, or a deserialization-specific exception revealing the underlying library and version — a stack trace naming ObjectInputStream, readObject, or an equivalent is a strong signal even before a full gadget chain is confirmed.

Step 5: Confirmation

Once a potential vulnerability is detected, confirm it with at least a few independent test cases to rule out coincidence. Document the exact request and response as proof. For Insecure Deserialization, a confirmed finding typically means showing that attacker-controlled input changes the application's behavior in a way that matters for security, not just that a payload was reflected somewhere harmless.

Real-World Impact

Real-World Impact

Insecure deserialization is one of the more severe vulnerability classes because it frequently leads directly to remote code execution. When an application deserializes attacker-controlled data without validating it first, a specially crafted payload can instantiate arbitrary objects, invoke dangerous methods, and ultimately run operating system commands.

In Java applications using ObjectInputStream, XStream, or Jackson with polymorphic typing enabled, deserialization gadget chains built from libraries like Commons-Collections or Spring provide reliable paths to code execution. Equivalent primitives exist in PHP's unserialize, Python's pickle, and .NET's BinaryFormatter.

The impact tends to be immediate and complete: full server compromise, lateral movement, data exfiltration, and persistent backdoors. This vulnerability class has been behind some of the largest breaches on record, including the Equifax breach, which traced back to an Apache Struts deserialization flaw.

Prevention & Remediation

Prevention and Secure Coding

Preventing Insecure Deserialization takes a defense-in-depth approach — no single control below is sufficient alone, but together they close off both the primary path and the most common bypasses.

Avoid deserializing untrusted data with a native/binary format entirely. Prefer data formats like JSON with a strict, predefined schema over native serialization formats (Java ObjectInputStream, Python pickle, PHP unserialize, .NET BinaryFormatter) for anything that touches untrusted input.

Type allowlisting where native deserialization is unavoidable. If a native format must be used, restrict deserialization to an explicit allowlist of expected classes/types rather than allowing arbitrary polymorphic types to be instantiated.

Keep gadget-chain-relevant libraries patched. Known gadget chains rely on specific versions of common libraries; patching those libraries removes the chain even if deserialization itself can't be eliminated immediately.

Integrity-check serialized data before deserializing. A signed or MAC-protected serialized payload lets the application detect tampering before deserialization ever begins.

Run the deserializing process with minimum privilege. Least-privilege execution and sandboxing limit the blast radius if a gadget chain does execute.

Source reports

A sample of the disclosed HackerOne reports this playbook was synthesized from.

Frequently Asked Questions

What is Insecure Deserialization?
Reports cluster around language-specific deserialization-to-RCE: PHP Phar streams (concrete5 CVE-2021-36766), Ruby Marshal (RubyGems Bundler response), Java SnakeYAML (Kubernetes Java client), .NET Telerik UI BinaryFormatter (CVE-2019-18935), Python pickle in Django cache (CVE-2021-33026), Java JNDI in Log4Shell (CVE-2021-44228), and Java JMX exposing unauthenticated deserialization (Basecamp jabber server).
How common is Insecure Deserialization in bug bounty reports?
Scanrub's research corpus for this playbook is built from 47 disclosed HackerOne reports in this category, synthesized for detection and prevention guidance rather than reproduced verbatim.
How do I test for Insecure Deserialization?
Map every input vector, record a baseline response, then inject targeted test payloads one field at a time and compare the response for timing, length, error, or reflection differences from that baseline. The "How to Test" section above walks through the full methodology for this specific vulnerability class.
What is the single most effective fix for Insecure Deserialization?
Avoid deserializing untrusted data with a native/binary format entirely — prefer JSON with a strict schema, and if native deserialization is unavoidable, allowlist the specific types it may instantiate.
Weekly security research

New vulnerability playbooks, tool updates, and bug bounty insights - delivered to your inbox. No spam.

Unsubscribe anytime. We respect your inbox.
Press ⌘K to search×