Skip to main content

Modern Deserialization Attacks (Java/.NET/PHP) and Gadget Hunting

 

Modern Deserialization Attacks in 2025: How Gadget Chains Still Break Java, .NET, and PHP Apps

When you think about the “scariest” web vulnerabilities, you probably imagine RCE, SSRF, or some fancy cloud takeover. But there’s one bug category that quietly sits underneath all of this—one that has caused some of the biggest breaches in the past decade—insecure deserialization.

And guess what?
Even in 2025, it’s still popping up everywhere, especially in large enterprise stacks running Java, .NET, and PHP.

This article breaks down modern deserialization attacks in a human, practical, bug-bounty-friendly way. No academic fluff. Just how the attacks actually work, how researchers build gadget chains, and how you can detect and prevent them in real systems.


1. What Exactly Is Deserialization? (The Two-Line Explanation)

Applications often need to save complex objects—user profiles, session data, tokens, carts, preferences—into a transportable format. So they serialize them (convert to bytes/json/xml). Later, they deserialize them to rebuild the object in memory.

This is normal.

The danger comes when the app trusts untrusted data and passes it straight into the deserializer.

If an attacker can control that input, they can create objects that trigger dangerous code paths—sometimes even full remote code execution (RCE).


2. Why Is Deserialization Still a Problem in 2025?

Because enterprise codebases:

  • run old libraries,

  • depend on massive frameworks with hidden object classes,

  • allow user-controlled XML/JSON/Binary input,

  • use outdated “blacklisted class” filters,

  • and often assume “serialization is safe because we handle internal data.”

But “internal only” quickly becomes “external input” when:

  • a proxy flows data from user → microservice → legacy backend,

  • session objects get stored client-side,

  • API gateways simply forward serialized payloads,

  • developers expose “debug endpoints” or message brokers.

Attackers love complexity, and deserialization is complexity on steroids.


3. The Secret Weapon: Gadget Chains

A gadget is simply:

A method in an existing class that performs a sensitive action when an object is deserialized.

When you chain multiple classes together—each triggering another—you build a gadget chain.

Think of a gadget chain like a domino line:

  1. You send a serialized object.

  2. During deserialization, it's readObject() method runs.

  3. That method triggers another class’s method.

  4. That method triggers something dangerous.

  5. At the end of the chain:
    RCE, file writes, SSRF, or logic abuse.

Modern attacks no longer require injecting “evil classes.” Instead, the attacker uses classes already present in the server’s classpath.

That’s why even up-to-date servers can be vulnerable.


4. Real Examples From Java, .NET, and PHP

4.1 Java: The King of Deserialization Bugs

Java deserialization has been abused for years because:

  • Java apps use many libraries (Spring, Struts, Jackson, Commons-Collections, Groovy, XStream, etc.).

  • Each library provides thousands of classes.

  • Many of these classes have “magic” methods:
    readObject(), readResolve(), finalize(), toString()

The most famous chain is:

commons-collections → InvokerTransformer → Runtime.exec()

Even though some vendors patched it, variations still exist in:

  • Commons-Beanutils

  • Spring-core

  • Groovy

  • XStream

  • JBoss

  • WebSphere/ColdFusion style servers

In real-world bug bounty cases, you’ll often find:

  • JSON parsers accepting polymorphic types (@class)

  • XML parsers allowing external entity loading

  • Message brokers deserializing Java objects from queues

  • API gateways forwarding serialized binaries

4.2 .NET: Dangerous Auto-Binding & BinaryFormatter

By 2025, Microsoft will officially discourage using:

  • BinaryFormatter

  • NetDataContractSerializer

  • LosFormatter

But enterprise apps still use them, especially legacy ASP.NET systems.

Popular exploit features include:

  • ObjectDataProvider (WPF)

  • Process.Start() triggers

  • TypeConfuseDelegate gadget chains

Even new .NET 6/7 apps sometimes use insecure patterns when migrating old code.

4.3 PHP: The Magic of __wakeup() and unserialize()

PHP deserialization is simpler but just as dangerous.

When you call:

unserialize($_POST['data']);

You’re basically telling PHP:
“Instantiate any class you want and run its magic methods.”

PHP gadgets use:

  • __wakeup()

  • __destruct()

  • __call()

Laravel, Symfony, SwiftMailer, and WordPress plugins have all had real-world gadget chains that allowed:

  • file deletion

  • SSRF

  • log poisoning → RCE

  • arbitrary file write via PHAR deserialization


5. How Hackers Actually Build Gadget Chains (Step-by-Step)

Let’s make this extremely clear and human:

Step 1: Identify an Untrusted Deserialization Sink

Examples:

  • /api/parseBinary

  • /debug/restoreSession

  • /import/settings

  • AMQP/Kafka message consumers

  • unserialize() in PHP logs/metadata

You detect these using:

  • Burp Suite passive scanning

  • source code search (“BinaryFormatter”, “readObject”, “unserialize”)

  • fuzzing with invalid serialized blobs


Step 2: Enumerate Libraries in Classpath or File System

You look for common libraries:

  • Commons-Collections

  • Groovy

  • Spring

  • XStream

  • Fastjson

  • Jackson

In PHP:

  • Laravel

  • Symfony

  • PHPUnit

  • WordPress plugins

Often, you can fingerprint them by error messages.


Step 3: Use Existing Gadget Chains

There are public exploit chains:

  • ysoserial (Java)

  • ysoserial.net (.NET)

  • phpggc (PHP)

Example for Java:

java -jar ysoserial.jar CommonsCollections5 'touch /tmp/pwned' | base64

