coreActivity: Activity Logging for WordPress <= 3.0 - Unauthenticated PHP Object Injection via 'user_agent' Log Meta Field
Description
The coreActivity: Activity Logging for WordPress plugin for WordPress is vulnerable to PHP Object Injection in all versions up to, and including, 3.0. This is due to the plugin failing to validate or strip PHP serialization syntax from the User-Agent HTTP header before storing it in the logmeta table, and subsequently calling `maybe_unserialize()` on every retrieved `meta_value` in `query_metas()` without verifying the data was originally serialized by the application. This makes it possible for unauthenticated attackers to inject a crafted PHP serialized payload via the User-Agent header during any logged event (such as a failed login attempt), which, when an administrator views the Logs page, is deserialized and passed to `DeviceDetector::setUserAgent()`, triggering a Fatal TypeError that creates a persistent Denial of Service condition blocking administrator access to the Logs page entirely.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
What Changed in the Fix
Changes introduced in v3.1
Source Code
WordPress.org SVN# Research Plan: CVE-2026-7635 PHP Object Injection in coreActivity ## 1. Vulnerability Summary The **coreActivity: Activity Logging for WordPress** plugin (<= 3.0) is vulnerable to **unauthenticated PHP Object Injection**. The plugin captures the `User-Agent` HTTP header during logged events (e.g.…
Show full research plan
Research Plan: CVE-2026-7635 PHP Object Injection in coreActivity
1. Vulnerability Summary
The coreActivity: Activity Logging for WordPress plugin (<= 3.0) is vulnerable to unauthenticated PHP Object Injection. The plugin captures the User-Agent HTTP header during logged events (e.g., failed logins, 404s, or general activity) and stores it in the logmeta database table without sanitizing PHP serialization syntax (e.g., O:8:"...").
When an administrator views the Logs page, the plugin retrieves these values and calls maybe_unserialize() on every meta_value. Because the input was not sanitized during storage, an attacker can provide a serialized object string that is then instantiated. The resulting object is passed to DeviceDetector::setUserAgent(), which expects a string, causing a Fatal TypeError in PHP 8.x. This results in a persistent Denial of Service (DoS) for the Logs page.
2. Attack Vector Analysis
- Endpoint: Any page that triggers a logged event. The most reliable unauthenticated target is
wp-login.php(triggering a login failure event). - Vulnerable Parameter:
User-AgentHTTP Request Header. - Authentication: None required (unauthenticated).
- Preconditions:
- The plugin must be active.
- Event logging must be enabled (typically default for login failures).
- The site must be running on PHP 8.x (to trigger the
TypeErrorDoS).
3. Code Flow
- Ingestion: A request is made to the WordPress site.
- Capture: In
Dev4Press\Plugin\CoreActivity\Log\Core::__construct(), the plugin populatescached_data['ua']via$this->get_user_agent()(which reads$_SERVER['HTTP_USER_AGENT']). - Logging Trigger: An event (like a failed login) calls
Dev4Press\Plugin\CoreActivity\Log\Core::log(). - Processing:
log()callsprepare_meta()andprepare_device($meta). The unsanitized User-Agent string is added to the$metaarray. - Storage:
Dev4Press\Plugin\CoreActivity\Basic\DB::i()->log_event($data, $meta)is called. Themeta_value(the malicious string) is written directly to thelogmetatable. - Retrieval (Admin Side): An administrator navigates to
wp-admin/admin.php?page=coreactivity-logs. - Deserialization: The display logic calls a retrieval function (likely
query_metas()) which executesmaybe_unserialize()on the storedmeta_value. - Sink: The resulting object (e.g., a
stdClassobject) is passed toDeviceDetector::setUserAgent(). - Fatal Error: PHP throws a
TypeErrorbecause the method signature forsetUserAgentrequires astring, but anobjectwas provided.
4. Nonce Acquisition Strategy
This vulnerability does not require a nonce for the injection phase.
- The injection occurs via the
User-Agentheader during standard WordPress actions (like login) which are hooked by the plugin. - The plugin's logging mechanism runs automatically on hooks like
wp_login_failed. - The DoS/Execution trigger occurs when the Admin visits the Logs page, which is a standard GET request to a known slug.
5. Exploitation Strategy
The goal is to inject a PHP object that triggers a TypeError when the administrator attempts to view the logs.
Injection Phase
- Target the login endpoint to ensure an event is logged.
- HTTP Request:
Note:POST /wp-login.php HTTP/1.1 Host: victim.com Content-Type: application/x-www-form-urlencoded User-Agent: O:8:"stdClass":0:{} log=admin&pwd=wrongpassword&wp-submit=Log+InO:8:"stdClass":0:{}is a simple serializedstdClassobject.
Trigger Phase
- Log in as a WordPress Administrator.
- Navigate to the coreActivity Logs page.
- HTTP Request:
GET /wp-admin/admin.php?page=coreactivity-logs HTTP/1.1 Host: victim.com Cookie: [Admin Cookies]
6. Test Data Setup
- Install and activate coreActivity: Activity Logging for WordPress version 3.0.
- Ensure PHP 8.0+ is used in the test environment.
- Confirm logging is active (check the dashboard at
/wp-admin/admin.php?page=coreactivity-dashboard).
7. Expected Results
- The
log_eventcall will successfully writeO:8:"stdClass":0:{}to the database meta table. - Upon accessing the Logs page, the server will return a 500 Internal Server Error or a white screen.
- The PHP error log will contain:
Fatal error: Uncaught TypeError: DeviceDetector\DeviceDetector::setUserAgent(): Argument #1 ($userAgent) must be of type string, stdClass given...
8. Verification Steps
- Database Check: Use WP-CLI to verify the injected value is in the database.
wp db query "SELECT meta_value FROM wp_coreactivity_logmeta WHERE meta_value LIKE 'O:8:%';" - Log Verification: Check the WordPress error log for the specific
TypeErrorinvolvingDeviceDetector.
9. Alternative Approaches
Remote Code Execution (RCE)
If the environment contains a usable POP chain (gadget), the vulnerability can be escalated from DoS to RCE.
- Analyze
composer.lockfor included libraries. erusev/parsedownandmatomo/device-detectorare present.- Search for gadgets in
dev4press/library(the plugin's custom shared library), specifically looking for__destruct,__wakeup, or__toStringmethods in theDev4Press\v55namespace. - If a gadget is found, replace
O:8:"stdClass":0:{}with the crafted gadget chain payload.
Summary
The coreActivity: Activity Logging for WordPress plugin (<= 3.0) is vulnerable to unauthenticated PHP Object Injection via the User-Agent HTTP header. The plugin stores the raw User-Agent string in the logmeta table and later retrieves it using maybe_unserialize() without validation, allowing attackers to inject crafted PHP objects that can lead to a Denial of Service (DoS) or potential Remote Code Execution (RCE).
Vulnerable Code
// core/log/Core.php private function __construct() { $this->cached_data = array( 'ip' => IP::visitor( coreactivity_settings()->get( 'ip_visitor_forwarded' ) ), 'remote_addr' => IP::visitor( false ), 'server_ip' => isset( $_SERVER['SERVER_ADDR'] ) ? IP::server() : '', 'ua' => $this->get_user_agent(), // Captures unsanitized User-Agent 'referer' => $this->get_referer(), // ... ); } --- // core/log/Core.php public function log( int $event_id, array $data = array(), array $meta = array() ) : int { // ... $data = $this->prepare_data( $event_id, $data ); $meta = $this->prepare_meta( $meta ); // Injects 'ua' into $meta // ... $meta = $this->prepare_device( $meta ); // ... $id = DB::i()->log_event( $data, $meta ); // Stores unsanitized User-Agent in DB // ... }
Security Fix
@@ -50,7 +50,7 @@ 'ip' => IP::visitor( coreactivity_settings()->get( 'ip_visitor_forwarded' ) ), 'remote_addr' => IP::visitor( false ), 'server_ip' => isset( $_SERVER['SERVER_ADDR'] ) ? IP::server() : '', - 'ua' => $this->get_user_agent(), + 'ua' => sanitize_text_field($this->get_user_agent()), 'referer' => $this->get_referer(), 'method' => $this->get_request_method(), 'protocol' => wp_get_server_protocol(), @@ -150,5 +150,5 @@ public function query_metas($log_id) { - // ... - $meta_value = maybe_unserialize($result->meta_value); + // Use a safer retrieval method that avoids automatic deserialization of user-provided strings + $meta_value = $result->meta_value; // ... }
Exploit Outline
The exploit is achieved by performing any action that triggers a logged event while supplying a malicious User-Agent string. 1. An unauthenticated attacker sends a request to an endpoint that triggers logging, such as a POST request to `wp-login.php` with incorrect credentials. 2. The request includes a crafted PHP serialized object (e.g., `O:8:"stdClass":0:{}`) within the `User-Agent` HTTP header. 3. The plugin captures this header and stores it directly in the `logmeta` database table as a `meta_value` associated with the log entry. 4. When a WordPress administrator navigates to the plugin's Logs page (`/wp-admin/admin.php?page=coreactivity-logs`), the plugin retrieves the stored meta values. 5. The plugin calls `maybe_unserialize()` on the retrieved data. Because the data is now a valid serialized object string, PHP instantiates the object. 6. On PHP 8.x, if the resulting object is passed to library functions expecting a string (like `DeviceDetector::setUserAgent`), it triggers a `Fatal TypeError`, effectively locking administrators out of the activity log page (Denial of Service).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.