Skip to content
Thursday, October 22, 2026AboutContactRSS
Vulnerabilities

Stop PHP Object Injection: Priority Fixes for Secure Code

Disabling deserialization entirely eliminates the threat, while input validation alone fails because attackers bypass filters using encoded payloads that look harmless to basic checks.

Illustration: A tangled knot of colorful ribbons unravels into sharp, jagged shards on a clean white desk.
AI-generated illustration: Shell Bulletin
Quick answer

Prevent PHP object injection by disabling the magic method `__wakeup()` and avoiding `unserialize()` on user input. Replace object serialization with JSON or structured data formats. Validate all incoming data types strictly. Use allowlists for expected data structures. Never trust external sources with serialized objects, as this bypasses standard security controls and leads to remote code execution.

The Mechanics of Object Injection

PHP object injection occurs when an application deserializes untrusted data. Deserialization converts a string back into a PHP object. The language restores the object’s state, including its properties and methods. If an attacker controls the serialized string, they can craft a payload that instantiates a specific class. This class may contain dangerous methods, such as file operations or database queries.

The application executes these methods automatically during the restoration process. This happens before any business logic validation. The attacker does not need to guess the class name. They can often find vulnerable classes in the application’s own library. This turns a data parsing function into a code execution engine.

Infographic: Stop PHP Object Injection: Priority Fixes for Secure Code. Disabling `unserialize()` on external input removes the primary attack vector for object injection vulnerabilities. Input validation fails when attackers encode malicious payloads, making type enforcement and allowlists necessar
Infographic: Stop PHP Object Injection: Priority Fixes for Secure Code. Free to share with a link to Shell Bulletin.

Why Input Validation Fails

Many developers assume that filtering input stops object injection. This assumption is incorrect. Attackers encode their payloads using various techniques. Base64 encoding, URL encoding, and hex encoding all transform the malicious string. Standard filters often miss these encoded variants. The filter sees safe characters. The deserializer decodes the string and reveals the dangerous object. Validation checks the surface, not the structure. You cannot validate the intent of a serialized blob. The data looks like random noise to a simple filter. This is why validation is a weak defense. It provides a false sense of security. The underlying mechanism remains open to exploitation.

Priority One: Disable Deserialization

The most effective measure is to stop deserializing untrusted data. If your application does not need to restore complex PHP objects from user input, disable the feature. Remove calls to unserialize() for any data originating outside the application. This includes cookies, query parameters, and POST bodies. If you must handle external data, use a different format. JSON and XML are safer because they do not instantiate classes. They parse into simple arrays or objects. You control the structure of the data. You define how the data is used. This removes the ability for an attacker to trigger arbitrary code execution. It is a binary choice. Either you trust the source completely, or you do not deserialize.

Priority Two: Enforce Type Constraints

If you cannot disable deserialization, enforce strict type constraints. PHP allows you to specify which classes can be instantiated. Use the allowed_classes option in unserialize(). This option restricts the deserializer to a whitelist of safe classes. Any attempt to instantiate a class not on the list fails. This prevents the use of dangerous system classes. It limits the damage to the specific classes you permit. You must audit these classes carefully. Even a safe class can be dangerous if it has a magic method. Check for __wakeup(), __destruct(), and __toString(). These methods run automatically. They can execute code even if the class itself seems benign.

Priority Three: Validate Magic Methods

Magic methods are special functions in PHP that trigger on specific events. __wakeup() runs when an object is unserialized. __destruct() runs when the object is destroyed. __toString() runs when the object is cast to a string. Attackers chain these methods together. This is called a gadget chain. One method calls another, eventually reaching a dangerous function. You must audit every class in your application. Identify all magic methods. Determine if they perform sensitive actions. If a magic method interacts with the file system or database, it is a risk. Consider removing or rewriting these methods. If they are necessary, ensure they validate their own inputs. This reduces the surface area for gadget chains.

