Critical Severity | OWASP A08:2021
π PHP Object Injection (Insecure Deserialization)
π§ Description
What is the vulnerability?
PHP Object Injection occurs when userβsupplied input is passed to unserialize() without proper validation. An attacker can supply a crafted serialized string that, when unserialized, instantiates arbitrary PHP objects and may trigger magic methods (e.g., __wakeup(), __destruct()) leading to Remote Code Execution (RCE), file deletion, or privilege escalation.
Why does it occur?
Developers use unserialize() on data from cookies, session storage, or API inputs, trusting it without sanitisation.
Security principle violated: Insecure Deserialization
Real-world analogy: Accepting a preβpackaged box from a stranger and opening it β you have no control over what's inside.
π·οΈ Classification
- Type: Insecure Deserialization
- OWASP: A08:2021 β Software and Data Integrity Failures
- CWE: CWE-502: Deserialization of Untrusted Data
π― Attack Surface
- β PHP sessions (serialized data in cookies or files)
- β
API endpoints accepting serialized objects (e.g.,
application/x-php-serialized) - β
Parameters passed to
unserialize()from user input - β
Applications using
__wakeup()or__destruct()for file operations
π Detection Methodology
- Look for parameters that look like serialized PHP data:
O:4:"User":1:{s:4:"name";s:3:"abc";} - Use static analysis to find
unserialize($_GET[...])orunserialize($_COOKIE[...]) - Fuzz with a harmless serialized object and observe behaviour changes.
π£ Basic Payloads
# Simple serialized string for a class with a destructor
O:1:"A":0:{}π Advanced Exploitation (POP Chain)
# Example payload using a known gadget chain (PHPGGC) phpggc Monolog/RCE1 system 'id' -s # Then send the generated payload to the vulnerable unserialize() endpoint.
π§ͺ Test Cases (STRICT)
| Step | Action | Expected | Actual |
|---|---|---|---|
| 1 | Submit a malformed serialized string (e.g., O:1:"A":0:{}) | Error or no effect | Application crash or unexpected behaviour |
| 2 | Use PHPGGC to generate a payload for RCE | No output or blocked | Command executed (e.g., id output) |
βοΈ Exploitation Steps
- Identify input that is passed to
unserialize(). - Enumerate classes and available magic methods (use code review or PHPGGC).
- Craft a gadget chain to achieve RCE.
- Deliver the payload and execute commands.
π‘οΈ Mitigation
β
Never use
β Use safe alternatives like
β Implement allowlist of classes when deserializing (e.g.,
β Use signature verification (HMAC) for serialized data.
β Keep dependencies updated to avoid known gadget chains.
unserialize() on user input.β Use safe alternatives like
json_decode().β Implement allowlist of classes when deserializing (e.g.,
unserialize($data, ['allowed_classes' => ['MyClass']])).β Use signature verification (HMAC) for serialized data.
β Keep dependencies updated to avoid known gadget chains.
π Mitigation Bypass
- If allowlist is too broad, attackers may still find usable classes.
- If custom autoloaders are misconfigured, new classes can be injected.
β οΈ Risk / Impact
Severity: Critical
Impact: Remote Code Execution, complete server takeover, data breach.
Impact: Remote Code Execution, complete server takeover, data breach.
π Proof of Concept (PoC)
# Vulnerable code
$data = $_GET['data'];
$obj = unserialize($data);
# Payload
?data=O:8:"stdClass":0:{}