🧠 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[...]) or unserialize($_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)

StepActionExpectedActual
1Submit a malformed serialized string (e.g., O:1:"A":0:{})Error or no effectApplication crash or unexpected behaviour
2Use PHPGGC to generate a payload for RCENo output or blockedCommand executed (e.g., id output)

βš™οΈ Exploitation Steps

  1. Identify input that is passed to unserialize().
  2. Enumerate classes and available magic methods (use code review or PHPGGC).
  3. Craft a gadget chain to achieve RCE.
  4. Deliver the payload and execute commands.

πŸ›‘οΈ Mitigation

βœ… Never use 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.

πŸ“Ž Proof of Concept (PoC)

# Vulnerable code
$data = $_GET['data'];
$obj = unserialize($data);

# Payload
?data=O:8:"stdClass":0:{}
Back to Web Security