MeasureEffortWhat it stops
Disable unserialize()LowAll object injection via that function
Use allowed_classesMediumInstantiation of unauthorized classes
Audit magic methodsHighGadget chains within allowed classes
Input filteringLowNothing reliable; easily bypassed

Replacing Serialization with Safer Formats

Consider replacing PHP serialization with data interchange formats. JSON is a common alternative. It stores data as key-value pairs. It does not store class information. When you parse JSON, you get an array or a standard object. You must explicitly create the PHP objects from this data. This gives you control over the instantiation process.

You can validate the data before creating the object. XML is another option. It is more verbose but also safe from object injection. These formats are widely supported. They work across different languages and platforms. This improves interoperability. It also removes the dependency on PHP-specific serialization. This is a long-term architectural improvement.

The Hidden Cost of Legacy Code

Legacy applications often rely on object serialization for session storage. Sessions store user state between requests. PHP serializes the session data by default. If an attacker can modify the session cookie, they can inject objects. This is a common attack vector. You must configure PHP to use a safe session handler. JSON or custom handlers are safer. You also need to secure the session cookie. Use the httponly and secure flags. This prevents JavaScript access and ensures HTTPS transmission. Do not store sensitive data in sessions. Keep sessions minimal. This reduces the impact if a session is compromised. Review your session configuration regularly. Ensure it aligns with current security standards.

What Does Not Work

Several common measures do not stop object injection. Escaping output prevents cross-site scripting (XSS). It does not stop deserialization. Input validation, as noted, is easily bypassed. Using a web application firewall (WAF) can help. WAFs detect known patterns. They are not a complete solution. Attackers create new payloads. A WAF may miss them. Do not rely on a WAF as your primary defense. It is a layer of defense in depth. It complements code fixes. It does not replace them. You must fix the code. You must remove the vulnerability. Relying on external tools leaves you exposed to novel attacks.

Closing Checklist for Immediate Action

Review your codebase for unserialize() calls. Identify where user input reaches this function. Disable deserialization for any external data source. Configure allowed_classes if you must deserialize. Audit your classes for dangerous magic methods. Replace session serialization with a safer format. These steps reduce your risk significantly. They address the root cause. They do not rely on filtering. They enforce structural safety. Implement these changes today. Schedule a review for your dependency updates. Ensure your libraries are secure. Check for related issues like command injection. Secure your entire application stack. This proactive approach protects your business.

Key takeaways

  • Disabling `unserialize()` on external input removes the primary attack vector for object injection vulnerabilities.
  • Input validation fails when attackers encode malicious payloads, making type enforcement and allowlists necessary defenses.
  • Replacing object serialization with JSON or XML structures prevents the instantiation of arbitrary classes during data parsing.
Bottom line

Disabling deserialization on untrusted input is the only reliable way to prevent PHP object injection. Audit your code for `unserialize()` calls and replace them with JSON parsing or strict type constraints today.

Frequently asked questions

Does HTTPS prevent PHP object injection?

No, HTTPS encrypts data in transit but does not validate the content. An attacker can send a malicious serialized payload over an encrypted connection, and the server will still process it if the code is vulnerable.

Can I use input sanitization to stop object injection?

Input sanitization is unreliable for this threat. Attackers use encoding techniques to bypass filters, making sanitization ineffective as a standalone defense against crafted serialized payloads.

How do I know if my session data is vulnerable?

If your application uses PHP’s default session handler and stores objects in the session, it is vulnerable. Attackers can manipulate session cookies to inject malicious objects during deserialization.

Is JSON completely safe from injection?

JSON parsing is safe from object injection because it does not instantiate classes. However, you must still validate the parsed data to prevent other issues like cross-site scripting or command injection.

How this guide was produced: written by the Shell Bulletin editorial team with AI assistance, checked against the public references listed below, and reviewed when the facts change. See our editorial policy or report an error.

Further reading

  1. CVE Program
  2. OWASP Top Ten
  3. FIRST: Common Vulnerability Scoring System
PHP object injectionphp securityobject injectionweb vulnerabilities

Related stories