Look for request data flowing into unserialize, magic methods such as __wakeup or __destruct, and code paths that manipulate filesystem or command execution primitives during object lifecycle events. A strong indicator is when user input is decoded and then passed into a sink without strict validation or class restrictions. Those patterns often reveal an exploitable gadget chain.
How PHP Object Injection Shows Up in a Custom Module or Theme
The most useful clue is not a single function name, it is the data flow. A custom module or theme becomes suspicious when untrusted request data can reach PHP deserialization, then continue into code that does something meaningful during object construction, wakeup, or destruction. In practice, that means tracing user-controlled input from the request boundary to the sink and then checking whether any class in scope exposes a gadget-like side effect.
Review the module or theme for places where serialized strings are accepted from forms, cookies, query parameters, AJAX endpoints, cache entries, or database fields that are themselves populated from request data. A warning sign is code that decodes, transforms, or partially validates the input and then still calls unserialize() or an equivalent object reconstruction path. If the code also permits broad class loading, autoloading, or loose object handling, the attack surface becomes much easier to exploit.
Pay close attention to lifecycle methods and any helper code they trigger. Magic methods such as __wakeup, __destruct, __toString, __call, and related callbacks are often where the dangerous behavior appears, because they can execute without an explicit function call from the application developer. When those methods touch files, templates, configuration, commands, external requests, or dynamic includes, the module may already contain the ingredients for a gadget chain even if none of those routines look dangerous in isolation.
Common Code Patterns That Reveal a Gadget Chain
Several patterns are especially revealing. One is a serialized blob being stored and later restored with no class allowlist or object restrictions. Another is a custom class that performs filesystem writes, deletes, path concatenation, command execution, template rendering, or method dispatch inside a destructor or wakeup method. A third is code that accepts structured input, decodes it, and forwards it into a sink with no strict schema checks or type enforcement.
It is also worth checking whether the module or theme reuses utility classes in a way that widens impact. A seemingly harmless helper that logs values, fetches remote URLs, manipulates upload paths, or shells out for image processing can become part of a chain when object properties are attacker-controlled. The important question is whether an attacker can influence object state before the dangerous method runs, not whether the dangerous method was written with malicious intent.
In custom CMS code, the risk often hides in convenience features: import/export routines, caching layers, plugin settings, preview endpoints, and legacy compatibility code. These features are attractive because developers sometimes trust internal data too much or preserve old serialized formats for backward compatibility. That is exactly where object injection tends to surface first, especially when the code path was added for functionality rather than security review.
What Makes the Finding Practically Exploitable
A finding becomes much more credible when the object graph includes a reachable sink and the attacker can shape the properties that flow into it. The presence of unserialize() alone is not the whole story; exploitability depends on whether the application can be induced to instantiate a class with a useful side effect and whether the input can reach the required properties in a predictable way. In other words, the issue is strongest when deserialization plus lifecycle behavior plus an actionable sink align.
For a custom module or theme, that usually means confirming three things: first, that user influence exists; second, that one or more classes in the runtime can be triggered through magic methods; and third, that the resulting behavior can touch a sensitive primitive such as file write, file include, command execution, SSRF, or authentication bypass. A module that only unserializes trusted, internal data is still worth reviewing, but the sign of an exploitable issue is when those assumptions are weak, undocumented, or easy to bypass.
If the code base contains third-party libraries, framework adapters, or vendor components, examine how the custom code passes data into them. Gadget chains are often assembled across boundaries, with the custom module providing the entry point and a library providing the dangerous method behavior. That is why object injection reviews should cover the whole reachable class set, not just the custom files themselves.
Risk and Threat Considerations
php object injection is risky because it can turn a parsing bug into code execution, file tampering, or data exposure once the application trusts attacker-shaped object state. The threat is amplified when custom modules or themes run with broad filesystem permissions or can invoke privileged application routines.
Failure mechanism: Untrusted input reaches deserialization, class selection is not restricted, and a magic method or chained helper consumes attacker-controlled properties in a sensitive sink.
Impact: An attacker may delete or overwrite files, execute commands, disclose secrets, alter application state, or build a reliable remote code execution path through a gadget chain.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
MITRE ATT&CK addresses the attack and risk surface, while OWASP ASVS, NIST SP 800-53 Rev 5 and CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP ASVS | V9 — Self-contained Tokens | Deserialization and object state handling are tied to token and object integrity checks. |
| V15 — Secure Coding and Architecture | Custom module and theme code paths need secure design against unsafe deserialization and gadget chains. | |
| Recommendation — Use V9 to validate object integrity and reject attacker-shaped state before reconstruction. Apply V15 to remove unsafe deserialization paths and constrain lifecycle side effects. | ||
| NIST SP 800-53 Rev 5 | SI-10 — Information Input Validation | The issue begins when untrusted input is accepted and transformed into executable object state. |
| AC-6 — Least Privilege | Object injection impact grows when the module can touch files, commands, or privileged actions. | |
| Recommendation — Enforce SI-10 to validate input before it reaches deserialization or object sinks. Apply AC-6 to limit what the compromised code path can read, write, or execute. | ||
| MITRE ATT&CK | T1059 — Command and Scripting Interpreter | Many PHP object injection chains end in command execution through a scripting sink. |
| Recommendation — Map any command-execution gadget to T1059 and hunt for reachable execution sinks. | ||
| CIS Controls v8 | CIS-16 — Application Software Security | Custom modules and themes are application code that should be reviewed for unsafe deserialization. |
| Recommendation — Use CIS-16 to review custom code for unsafe object handling and exploitable sinks. | ||
Practitioner Guidance
What to verify: Confirm whether the module or theme ever deserializes data that a requester can influence directly or indirectly, including stored values that originate from requests. If the answer is yes, verify whether class allowlisting, strict type checks, and object restrictions are enforced before that data is used.
Decision rule: If the deserialized object can reach file handling, command execution, template loading, or dynamic dispatch, treat it as a high-priority finding even if exploitation is not yet proven. If the code only handles trusted internal data, document the trust boundary and look for ways that boundary can be bypassed later by adjacent features.
Practitioner takeaway: The strongest indicator is not “serialization exists,” it is “attacker-controlled data can shape object state before a sensitive lifecycle method runs.” When that pattern is present, assume the module or theme needs deeper gadget-chain review, not just a superficial code scan.
Related resources from NHI Mgmt Group
Deepen Your Knowledge
Reviewed and updated by the NHIMG editorial team on September 24, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org