WP Go Maps < 10.0.10 - Unauthenticated Sensitive Information Disclosure via Datatables AJAX Fallback
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:NTechnical Details
<=10.0.09What Changed in the Fix
Changes introduced in v10.0.10
Source Code
WordPress.org SVN# 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 inincludes/class.rest-api.phpviawp_ajax_nopriv_wpgmza_rest_api_request) - Method:
GETorPOST - Authentication: None (Unauthenticated)
- Vulnerable Parameter:
short_route(used to target thedatatableslogic) - 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
- Entry Point: An unauthenticated request is sent to
admin-ajax.phpwithaction=wpgmza_rest_api_request. - Fallback Logic:
WPGMZA\RestAPI::onAJAXRequest(inincludes/class.rest-api.php) receives the request. It identifies the intended route based on theshort_routeor URL parameters. - Route Registration: In
includes/class.rest-api.php, thedatatablesroute is registered viaregisterRoute(). Crucially, lines 135-139 explicitly skip nonce checks for thedatatablesroute:$skipNonceRoutes = array('features', 'markers', 'marker-listing', 'datatables'); if(in_array(str_replace('/', '', $route), $skipNonceRoutes)){ $doActionNonceCheck = false; } - Table Instantiation: The request triggers the DataTables handler, which instantiates
WPGMZA\MarkerDataTable. - Vulnerable Sink:
WPGMZA\MarkerDataTable::getWhereClause(inincludes/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; } - Logic Failure: Since the request is processed via
admin-ajax.php,is_admin()returnstrue. Theifcondition evaluates tofalse, theapproved=1clause 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.
- Request Type: POST (to bypass potential GET length limits and follow the fallback structure).
- URL:
http://<target>/wp-admin/admin-ajax.php - Payload Parameters:
action:wpgmza_rest_api_requestshort_route:/datatablesphp_class:WPGMZA\\MarkerDataTabledraw:1(Standard DataTables parameter)start:0length:10
- Action: Send the request using the
http_requesttool.
6. Test Data Setup
To verify the disclosure, markers with approved = 0 must exist.
- 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');" - 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
dataarray (DataTables format). - Indicator of Success: The
dataarray 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:
- Use
jqor a similar tool to parse the response from thehttp_requesttool. - Confirm the presence of markers where
approvedis logically0. - 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.
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
@@ -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; @@ -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.