You embed this payload into a request—if the app is vulnerable, the command runs.


Step 4: Build Custom Chains When Public Ones Fail

Modern apps patch known gadgets.
So researchers hunt for new gadgets, usually by:

  • scanning for classes with “magic” methods,

  • identifying methods that execute commands, write files, open URLs, or load templates,

  • chaining them based on the constructor → method → destructor flows.

Automation tools like GadgetInspector help map potential chains.


6. Detection: How To Know If the App Is Vulnerable

1. Look for Deserialization Exceptions

Send a corrupted payload (random bytes).
If the server throws:

  • StreamCorruptedException

  • InvalidClassException

  • SerializationException

…it’s likely deserializing something.

2. Look for Polymorphic Type Hints in JSON

If JSON uses something like:

{ "@class": "com.app.User" }

You’re dealing with a dangerous parser (Jackson/Fastjson style).

3. Identify Magic Methods in Code

Search /src for:

  • readObject

  • readResolve

  • finalize

  • __wakeup()

  • __destruct()

4. Use safe probing payloads

Each ecosystem has “benign gadget chains” that don’t execute commands but prove invocation (e.g., DNS ping).


7. Mitigation: What Actually Works

Here’s the frustrating truth:

Blacklists do not work.
Developers tried blocking “CommonsCollections,” but attackers simply used Spring/Groovy/BeanUtils instead.

Real mitigations that work:

1. Completely avoid unsafe serializers

  • Java → avoid native Java serialization. Use JSON-B, Jackson (with type restrictions), Kryo (safely configured).

  • .NET → avoid BinaryFormatter entirely.

  • PHP → never use unserialize() on user input.

2. Enforce strict allow-lists

Only deserialize specific, known, final classes.

3. Disable polymorphic typing

Especially in Jackson / Fastjson:

objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); objectMapper.activateDefaultTyping(…)

Disable the second line unless you absolutely need it.

4. Sign/Encrypt serialized data

If you must serialize to the client, ensure:

  • Signing keys rotate

  • Integrity checks exist

  • The client cannot modify objects undetected

5. Add WAF rules and IDS signatures

Detect serialized binary formats:

  • Java serialization magic bytes

  • .NET binary headers

  • PHP serialized object markers like O:


8. Final Thoughts

Deserialization bugs are terrifying because the attack surface is hidden—buried deep inside the object graph, libraries, and frameworks that most developers never read.

For attackers, it’s a goldmine:
One gadget chain = full system compromise.

For defenders, the strategy is simple:
Don’t deserialize untrusted data. Ever.

If you’re a bug bounty hunter, learning gadget chains gives you a massive advantage—most researchers skip these because they look “too enterprise,” but that’s where the payouts usually are.

Comments

Popular posts from this blog

Practical XSS: DOM vs Reflected vs Stored — Advanced Payloads & Bypasses

Practical XSS: DOM vs Reflected vs Stored in 2025 (Payloads & Bypasses) If you hunt bugs, run red teams, or build web apps, XSS still matters in 2025. It is one of the easiest ways to jump from “weird UI bug” to full account takeover, even on big platforms. Cross-site scripting (XSS) is when an attacker runs their own JavaScript in someone else’s browser using a vulnerable site. The three main flavors are simple to say, hard to defend: reflected XSS (comes back in a single response), stored XSS (saved on the server), and DOM-based XSS (triggered by client-side code). This guide focuses on real payloads and modern bypass tricks, not just alert(1) . You will see how attackers build and adapt payloads for each type, and how filters, CSP, and WAFs can fail in practice. It is written for people who already get basic HTTP and HTML and want to level up their XSS game. Quick XSS refresher: DOM vs reflected vs stored in simple terms Photo by Markus Winkler In 2025, XSS is still one of the...

API Authorization Flaws (Broken Object Level & Function Level Auth)

  API Authorization Flaws: BOLA and BFLA Explained for Real-World Security APIs are the hidden pipes that keep modern apps running. Your banking app, ride sharing app, and social media feed all depend on APIs to send and receive data behind the scenes. When those APIs make simple mistakes in authorization , private data leaks. You do not always need complex malware. Often, attackers just change an ID or call a hidden function. Two of the worst mistakes are Broken Object Level Authorization (BOLA) and Broken Function Level Authorization (BFLA). Both BOLA and BFLA appear in the OWASP API Security Top 10 that teams still follow as of 2025, based on the latest 2023 list, where BOLA is ranked number 1 and BFLA is number 5. This post breaks down what these flaws are, how attackers abuse them, and clear steps your team can take to prevent them. What Are API Authorization Flaws and Why Do They Matter? Photo by Markus Winkler To understand API authorization flaws, start with two si...

Chain Exploits: From Information Leak to RCE in 2025

 Chain Exploits: From Information Leak to RCE in 2025 A lot of people picture hacking as one big magic trick. In reality, most modern attacks are a chain of small, boring bugs that line up in a very bad way. Two of the most dangerous links in that chain are an information leak and remote code execution (RCE). An information leak is any bug that reveals data that should stay private. RCE is a bug that lets an attacker run their own code on your server or node from far away. On their own, each bug might look minor. Together, they can give an attacker full control of your web app, CI pipeline, or blockchain stack. In 2025, with DeFi protocols, Web3 dashboards, and npm-heavy codebases everywhere, this pattern is more common than people think. This post walks step by step from a tiny leak to full system control, using simple language and real style examples from npm supply chain attacks and DeFi exploits. What Is a Chain Exploit and Why Does It Matter for Security in 2025? A chain explo...