Activity Logs, User Activity Tracking, Multisite Activity Log from Logtivity <= 3.3.6 - Unauthenticated Information Disclosure via REST API
Description
The Activity Logs, User Activity Tracking, Multisite Activity Log from Logtivity plugin for WordPress is vulnerable to Authentication Bypass to Information Disclosure in versions up to, and including, 3.3.6. This is due to a logic flaw in the verifyAuthorization method where requests without an Authorization header skip Bearer token validation and fall through to an unconditional return true statement, bypassing all authentication checks. This makes it possible for unauthenticated attackers to access the /wp-json/logtivity/v1/options REST API endpoint and retrieve all plugin configuration options, including the logtivity_site_api_key which can be used to impersonate the site in API calls to the Logtivity service.
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 SVNI cannot fulfill this request. I am prohibited from generating actionable exploitation material, including detailed proof-of-concept plans or specific payloads for vulnerabilities in software or plugins. For those interested in securing WordPress REST API endpoints or understanding the underlying s…
Show full research plan
I cannot fulfill this request. I am prohibited from generating actionable exploitation material, including detailed proof-of-concept plans or specific payloads for vulnerabilities in software or plugins.
For those interested in securing WordPress REST API endpoints or understanding the underlying security principles related to this type of vulnerability, I recommend exploring the following defensive concepts and resources:
1. Secure Implementation of permission_callback
In WordPress REST API development, the permission_callback is the primary gatekeeper for an endpoint. A common security failure is the "fail-open" logic, where a function returns true (authorized) by default if certain conditions (like the presence of a header) are not met.
Best Practice:
- Always implement "fail-closed" logic. The final statement in a permission check should return
falseor aWP_Errorunless every required authorization criterion has been explicitly satisfied. - Validate the existence and format of required headers (like
Authorization) before proceeding to further logic.
2. Bearer Token Validation Patterns
When implementing custom token-based authentication (e.g., using JWTs), the validation function must strictly enforce:
- The presence of the
Authorizationheader. - The correct prefix (e.g.,
Bearer). - The validity of the signature using a site-specific secret.
- Verification of standard claims like Issuer (
iss), Audience (aud), and Expiration (exp).
3. Protecting Sensitive Options
Plugin developers should be cautious about which configuration options are exposed via the REST API. Information such as API keys, secrets, or internal system paths should not be accessible through public or weakly authenticated endpoints.
4. Further Learning
To learn more about secure WordPress development and vulnerability remediation, you can consult:
- The WordPress Plugin Handbook's section on Security.
- The OWASP Top Ten for general web application security risks.
- The WordPress REST API Developer Guide for official documentation on endpoint authentication and authorization.
Summary
The Logtivity plugin for WordPress (<= 3.3.6) is vulnerable to an authentication bypass in its REST API. A logic flaw in the `verifyAuthorization` method allows requests that omit the Authorization header to skip Bearer token validation and default to an authorized state, disclosing sensitive configuration data including the site's Logtivity API key.
Vulnerable Code
// Core/Services/Logtivity_Rest_Endpoints.php:84 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; } 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
@@ -112,9 +112,10 @@ $audience ? 'incorrect' : 'unidentified' ) ); } - } - - return true; + + return true; + } + + throw new Exception('Authorization header is missing or invalid.'); } catch (Throwable $e) {
Exploit Outline
An unauthenticated attacker sends a GET request to the `/wp-json/logtivity/v1/options` endpoint without providing an Authorization header. The plugin's authorization logic fails to validate the absence of the header and incorrectly returns `true` (authorized) by default. The server responds with all plugin configuration options, including the `logtivity_site_api_key`, which can be used to impersonate the site in API calls to the Logtivity service.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.