CVE-2024-24842: unauthenticated PHP object injection in a 10,000-install WordPress plugin
A view-counter cookie that nobody thinks about reaches PHP's unserialize() with no authentication. This is how a single unsafe deserialize call in the Knowledge Base plugin becomes a CVSS 9.8 unauthenticated object injection, and the one-line change that fixed it.
Knowledge Base for Documentation, FAQs with AI Assistance is a WordPress plugin with more than 10,000 active installations. CVE-2024-24842 is a CVSS 9.8 unauthenticated PHP object injection in it, and it is a clean, small example of how one careless unserialize() opens the whole door. Affected versions are 11.30.2 and below; the fix landed in 11.31.0.

The bug in one sentence
User input reaches PHP's unserialize() without authentication and without sanitization. That is the entire vulnerability class: if an attacker controls the bytes handed to unserialize(), they control the shape and contents of the objects PHP builds, and any dangerous "magic method" (__wakeup, __destruct, …) on a class the application already loads can be triggered as a gadget.
Tracing the call path
The plugin exposes an AJAX action to count article views. Because it is registered through the wp_ajax_nopriv_ hook, it is reachable by anyone, logged in or not. From there the input flows down a short chain:
epkb_count_article_view(the AJAX action) →process_article_count()→maybe_increase_article_count()→is_article_recently_viewed()→maybe_unserialize()
The last call is the problem. maybe_unserialize() is a thin WordPress wrapper around PHP's native unserialize(): if the string looks serialized, it deserializes it. The data it is handed comes straight from the epkb_article_views_counter cookie — fully attacker-controlled, never validated.

Why a cookie is the perfect vector
Nobody audits a view-counter cookie. It looks like harmless bookkeeping — "which articles has this browser already seen" — so it round-trips through the plugin untouched. But a cookie is just a header the client sets, which means the attacker sets it. Put a crafted serialized payload in epkb_article_views_counter, hit the unauthenticated AJAX endpoint, and the plugin deserializes your bytes on the server.
Impact
An unauthenticated attacker can trigger PHP object injection on any site running a vulnerable version. Depending on the gadgets available in the wider WordPress environment, that ranges from property-oriented tampering to remote code execution. CVSS 9.8 reflects the worst realistic case: unauthenticated, network-reachable, high impact on confidentiality, integrity and availability.
The fix
The patch is exactly what you would hope: stop deserializing untrusted input. Version 11.31.0 replaced the unsafe maybe_unserialize() handling of the cookie with JSON-based encoding and decoding. JSON only produces plain arrays and scalars, so a malicious payload can no longer instantiate arbitrary objects. No gadget chain, no injection.
The lesson is the boring, durable one: never hand user-controlled bytes to unserialize(). If you need structured data from a cookie or a request, use json_decode(). The moment a value crosses the trust boundary from client to server, serialized PHP is not a data format, it is code.
References & further reading
An Ngo
Co-Founder, Starfish Security