====== 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:9'' -> ''s:5'') when changing values. **Magic methods:** PHP auto-invokes certain methods during object lifecycle: * ''__wakeup()'' -- called when an object is deserialized (via ''unserialize()'') * ''__destruct()'' -- called when no references to the object remain * ''__toString()'' -- called when the object is treated as a string * ''__call()'' -- called when an undefined method is invoked 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:** class Example2 { private $hook; function __wakeup() { if (isset($this->hook)) eval($this->hook); } } $user_data = unserialize($_COOKIE['data']); 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: class Example2 { private $hook = "phpinfo();"; } print urlencode(serialize(new Example2)); ===== 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: java -jar ysoserial.jar CommonsCollections1 'id' 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.