WP Go Maps (formerly WP Google Maps) <= 10.0.04 - Missing Authorization to Authenticated (Subscriber+) Map Engine Setting Modification
Description
The WP Go Maps (formerly WP Google Maps) plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the processBackgroundAction() function in all versions up to, and including, 10.0.04. This makes it possible for authenticated attackers, with Subscriber-level access and above, to modify global map engine settings.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=10.0.04What Changed in the Fix
Changes introduced in v10.0.05
Source Code
WordPress.org SVNThis research plan outlines the steps required to exploit a missing authorization vulnerability in WP Go Maps (formerly WP Google Maps) versions up to 10.0.04, allowing a Subscriber-level user to modify global map engine settings. ### 1. Vulnerability Summary The vulnerability exists in the `WPGMZA…
Show full research plan
This research plan outlines the steps required to exploit a missing authorization vulnerability in WP Go Maps (formerly WP Google Maps) versions up to 10.0.04, allowing a Subscriber-level user to modify global map engine settings.
1. Vulnerability Summary
The vulnerability exists in the WPGMZA\AdminNotices class, specifically in the processBackgroundAction() method (hooked to the AJAX action wpgmza_persisten_notice_quick_action). The method fails to perform a capability check (e.g., current_user_can('manage_options')) before executing background tasks associated with persistent admin notices. An authenticated attacker with Subscriber-level access can trigger the swap_internal_engine action, which modifies the global map engine configuration (switching from Legacy to Atlas Novus).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
wpgmza_persisten_notice_quick_action(Note the typo:persisteninstead ofpersistent) - Vulnerable Function:
WPGMZA\AdminNotices::processBackgroundAction() - Authentication: Authenticated (Subscriber+)
- Payload Parameter:
slug=switch_engines - Impact: Modifies the
wpgmza_internal_enginesetting, potentially breaking map functionality or changing the UI/UX site-wide.
3. Code Flow
- Entry Point: The plugin registers the AJAX hook in
includes/class.admin-notices.phpline 115:add_action('wp_ajax_wpgmza_persisten_notice_quick_action', array($this, 'processBackgroundAction')); - Processing: When a Subscriber sends a request with
action=wpgmza_persisten_notice_quick_action, WordPress invokesprocessBackgroundAction(). - Trigger: The function (based on the
AdminNotices::createcall on line 64) looks up the persistent notice with the slugswitch_engines. - Sink: The notice
switch_enginesis defined with anajax_actionofswap_internal_engine. TheprocessBackgroundActionmethod executes this action, which updates the global map engine settings via theInternalEngineclass or direct option updates.
4. Nonce Acquisition Strategy
The plugin localizes a global JavaScript object containing the necessary AJAX nonce for authenticated users.
- Shortcode/Page: The
AdminNoticesare initialized on the WordPress admin dashboard. Any logged-in user (including Subscribers) can accesswp-admin/index.php. - Procedure:
- Navigate to
/wp-admin/as a Subscriber. - Use
browser_evalto extract the nonce from thewpgmza_global_varsobject.
- Navigate to
- JS Variable:
window.wpgmza_global_vars?.nonce - Fallback: If not found there, check
window.WPGMZA?.ajax_nonce.
5. Exploitation Strategy
The goal is to force the plugin to switch the global internal engine setting.
Request Details:
- URL:
http://[target]/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
(Note: The parameter name for the nonce in this plugin is typicallyaction=wpgmza_persisten_notice_quick_action&slug=switch_engines&security=[NONCE]security.)
6. Test Data Setup
- Plugin State: Ensure WP Go Maps is installed and active.
- Initial Config: Set the internal engine to legacy to ensure the "switch" notice is targetable:
wp option update wpgmza_internal_engine legacy - Attacker: Create a subscriber user:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password
7. Expected Results
- The AJAX request should return a successful response (likely a JSON object or
1). - The global WordPress option
wpgmza_internal_engine(or the internal setting managed by the plugin) will be changed fromlegacytoatlas-novus.
8. Verification Steps
- Check Setting: Use WP-CLI to verify the change:
wp option get wpgmza_internal_engine- Success: Output is
atlas-novus. - Failure: Output remains
legacy.
- Success: Output is
- Check Notice: Verify if the notice was dismissed in the database:
wp db query "SELECT dismissed FROM wp_wpgmza_admin_notices WHERE name='switch_engines'"
9. Alternative Approaches
If the slug parameter is not the direct trigger, processBackgroundAction might accept an id or ajax_action parameter directly.
- Alternative Body 1:
action=wpgmza_persisten_notice_quick_action&ajax_action=swap_internal_engine&security=[NONCE] - Alternative Body 2 (Notice ID): First, find the ID of the
switch_enginesnotice:wp db query "SELECT id FROM wp_wpgmza_admin_notices WHERE name='switch_engines'"
Then use:action=wpgmza_persisten_notice_quick_action&id=[ID]&security=[NONCE]
Note on Typo: If the request fails with a 400 error, verify the hook name in the actual installed source code, as wpgmza_persisten_notice_quick_action (missing 't') is the literal hook used in the vulnerable version.
Summary
The WP Go Maps plugin for WordPress is vulnerable to unauthorized modification of data due to missing capability checks in the `AdminNotices` class. Authenticated attackers with Subscriber-level access and above can trigger the `processBackgroundAction` AJAX function to modify the global map engine configuration, potentially switching the site from the Legacy engine to Atlas Novus without administrator permission.
Vulnerable Code
// includes/class.admin-notices.php line 330 public function dismissFromPostAjax(){ if (empty($_POST['slug']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce')) { wp_send_json_error(__( 'Security check failed, import will continue, however, we cannot provide you with live updates', 'wp-google-maps' )); } --- // includes/class.admin-notices.php line 349 public function processBackgroundAction(){ if (empty($_POST['relay']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce')) { wp_send_json_error(__( 'Security check failed, import will continue, however, we cannot provide you with live updates', 'wp-google-maps' )); }
Security Fix
@@ -328,7 +328,9 @@ * @return void */ public function dismissFromPostAjax(){ - if (empty($_POST['slug']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce')) { + global $wpgmza; + + if (empty($_POST['slug']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce') || !$wpgmza->isUserAllowedToEdit()) { wp_send_json_error(__( 'Security check failed, import will continue, however, we cannot provide you with live updates', 'wp-google-maps' )); } @@ -347,7 +349,9 @@ * @return void */ public function processBackgroundAction(){ - if (empty($_POST['relay']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce')) { + global $wpgmza; + + if (empty($_POST['relay']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce') || !$wpgmza->isUserAllowedToEdit()) { wp_send_json_error(__( 'Security check failed, import will continue, however, we cannot provide you with live updates', 'wp-google-maps' )); }
Exploit Outline
To exploit this vulnerability, an attacker with a Subscriber-level account must first obtain a valid AJAX nonce. This nonce is typically localized in the `wpgmza_global_vars` JavaScript object on the WordPress admin dashboard for any logged-in user. The attacker then sends a POST request to `/wp-admin/admin-ajax.php` with the action `wpgmza_persisten_notice_quick_action` (noting the literal typo in the hook). By setting the `relay` parameter to `switch_engines` and providing the valid nonce in `wpgmza_security`, the plugin will execute the `swap_internal_engine` action. This modifies the `wpgmza_internal_engine` global option, switching the map engine without the required 'manage_options' capability.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.