Serialization converts in-memory objects into a storable/transmittable format; deserialization reverses this. Vulnerabilities arise when untrusted data is deserialized, potentially triggering dangerous operations via magic methods (e.g., PHP's wakeup, Java's readObject). Attackers chain existing classes (gadget chains) to achieve remote code execution, file access, or denial of service. Key languages include Java (Commons Collections), PHP (POP chains), Python (pickle), .NET (BinaryFormatter), and Node.js. Defenses include never deserializing untrusted data, using integrity checks, class whitelisting, updating dependencies, and isolation. PHP serialization structure includes object declarations and properties with visibility markers. Magic methods like wakeup and __destruct are entry points. Advanced exploits use POP chains and bypasses like CVE-2016-7124. Specific cases include Jboss (CVE-2017-12149, CVE-2017-7504), Weblogic (CVE-2018-2628), and Apache Shiro (Shiro-550, due to hardcoded AES key). Prevention involves secure configuration, middleware updates, and strict input validation.
1. What Are Serialization and Deserialization?
Serialization: Converting an in-memory object into a storable or transmittable format (byte stream, JSON, XML, etc.).
Deserialization: Restoring data in such a format back into a program object.
The vulnerability lies in the "deserializing untrusted data" step. While the program is still reconstructing the object, certain dangerous operations may be triggered automatically — attackers exploit this to craft malicious data.
1.1 Introduction to Deserialization
It's about turning an object into transmittable characters, purely for the sake of easier transport.
Suppose we write a class that holds some variables. After the class is instantiated, the values of those variables change during use. Later on, we may need those variable values again. If we keep the class alive indefinitely just to reuse it later, that wastes system resources. In a small project this might not matter much, but as the project grows, small problems become magnified and cause significant trouble. This is where PHP provides a solution: you can serialize the object, store it as a string, and restore it when needed. That is what serializing an object for storage is all about.
In PHP deserialization, the discussion centers on two functions: serialize() and unserialize().
2. How Deserialization Vulnerabilities Arise
serialize() and unserialize() themselves have no vulnerabilities in PHP's internal implementation. Deserialization vulnerabilities arise from how the application handles objects, magic methods, and serialization-related issues.
When the parameter passed to unserialize() is controllable, a user can inject a carefully crafted payload. During deserialization, certain magic methods within the object may be triggered, leading to unexpected consequences.
3. Typical Scenarios Across Different Languages
Many languages automatically invoke certain lifecycle methods on objects during deserialization.
Examples:
Java: readObject(), finalize();
PHP: __wakeup(), __destruct(), __toString()
Python: __reduce__(), __setstate__()
Attackers cannot execute arbitrary code directly, but they can leverage existing classes within the application or third-party libraries, piecing together a call chain (Gadget Chain) by chaining them together, ultimately achieving arbitrary command execution. Since the data is fully controlled by the attacker, even class names and field values can be tampered with.
JavaJava: Most common. It exploits ObjectInputStream to deserialize malicious serialized objects, combined with components like Commons Collections and Fastjson to complete the attack.
PHPPHP: When unserialize() processes user input, magic methods are exploited to construct POP chains.
PythonPython: The pickle module's loads() explicitly warns against deserializing untrusted data, because its virtual machine can be directly injected with system commands.
.NET.NET: BinaryFormatter and SoapFormatter have been officially marked as dangerous and should not be used on untrusted data.
Node.jsNode.js: Third-party packages like node-serialize, if used to directly deserialize user-supplied data, can also lead to code injection.
4. Impact
Remote Code Execution: Gain server access.: Gain server access
File Read/Write: Steal configurations, source code, or write a WebShell.: Steal configurations, source code, or write a WebShell
Denial of Service: Construct "deserialization bombs" through nested arrays, circular references, etc., exhausting CPU and memory.: Construct "deserialization bombs" through nested arrays, circular references, etc., exhausting CPU and memory
5. How to Defend
Never deserialize untrusted data (the most fundamental approach). Prefer pure data formats like JSON, and only use the library's pure data mapping mode. (the most fundamental approach). Prefer pure data formats like JSON, and only use the library's pure data mapping mode.
When deserialization is unavoidable, perform integrity checks: digitally sign or encrypt the serialized data to ensure it has not been tampered with.integrity checks: digitally sign or encrypt the serialized data to ensure it has not been tampered with.
Class whitelisting: strictly limit which classes are allowed for deserialization (e.g., Java's ObjectInputFilter, PHP 7.3+'s allowed_classes option).
Update dependencies: promptly upgrade base libraries and frameworks to avoid using older versions known to contain Gadgets.
Isolation: perform deserialization operations inside a sandbox or a low-privilege process.
In summary: never trust serialized objects from the client. If your business must use them, always add signature verification and whitelist checks.
6. PHP Deserialization
6.1 Structure
To understand attacks, you first need to be able to read serialized strings. When you serialize a Person class instance, you get a structure like the one below.
PHP
class Person {
public $name = "张三";
private $age = 20;
producted $sex = "boy"
}
TEXT
O:6:"Person":3:{s:4:"name";s:6:"张三";s:11:" Person age";i:20;s:6:" * sex";s:3:"boy";}
Object declaration: O:6:"Person":3 means an object (O), class name length 6, class name Person, with 3 properties.
O: This is an Object.
6: The class name "Person" is 6 bytes long (P-e-r-s-o-n).
"Person": The object.
3: This object has 3 properties.
First property (public): s:4:"name";s:6:"张三";
s:4:"name": data type is string, length 4, content is "name".
s:6:"张三": data type is string, length 6, content is "张三".
This is because "张三" takes up 6 bytes in UTF-8 encoding (each Chinese character occupies 3 bytes). If it were written as s:2, it would cause a parsing error.
Second property (private): s:11:" Person age";i:20
This is the most critical part of the entire string.
On the surface it looks like: " Person age" (a leading space and a space in the middle). But the length is 11 — let's count the hidden characters:
Actual storage: \x00+Person+\x00+age
Break it down: \x00 (1 byte) + Person (6 bytes) + \x00 (1 byte) + age (3 bytes)
In text display, \x00 (null byte, invisible) is commonly shown as a space,a space,which is why it is written as " Person age".
i:20: the value is the integer 20.
Third property (protected): s:6:" * sex";s:3:"boy";
On the surface it looks like " * sex", and the length seems to be only 4 —
but the actual length is 6:
Actual storage: \x00 (1 byte) + * (1 byte) + \x00 (1 byte) + sex (3 bytes)
If the property name contains an asterisk, it is a protected property.
6.2 Dangerous Magic Methods
During the execution of unserialize(), if certain methods are defined in the class, PHP will invoke them automatically — these become the "entry points" for attacks:
Called first and automatically during deserialization,first and automatically during deserialization,often used for object resource initialization.
Automatically called when the object is destroyedwhen the object is destroyed(e.g., at script shutdown), often used for "cleanup" work.
Triggered when the object is used as a stringobject is used as a string(e.g., echo $obj).
Triggered when calling a non-existent or inaccessible methodnon-existent or inaccessible methodon an object.
Triggered when reading/assigning a non-existent or inaccessible propertynon-existent or inaccessible propertyon an object.
6.3 Exploitation Techniques and POP Chain Construction
6.3.1 Basic Exploitation
Directly exploit dangerous magic methods. For example, control the file deletion path inside __destruct() to achieve arbitrary file deletion.
6.3.2 Advanced Exploitation (POP Chains)
Use a magic method as the starting point to call methods of other classes, linking them together like a chain, link by link, ultimately executing high-risk operations.
When the serialized string's property count value exceeds the actual number of properties,property count value exceeds the actual number of properties,the execution of __wakeup() can be bypassed.
Phar Deserialization: exploits the phar:// pseudo-protocol to trigger metadata deserialization within file operation functions like file_exists(), representing an "unserialize()-less" exploitation technique.
6.4 JBoss Deserialization
How to detect: Download the detection tool and run: java -jar DeserializeExploit.jar
Principle: The root cause is that the ObjectInputStream class does not restrict the types of objects being generated during deserialization.
Exploitation: Download an exploit tool to get a reverse shell — available on GitHub.
6.4.3 JBoss Remote Deployment Vulnerability
Principle: The backend does not apply strict filtering to user-controllable parameters.
Impact: Leads to arbitrary command execution; an intruder can exploit this vulnerability to directly obtain a WebShell.
6.5 WebLogic Deserialization
Versions: 10.3.6.0, 12.1.3.0, 12.2.1.2, 12.2.1.3
CVE-2018-2628
Principle: This vulnerability originates in WebLogic's T3 service. When the WebLogic console port (default 7001) is open, the T3 service is enabled by default. Attackers can use the T3 protocol to send malicious serialized data.
Non-deserialization vulnerability — Weak passwords: For weak password vulnerabilities, you can search online for the middleware's default credentials. For example, the WebLogic weak password: both username and password are "weblogic".
Java deserialization vulnerability exploitation (CVE-2018-2628). Arbitrary file upload vulnerability exploitation (CVE-2018-2894). XML Decoder deserialization vulnerability exploitation (CVE-2017-10271). SSRF vulnerability (requires the UDDI component to be selected when installing WebLogic). Deserialization vulnerability (CVE-2019-2725). Unauthorized access.
Attack signature: The Set-Cookie header in the response contains the field rememberMe=deleteMe.
Vulnerability impact: All Apache Shiro versions <= 1.2.4 are affected.
Vulnerability principle:
The vulnerability exploits the rememberMe parameter in the cookie. This parameter's value is AES-encrypted and then Base64-encoded before being set in the cookie. On the server side, the rememberMe cookie value should be Base64-decoded first, then AES-decrypted, and then deserialized.
The key issue is that the AES encryption key is hard-coded in the source code. AES is symmetric encryption, so the encryption key is also the decryption key. Once an attacker obtains the AES encryption key, they can construct a malicious object, serialize it, AES-encrypt it, and Base64-encode it. They then send it as the rememberMe cookie field. Shiro decrypts and deserializes it, ultimately resulting in a deserialization vulnerability.
Mitigation measures:
Upgrade.
Change the hard-coded key in the source file.
Temporary mitigation suggestions:
Attempt to intercept brute-force traffic on security devices to promptly block attack attempts.
Upgrade the JDK version to 8u191/7u201/6u211/11.0.1 or above.
Use WAF to intercept overly long rememberMe values in cookies.
Use WAF to block IPs with excessively frequent access, as this vulnerability requires cookie brute-forcing.
6.7 Security Hardening
Configure PHP security parameters properly: in the php.ini configuration file, there is a disable_functions = directive that disables certain PHP functions. The server uses this to disable PHP command execution functions.
Upgrade middleware.
Strictly control incoming variables and use magic methods with caution.
1. What Are Serialization and Deserialization?
The vulnerability lies in the "deserializing untrusted data" step. While the program is still reconstructing the object, certain dangerous operations may be triggered automatically — attackers exploit this to craft malicious data.
1.1 Introduction to Deserialization
2. How Deserialization Vulnerabilities Arise
serialize() and unserialize() themselves have no vulnerabilities in PHP's internal implementation. Deserialization vulnerabilities arise from how the application handles objects, magic methods, and serialization-related issues.
3. Typical Scenarios Across Different Languages
Many languages automatically invoke certain lifecycle methods on objects during deserialization.
Examples:
Attackers cannot execute arbitrary code directly, but they can leverage existing classes within the application or third-party libraries, piecing together a call chain (Gadget Chain) by chaining them together, ultimately achieving arbitrary command execution. Since the data is fully controlled by the attacker, even class names and field values can be tampered with.
4. Impact
5. How to Defend
In summary: never trust serialized objects from the client. If your business must use them, always add signature verification and whitelist checks.
6. PHP Deserialization
6.1 Structure
To understand attacks, you first need to be able to read serialized strings. When you serialize a Person class instance, you get a structure like the one below.
6.2 Dangerous Magic Methods
During the execution of unserialize(), if certain methods are defined in the class, PHP will invoke them automatically — these become the "entry points" for attacks:
6.3 Exploitation Techniques and POP Chain Construction
6.3.1 Basic Exploitation
Directly exploit dangerous magic methods. For example, control the file deletion path inside __destruct() to achieve arbitrary file deletion.
6.3.2 Advanced Exploitation (POP Chains)
Use a magic method as the starting point to call methods of other classes, linking them together like a chain, link by link, ultimately executing high-risk operations.
6.3.3 Automated Tools
6.3.4 Special Bypasses
6.4 JBoss Deserialization
6.4.1 JBoss 5.x/6.x Deserialization Vulnerability (CVE-2017-12149)
Principle: The ReadOnlyAccessFilter in JBoss's HttpInvoker component deserializes the client data stream without performing any security checks.
Access URLs:
A 500 response indicates the vulnerability is present.
Exploitation: Download an exploit tool to get a reverse shell — available on GitHub.
6.4.2 JBoss 4.x JBossMQ JMS Deserialization Vulnerability (CVE-2017-7504)
Principle: The root cause is that the ObjectInputStream class does not restrict the types of objects being generated during deserialization.
Exploitation: Download an exploit tool to get a reverse shell — available on GitHub.
6.4.3 JBoss Remote Deployment Vulnerability
Principle: The backend does not apply strict filtering to user-controllable parameters.
Impact: Leads to arbitrary command execution; an intruder can exploit this vulnerability to directly obtain a WebShell.
6.5 WebLogic Deserialization
Versions: 10.3.6.0, 12.1.3.0, 12.2.1.2, 12.2.1.3
CVE-2018-2628
Non-deserialization vulnerability — Weak passwords: For weak password vulnerabilities, you can search online for the middleware's default credentials. For example, the WebLogic weak password: both username and password are "weblogic".
Java deserialization vulnerability exploitation (CVE-2018-2628). Arbitrary file upload vulnerability exploitation (CVE-2018-2894). XML Decoder deserialization vulnerability exploitation (CVE-2017-10271). SSRF vulnerability (requires the UDDI component to be selected when installing WebLogic). Deserialization vulnerability (CVE-2019-2725). Unauthorized access.
6.6 Apache Deserialization
6.6.1 Shiro-550 Java Deserialization Vulnerability
Attack signature: The Set-Cookie header in the response contains the field rememberMe=deleteMe.
Vulnerability impact: All Apache Shiro versions <= 1.2.4 are affected.
Vulnerability principle:
Mitigation measures:
6.7 Security Hardening