Skip to content

Philippe Arteau - The New Wave of Deserialization Bugs

Philippe Arteau

Analysts investigate attack surfaces and defenses concerning Philippe Arteau - The New Wave of Deserialization Bugs.

Summary

### Overview Philippe Arteau, a security researcher at GoSecure and developer of Find Security Bugs, explores the pervasive vulnerability class of unsafe object deserialization. He explains how applications that accept serialized data from untrusted network sources introduce severe security risks, frequently enabling remote code execution (RCE). The talk demonstrates practical exploitation against legacy enterprise platforms like JBoss, discusses static analysis tooling for auditing binary dependencies, examines similar flaws across other languages (PHP and Python), and evaluates potential remediation strategies.

### Key Topics - **Core Mechanics of Serialization and Deserialization**: How objects in memory are converted into byte streams (or formats like JSON, XML, Protocol Buffers, and native Java binary streams) for persistence, caching, inter-process communication, or network transport. - **The Root Design Flaw**: Native deserialization mechanisms that invoke custom behaviors during reconstruction (such as Java's `readObject`) effectively expose new untrusted entry points, allowing attackers to initialize arbitrary classes and states available on the classpath. - **Gadget Chains and Exploitation**: Constructing execution paths using existing classes (gadgets)—such as Apache Commons Collections combined with dynamic proxies and invocation handlers—to achieve remote code execution. - **Static Analysis & Tooling**: Leveraging `ysoserial` for payload generation and using `Find Security Bugs` to locate vulnerable deserialization endpoints and identify potential gadget classes in compiled binaries without requiring source code. - **Cross-Language Equivalents**: Analyzing comparable behaviors in PHP (`unserialize` triggering magic methods like `__destruct`) and Python (`pickle` via custom `__reduce__` methods).

### Technical Details Exploiting deserialization requires two fundamental components: an endpoint performing deserialization on untrusted input, and serializable "gadget" classes present on the application's classpath.

In Java, when `readObject()` is called on an incoming serialized stream, the runtime identifies the class name, loads and instantiates the class (without calling standard constructors), populates its fields, and executes its custom `readObject()` method before any explicit type casting occurs. Even if the application expects a specific object type and subsequently throws a `ClassCastException`, the malicious code inside `readObject()` has already executed.

Arteau demonstrates an attack against an old version of JBoss containing the HTTP endpoint `/invoker/JMXInvokerServlet`. Using the tool `ysoserial`, an attacker generates a serialized payload using the `CommonsCollections1` gadget chain to execute arbitrary OS commands (such as launching a calculator or establishing a reverse shell). The payload is saved to a file (`nsec.bin`) and sent to the endpoint via Burp Suite Repeater, reliably achieving remote code execution. He explains how classes without explicit `readObject` implementations (e.g., Apache Commons Collections transformers) can still be triggered using serializable Java Dynamic Proxies and `InvocationHandler` implementations.

To audit applications, Arteau shows how `Find Security Bugs` can inspect large deployments (scanning over 2,000 MB of JBoss JAR files) to highlight endpoints (like remoting and REST packages) and search for risky serializable classes or invocation handlers. Beyond Java, he discusses PHP's `unserialize()`, illustrating a CTF example where modifying object properties in an unsanitized SQL database wrapper triggered SQL injection inside `__destruct()`. In Python, the `pickle` module's `__reduce__` method allows arbitrary callable functions and arguments to be directly bundled into the serialized stream.

### Takeaways - **Avoid Native Serialization in Remote Interfaces**: Native deserialization should not be exposed to untrusted inputs. Modern applications should instead use static, data-only formats such as JSON or Protocol Buffers, which do not permit arbitrary class instantiation or automatic behavior execution. - **Blacklisting is Incomplete**: Defensive measures such as blacklisting known gadgets (or using tools like `NotSoSerial`) only offer temporary mitigation and turn into a "whack-a-mole" game as new gadget chains are uncovered. - **Comprehensive Auditing**: Organizations maintaining proprietary or legacy Java applications should use static binary analysis to identify exposed deserialization entry points and remove vulnerable or unused gadget libraries from their classpath.

Related talks