{
    "slug": "php_object_injection",
    "term": "PHP Object Injection",
    "category": "security",
    "difficulty": "advanced",
    "short": "Passing attacker-controlled data to unserialize() triggers magic methods on existing classes, enabling code execution, file deletion, or SSRF.",
    "long": "PHP Object Injection is the practical exploit of insecure deserialization. When unserialize() processes attacker-controlled input, it instantiates arbitrary classes already loaded in the application's autoloader and calls __wakeup(), __destruct(), and __toString() as part of reconstruction. Attackers craft Property Oriented Programming (POP) chains — sequences of magic method calls across multiple classes that together achieve a malicious effect. Tools like PHPGGC (PHP Generic Gadget Chains) automate POP chain generation for popular frameworks. The fix: never unserialize untrusted data.",
    "aliases": [
        "PHP unserialize attack",
        "object injection",
        "PHP deserialization"
    ],
    "tags": [
        "php",
        "deserialization",
        "rce",
        "cwe-502"
    ],
    "misconception": "PHP object injection is only dangerous if the codebase has obvious gadget chains. Modern exploit tools automatically scan autoloaded classes for usable magic method chains — large applications with many dependencies almost always have exploitable gadgets.",
    "why_it_matters": "PHP's unserialize() invokes magic methods like __wakeup, __destruct, and __toString on attacker-crafted objects — existing classes in the application's autoloader can be chained into arbitrary code execution.",
    "common_mistakes": [
        "Passing user-controlled cookies, GET/POST parameters, or database values to unserialize().",
        "Believing that base64 encoding or encryption of serialized data prevents injection — if the key is compromised or the encoding bypassable, it doesn't help.",
        "Using serialize()/unserialize() for caching or session storage of user-controllable data.",
        "Not auditing installed packages for gadget chains — popular frameworks have known deserialization gadgets."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "insecure_deserialization",
        "serialize_function",
        "magic_methods"
    ],
    "prerequisites": [
        "insecure_deserialization",
        "deserialization_gadget_chains",
        "magic_methods"
    ],
    "refs": [
        "https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection",
        "https://github.com/ambionics/phpggc"
    ],
    "bad_code": "// Deserializing user-controlled data:\n$prefs = unserialize(base64_decode($_COOKIE['user_prefs']));\n// Attacker crafts a serialized object with __destruct that writes a webshell",
    "good_code": "// Never unserialize user input — use JSON instead:\n// Bad:\n// $obj = unserialize($_COOKIE['prefs']);\n\n// Safe: JSON for data exchange:\n$prefs = json_decode($_COOKIE['prefs'] ?? '{}', true);\nif (!is_array($prefs)) $prefs = [];\n\n// If unserialize is absolutely needed, use allowed_classes:\n$obj = unserialize($data, ['allowed_classes' => [SafeClass::class]]);\n// Only SafeClass can be instantiated — gadget chains blocked\n\n// Verify data integrity with HMAC before deserializing:\n$expected = hash_hmac('sha256', $data, SECRET_KEY);\nif (!hash_equals($expected, $signature)) {\n    throw new SecurityException('Data tampered');\n}\n$obj = unserialize($data, ['allowed_classes' => false]);",
    "quick_fix": "Replace unserialize() with json_decode() — JSON cannot carry PHP class information so no objects are reconstructed; if you must unserialize, use allowed_classes: [] strictly",
    "severity": "critical",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/php_object_injection",
        "html_url": "https://codeclaritylab.com/glossary/php_object_injection",
        "json_url": "https://codeclaritylab.com/glossary/php_object_injection.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[PHP Object Injection](https://codeclaritylab.com/glossary/php_object_injection) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/php_object_injection"
            }
        }
    }
}