CVE-2026-8385

WP Go Maps < 10.0.10 - Unauthenticated Sensitive Information Disclosure via Datatables AJAX Fallback

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
10.0.10
Patched in
1d
Time to patch

Description

The WP Go Maps plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 10.0.09 via the datatables AJAX fallback route. This makes it possible for unauthenticated attackers to extract marker records that the site owner has not approved for public display, including their title, category, address and description fields.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=10.0.09
PublishedJune 5, 2026
Last updatedJune 5, 2026
Affected pluginwp-google-maps

What Changed in the Fix

Changes introduced in v10.0.10

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-8385 ## 1. Vulnerability Summary The **WP Go Maps** plugin (versions <= 10.0.09) contains a sensitive information disclosure vulnerability within its DataTables AJAX fallback mechanism. The core issue is a logical flaw in how the plugin determines if a request…

Show full research plan

Exploitation Research Plan: CVE-2026-8385

1. Vulnerability Summary

The WP Go Maps plugin (versions <= 10.0.09) contains a sensitive information disclosure vulnerability within its DataTables AJAX fallback mechanism. The core issue is a logical flaw in how the plugin determines if a request is "administrative." In WPGMZA\MarkerDataTable::getWhereClause, the code uses is_admin() to decide whether to filter out unapproved markers. In WordPress, is_admin() returns true for all requests to admin-ajax.php, including unauthenticated (nopriv) requests. Consequently, an unauthenticated attacker can access the AJAX fallback route to retrieve marker data—including title, address, and description—that has not been approved for public display.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wpgmza_rest_api_request (Registered in includes/class.rest-api.php via wp_ajax_nopriv_wpgmza_rest_api_request)
  • Method: GET or POST
  • Authentication: None (Unauthenticated)
  • Vulnerable Parameter: short_route (used to target the datatables logic)
  • Preconditions: The plugin must be active. At least one "unapproved" marker must exist in the database (e.g., a visitor-generated marker awaiting moderation).

3. Code Flow

  1. Entry Point: An unauthenticated request is sent to admin-ajax.php with action=wpgmza_rest_api_request.
  2. Fallback Logic: WPGMZA\RestAPI::onAJAXRequest (in includes/class.rest-api.php) receives the request. It identifies the intended route based on the short_route or URL parameters.
  3. Route Registration: In includes/class.rest-api.php, the datatables route is registered via registerRoute(). Crucially, lines 135-139 explicitly skip nonce checks for the datatables route:
    $skipNonceRoutes = array('features', 'markers', 'marker-listing', 'datatables');
    if(in_array(str_replace('/', '', $route), $skipNonceRoutes)){
        $doActionNonceCheck = false;
    }
    
  4. Table Instantiation: The request triggers the DataTables handler, which instantiates WPGMZA\MarkerDataTable.
  5. Vulnerable Sink: WPGMZA\MarkerDataTable::getWhereClause (in includes/tables/class.marker-datatable.php) executes:
    if(!(is_admin() || (isset($_SERVER['HTTP_REFERER']) && preg_match('/page=wp-google-maps-menu/', $_SERVER['HTTP_REFERER']) && $wpgmza->isUserAllowedToEdit())))
    {
        $clause .= ' AND approved=%d';
        $query_params[] = 1;
    }
    
  6. Logic Failure: Since the request is processed via admin-ajax.php, is_admin() returns true. The if condition evaluates to false, the approved=1 clause is not appended, and the database query returns all markers, including unapproved ones.

4. Nonce Acquisition Strategy

No nonce is required for this exploit. As identified in includes/class.rest-api.php (Line 137), the datatables route is explicitly added to the $skipNonceRoutes array, and the AJAX action is registered as wp_ajax_nopriv_wpgmza_rest_api_request.

5. Exploitation Strategy

The goal is to invoke the datatables fallback route for the MarkerDataTable class.

  1. Request Type: POST (to bypass potential GET length limits and follow the fallback structure).
  2. URL: http://<target>/wp-admin/admin-ajax.php
  3. Payload Parameters:
    • action: wpgmza_rest_api_request
    • short_route: /datatables
    • php_class: WPGMZA\\MarkerDataTable
    • draw: 1 (Standard DataTables parameter)
    • start: 0
    • length: 10
  4. Action: Send the request using the http_request tool.

6. Test Data Setup

To verify the disclosure, markers with approved = 0 must exist.

  1. Create an Unapproved Marker:
    wp db query "INSERT INTO wp_wpgmza (title, address, description, approved, lat, lng) VALUES ('Secret Location', '123 Hidden St', 'Sensitive Data', 0, '0.000000', '0.000000');"
    
  2. Verify Setup:
    wp db query "SELECT id, title, approved FROM wp_wpgmza WHERE approved = 0;"
    

