Table of Contents

BBC Ch 14: Insecure Deserialization

Source: Bug Bounty Bootcamp by Vickie Li

Mechanisms

Serialization converts a program object into a format (byte stream or string) suitable for storage or network transfer. Deserialization reconstructs the object. Many languages support this: Java, PHP, Python, Ruby.

Developers often trust serialized data because it looks opaque or unreadable. Insecure deserialization occurs when user-supplied serialized data is deserialized without verification, letting attackers manipulate object properties or trigger dangerous magic methods.

PHP Object Injection

PHP serialize format example:

O:4:"User":2:{s:8:"username";s:6:"vickie";s:6:"status";s:9:"not admin";}

Format: O:CLASS_NAME_LENGTH:“CLASS_NAME”:PROPERTY_COUNT:{PROPERTIES}

Manipulating variables: if a serialized object is used for authentication and isn't signed or encrypted, modify the status field:

O:4:"User":2:{s:8:"username";s:6:"vickie";s:6:"status";s:5:"admin";}

Note: update the string length marker (s:9s:5) when changing values.

Magic methods: PHP auto-invokes certain methods during object lifecycle:

If a magic method passes object properties into dangerous functions like eval(), an attacker can achieve RCE by controlling those properties in the serialized payload.

Classic PHP RCE via wakeup: <code php> class Example2 { private $hook; function wakeup() { if (isset($this→hook)) eval($this→hook); } } $user_data = unserialize($_COOKIE['data']); </code> Set $hook = “phpinfo();” in a crafted serialized object, URL-encode it, and pass it as the data cookie. The server calls eval(“phpinfo();”) on deserialization. Generate the payload: <code php> class Example2 { private $hook = “phpinfo();”; } print urlencode(serialize(new Example2)); </code> ===== POP Chains ===== When magic methods don't directly contain exploitable code, chain method calls across multiple classes (property-oriented programming). Each “gadget” is a code snippet from the existing codebase. Magic methods serve as the entry point; they call methods on other classes that eventually reach dangerous code like eval() or exec(). Example flow: __wakeup() calls $obj→evaluate()CodeSnippet::evaluate() calls eval($this→code) → attacker controls $code. ===== Java Deserialization ===== Java serialized objects implement java.io.Serializable. Signatures that identify them: * Hex: AC ED 00 05 at the start * Base64: starts with rO0 * Content-Type header: application/x-java-serialized-object Java deserialization exploits use gadget chains from libraries (Apache Commons-Collections, Spring Framework, Apache Groovy, Apache Commons FileUpload) to reach code execution. Ysoserial automates gadget chain generation: <code> java -jar ysoserial.jar CommonsCollections1 'id' </code> Feed the output as a serialized object in the vulnerable parameter. ===== Prevention ===== * Never deserialize data tainted by user input without verification * Use an allowlist to restrict which classes can be deserialized * Prefer simple data types (strings, arrays) over serialized objects for transport * Keep session state server-side instead of in serialized cookies * Keep dependencies patched; many deserialization vulns come from third-party libraries ===== Hunting for Insecure Deserialization ===== With source code: search for dangerous deserialization functions: * PHP: unserialize() * Java: readObject() * Python: pickle.loads() * Ruby: Marshal.load() Confirm that user-supplied data flows into these calls. Without source code: * Find large blobs of data in HTTP requests (cookies, POST body, headers) – these may be serialized objects * Decode them: base64 blocks starting with Tzo or rO0 are likely PHP or Java objects * Look for Content-Type: application/x-java-serialized-object * Tamper with the object: change usernames, status flags, or role names; re-serialize and replay * Try to achieve RCE using known gadget chains for the detected language ===== 6-Step Checklist ===== - Find entry points where user-supplied data is deserialized (cookies, POST params, headers). - Identify the serialization format (PHP, Java, Python, Ruby) from signatures or Content-Type. - Tamper with variable values in the serialized object (status, role, username) and check for privilege changes. - If variable tampering achieves authentication bypass, document and report. - See if magic methods or POP chains can escalate to RCE (use Ysoserial for Java). - Draft report; be careful not to cause damage when testing RCE payloads.