ZeroPath at Black Hat USA 2026

Admin Columns WordPress Plugin CVE-2026-7654: Brief Summary of PHP Object Injection to Remote Code Execution

A brief summary of CVE-2026-7654, a high severity PHP Object Injection vulnerability in the Admin Columns WordPress plugin that enables authenticated attackers with Contributor level access to achieve remote code execution via a bundled Laravel POP gadget chain.

CVE Analysis

10 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-06-05

Admin Columns WordPress Plugin CVE-2026-7654: Brief Summary of PHP Object Injection to Remote Code Execution
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A PHP Object Injection flaw in the Admin Columns WordPress plugin allows any authenticated user with Contributor level privileges to achieve full remote code execution on the underlying web server, scoring a CVSS 8.8. What makes this vulnerability particularly notable is not just the low authentication barrier, but the fact that the plugin bundles a Laravel library containing a ready made POP gadget chain that converts the deserialization weakness into immediate, practical code execution.

Admin Columns is a widely used WordPress plugin developed by CodePress that enhances the WordPress admin interface by allowing administrators to customize, sort, and manage columns on post, page, user, and taxonomy list screens. With over 100,000 active installations and a 4.9 out of 5 star rating from more than 1,650 reviews, it occupies a significant footprint in the WordPress ecosystem. The plugin also offers a commercial Pro version with integrations for WooCommerce, Advanced Custom Fields, and Yoast SEO, making it a common fixture on both small and enterprise WordPress deployments.

Technical Information

Root Cause: Unsafe Deserialization in IdsToCollection

The vulnerability resides in the IdsToCollection::get_ids_from_string() function, located at line 42 of classes/Formatter/IdsToCollection.php. This function calls PHP's native unserialize() on post meta values without specifying the allowed_classes option. The allowed_classes parameter was introduced in PHP 7.0 precisely to prevent Object Injection by controlling which classes can be instantiated during deserialization. Its absence here means any PHP class available in the runtime can be instantiated from a crafted serialized string.

The data flow begins in Meta.php (line 34 in classes/Formatter/), which reads custom field meta values from WordPress posts and passes them downstream to IdsToCollection for processing. This is the entry point where attacker controlled data enters the vulnerable deserialization path.

Attack Flow

The exploitation proceeds through a clear sequence:

  1. Initial Access: An attacker authenticates to the WordPress site with Contributor level credentials. This is one of the lowest default WordPress roles, commonly granted to guest authors or external content contributors.

  2. Payload Injection: The attacker creates or edits a post and sets a custom meta field value to a crafted serialized PHP object string. WordPress allows Contributors to set custom meta fields on their own posts.

  3. Trigger Deserialization: When the Admin Columns plugin renders the column view for the post (for example, when an administrator views the post list in the WordPress admin panel), the Meta.php formatter reads the custom field value and passes it to IdsToCollection::get_ids_from_string().

  4. Object Instantiation: The get_ids_from_string() function calls unserialize() on the attacker controlled meta value. Because no allowed_classes restriction is in place, PHP instantiates whatever class is specified in the serialized payload.

  5. POP Chain Execution: The crafted payload leverages classes from the Laravel serializable-closure library bundled in the plugin's vendor/ directory to achieve arbitrary code execution.

The Bundled POP Gadget Chain

The escalation from Object Injection to Remote Code Execution depends entirely on the availability of exploitable classes in the application's scope. In many PHP Object Injection scenarios, attackers must discover suitable gadget chains from the application's own codebase or its dependencies. In this case, the Admin Columns plugin ships with the Laravel serializable-closure library, which provides a complete, self contained POP (Property Oriented Programming) chain.

Two classes in this library are central to the chain:

Native.php (located at vendor/laravel/serializable-closure/src/Serializers/Native.php, line 148): This serializer class implements magic methods (__wakeup() or __destruct()) that are automatically invoked during deserialization. These methods process serialized closure data, providing the initial entry point for the gadget chain.

ClosureStream.php (located at vendor/laravel/serializable-closure/src/Support/ClosureStream.php, line 47): This class implements a PHP stream wrapper that can execute arbitrary PHP code when its stream methods are invoked. The class is annotated with #[AllowDynamicProperties], which enables dynamic property injection, a capability critical to the POP chain's operation.

By constructing a serialized payload that chains the Native serializer's magic methods through to ClosureStream's code execution capability, an attacker executes arbitrary PHP code as the web server user. No file uploads, no additional vulnerabilities, and no external dependencies are required.

CVSS v3.1 Breakdown

The CVSS vector is CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H, yielding a score of 8.8 (High).

MetricValueImplication
Attack VectorNetworkExploitable remotely over the internet
Attack ComplexityLowNo special conditions or race conditions required
Privileges RequiredLowContributor level access is sufficient
User InteractionNoneNo victim action needed; triggered when admin views post list
ScopeUnchangedImpact confined to the vulnerable component
ConfidentialityHighFull system data accessible
IntegrityHighFull system modification possible
AvailabilityHighFull system disruption possible

The combination of Low Attack Complexity and Low Privileges Required is what makes this vulnerability particularly accessible. The attacker does not need to be an Administrator; a Contributor account is enough. On sites that allow user registration with Contributor roles, the barrier to exploitation is essentially just creating an account.

CWE-502: Deserialization of Untrusted Data

This vulnerability is a textbook instance of CWE-502, which describes weaknesses where an application deserializes untrusted data without sufficiently ensuring the resulting data will be valid. In the PHP context, this manifests as PHP Object Injection: unserialize() processes attacker controlled serialized strings, creating objects whose magic methods (__wakeup(), __destruct(), __toString(), etc.) execute operations the developer never intended. The OWASP PHP Object Injection documentation specifically identifies the use of unserialize() on user controlled input as the root cause pattern.

Affected Systems and Versions

The vulnerability affects the Admin Columns plugin (slug: codepress-admin-columns) for WordPress in the following configuration:

  • Affected versions: All versions up to and including 7.0.18
  • Fixed version: 7.0.19 (released May 29, 2026)
  • WordPress requirement: 5.9 or higher
  • PHP requirement: 7.4 or higher
  • Active installations: Over 100,000

The vulnerability is exploitable by any authenticated user with Contributor level access or above (Contributor, Author, Editor, or Administrator roles). Sites that allow open user registration with Contributor roles are at the highest risk.

Both the free version available on the WordPress plugin directory and the commercial Admin Columns Pro version should be evaluated, as the vulnerable code path exists in the core plugin's formatter classes and bundled vendor libraries.

Vendor Security History

The Wordfence Threat Intelligence database maintains a dedicated vulnerability listing page for the Admin Columns plugin, indicating that CVE-2026-7654 is not the first security issue discovered in this software. WPScan also maintains a separate vulnerability listing for the plugin.

A comparable authenticated PHP Object Injection vulnerability was discovered in the "Filter Custom Fields & Taxonomies Light" plugin (versions up to 1.05), which shares the same fundamental weakness pattern: insecure deserialization of custom field meta values in WordPress plugins. This suggests a recurring vulnerability class across the WordPress plugin ecosystem, particularly in plugins that process serialized post meta data.

CodePress's response to CVE-2026-7654 was timely. The patched version 7.0.19 was released on May 29, 2026, approximately one week before the CVE was formally published on the NVD on June 5, 2026. This timeline suggests responsible disclosure coordination between the vulnerability discoverer, Osvaldo Noe Gonzalez Del Rio, and the vendor, with the patch being made available before public disclosure.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Jira
  • Linear
  • Slack
  • Security Compass
Security magnifying glass visualization