7. Expected Results

  • Response Code: 200 OK
  • Response Body: A JSON object containing a data array (DataTables format).
  • Indicator of Success: The data array contains the entry for "Secret Location" despite it being unapproved.

8. Verification Steps

After the HTTP request, check the response body for the sensitive marker:

  1. Use jq or a similar tool to parse the response from the http_request tool.
  2. Confirm the presence of markers where approved is logically 0.
  3. Validate that the same marker is not visible on the frontend map (which uses a different, properly filtered REST endpoint).

9. Alternative Approaches

If the php_class parameter is restricted, the attacker can attempt to reach the endpoint by mimicking the standard REST API path structure through the short_route parameter, e.g., short_route=markers if that route also utilizes a vulnerable DataTable class without proper capability checks.

10. Remediation Recommendation

The use of is_admin() for security checks in AJAX handlers should be replaced with current_user_can('manage_options') or a specific plugin capability (e.g., $wpgmza->isUserAllowedToEdit()). This ensures that only users with actual administrative privileges—rather than any request hitting the administrative AJAX endpoint—can bypass marker approval filters.

Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Go Maps plugin is vulnerable to unauthenticated sensitive information disclosure due to a logic flaw in its DataTables AJAX fallback mechanism. By exploiting the fact that is_admin() returns true for all admin-ajax.php requests, attackers can retrieve marker data that has not been approved for public display.

Vulnerable Code

// includes/tables/class.marker-datatable.php:33
protected function getWhereClause($input_params, &$query_params, $clause_for_total=false)
{
    global $wpgmza;
    
    $clause = AjaxTable::getWhereClause($input_params, $query_params, $clause_for_total);
    
    if(!(is_admin() || (isset($_SERVER['HTTP_REFERER']) && preg_match('/page=wp-google-maps-menu/', $_SERVER['HTTP_REFERER']) && $wpgmza->isUserAllowedToEdit())))
    {
        $clause .= ' AND approved=%d';
        $query_params[] = 1;
    }
    
    return $clause;
}

---

// includes/class.rest-api.php:135
$skipNonceRoutes = array('features', 'markers', 'marker-listing', 'datatables');
if(in_array(str_replace('/', '', $route), $skipNonceRoutes)){
    $doActionNonceCheck = false;
}

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/wp-google-maps/10.0.09/includes/tables/class.marker-datatable.php	2026-04-16 15:28:10.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wp-google-maps/10.0.10/includes/tables/class.marker-datatable.php	2026-05-13 08:10:24.000000000 +0000
@@ -30,7 +30,7 @@
 		
 		$clause = AjaxTable::getWhereClause($input_params, $query_params, $clause_for_total);
 		
-		if(!(is_admin() || (isset($_SERVER['HTTP_REFERER']) && preg_match('/page=wp-google-maps-menu/', $_SERVER['HTTP_REFERER']) && $wpgmza->isUserAllowedToEdit())))
+		if(!((isset($_SERVER['HTTP_REFERER']) && preg_match('/page=wp-google-maps-menu/', $_SERVER['HTTP_REFERER']) && $wpgmza->isUserAllowedToEdit())))
 		{
 			$clause .= ' AND approved=%d';
 			$query_params[] = 1;
--- /home/deploy/wp-safety.org/data/plugin-versions/wp-google-maps/10.0.09/includes/class.rest-api.php	2026-04-16 15:28:10.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wp-google-maps/10.0.10/includes/class.rest-api.php	2026-05-13 08:10:24.000000000 +0000
@@ -838,6 +838,12 @@
 				if(preg_match('#/wpgmza/v1/markers/(\d+)#', $route, $m)) {
 					try{
 						$marker = Marker::createInstance($m[1], Crud::SINGLE_READ, isset($_GET['raw_data']));
+
+						if(empty($marker->approved) && !$wpgmza->isUserAllowedToEdit()){
+							/* Marker is not approved */
+							return new \WP_Error('wpgmza_marker_not_found', 'Marker does not exist', array('status' => 404));
+						}
+
 						return $marker;
 					} catch (\Exception $ex){
 						return new \WP_Error('wpgmza_marker_not_found', 'Marker does not exist', array('status' => 404));

Exploit Outline

The exploit targets the AJAX fallback route 'wpgmza_rest_api_request' via /wp-admin/admin-ajax.php. An unauthenticated attacker sends a POST request with 'short_route' set to '/datatables' and 'php_class' set to 'WPGMZA\\MarkerDataTable'. Because the plugin uses is_admin() to determine whether to apply the 'approved=1' filter, and is_admin() returns true for all admin-ajax.php requests, the database query returns all markers including those pending approval. No nonce is required as the 'datatables' route is explicitly excluded from nonce checks.

Check if your site is affected.

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