MapPress Maps for WordPress <= 2.97.3 - Unauthenticated Stored Cross-Site Scripting
Description
The MapPress Maps for WordPress plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.97.3 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=2.97.3What Changed in the Fix
Changes introduced in v2.97.4
Source Code
WordPress.org SVNThis research plan targets **CVE-2026-56011**, an unauthenticated stored Cross-Site Scripting (XSS) vulnerability in the MapPress Maps for WordPress plugin. The vulnerability stems from a lack of capability checks in AJAX handlers that allow unauthenticated users to save or update map data, combined…
Show full research plan
This research plan targets CVE-2026-56011, an unauthenticated stored Cross-Site Scripting (XSS) vulnerability in the MapPress Maps for WordPress plugin. The vulnerability stems from a lack of capability checks in AJAX handlers that allow unauthenticated users to save or update map data, combined with insufficient output escaping in the map rendering logic.
1. Vulnerability Summary
- Vulnerability: Unauthenticated Stored XSS.
- Location: The vulnerability resides in the AJAX handlers registered in
mappress_api.php(specifically those lackingcurrent_user_canchecks) and the rendering logic inmappress_map.php/mappress_poi.php. - Cause: The plugin registers
wp_ajax_nopriv_versions of map-saving actions. These actions do not verify that the requester has theedit_postsormanage_optionscapability. Furthermore, theto_html()methods for Maps and POIs (Points of Interest) do not properly escape all fields (like POI body content) before outputting them to the page.
2. Attack Vector Analysis
- Vulnerable Endpoint:
/wp-admin/admin-ajax.php. - Action:
mapp_save(inferred action for saving/creating maps). - HTTP Parameter:
map(JSON string containing map and POI data). - Authentication: Unauthenticated (No login required).
- Preconditions: The site must have the plugin active. The exploit is more effective if a MapPress map or "Mashup" is already displayed on a public page, or if the attacker can identify the
oid(Object ID) of an existing post to attach a map to.
3. Code Flow
- Entry Point: An unauthenticated attacker sends a POST request to
admin-ajax.phpwithaction=mapp_save. - Dispatch: WordPress matches the action to the handler registered via
add_action('wp_ajax_nopriv_mapp_save', ...)inmappress_api.php. - Lack of Authorization: The handler in
mappress_api.phpprocesses the request without callingcurrent_user_can(). - Data Processing: The handler parses the
mapJSON parameter. It may callnew Mappress_Map($json_data)and then$map->save(). - Persistence: The
save()method (inmappress_obj.phpormappress_db.php) writes the unsanitized or insufficiently sanitized POI titles/bodies to the{wp_prefix}mappress_mapsor{wp_prefix}mappress_poststables. - Rendering (Sink): When a user views the post/page,
Mappress_Map::to_html()is called (likely viathe_contentfilter). It iterates through POIs, calling$poi->to_html(). - Execution: If
$poi->to_html()returns the POIbodyortitlewithoutesc_html()orwp_kses(), the injected<script>executes in the victim's browser.
4. Nonce Acquisition Strategy
MapPress uses wp_localize_script to pass configuration and nonces to the frontend.
- Shortcode: The plugin's scripts are typically enqueued when the
[mappress]shortcode is present. - Strategy:
- Create a sacrificial page with the shortcode:
wp post create --post_type=page --post_status=publish --post_title="Map" --post_content='[mappress]'. - Navigate to this page.
- Extract the nonce from the
mapp_data(inferred) JavaScript object.
- Create a sacrificial page with the shortcode:
- JS Variable:
window.mapp_data?.nonceorwindow.mappress_data?.nonce. - Verification: Check the
mappress.phpormappress_map.phpfiles for calls towp_create_nonce. Ifcheck_ajax_refereris called in the save handler, the action string must match the one used inwp_create_nonce.
5. Exploitation Strategy
- Setup: Place a map on a page to identify its structure.
- Payload Preparation: Create a JSON object representing a Map with a malicious POI.
{ "title": "Normal Map", "pois": [ { "title": "XSS", "body": "Location info<script>alert(document.domain)</script>", "point": {"lat": 0, "lng": 0} } ] } - HTTP Request:
- Method:
POST - URL:
http://example.com/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=mapp_save&_wpnonce=[NONCE]&map={"title":"XSS_Map","pois":[{"title":"XSS","body":"<img src=x onerror=alert(1)>"}]}
- Method:
- Injection: If the response is a JSON success message (e.g.,
{"success": true, "mapid": 123}), the XSS is stored.
6. Test Data Setup
- Plugin: Install MapPress Maps for WordPress v2.97.3.
- Content: Create one public post with ID
1. - Shortcode:
wp post create --post_type=page --post_status=publish --post_content='[mappress]'to ensure nonces are generated and scripts are loaded.
7. Expected Results
- The
admin-ajax.phprequest returns a200 OKwith a success status, even though no cookies are sent. - When navigating to the page where the map is rendered, an alert box appearing with
1(ordocument.domain) confirms the Stored XSS.
8. Verification Steps
- DB Check: Use
wp db query "SELECT title, body FROM wp_mappress_maps"(or the appropriate table identified inmappress_db.php) to confirm the payload is stored verbatim. - Log Check: Verify no "Forbidden" or "403" errors occurred during the AJAX POST.
- Render Check: View the source of the page containing the map and look for the raw
<img src=x onerror=alert(1)>inside themappress-mapcomponent or POI list.
9. Alternative Approaches
- REST API: If the AJAX actions are secured but the plugin registered REST routes in
mappress_api.php, checkregister_rest_routefor missingpermission_callbackarguments (or those returning__return_true). - POI List XSS: Some templates render a list of POIs below the map. Check
templates/mashup-modal.phpormappress_template.phpto see if thebodyfield is escaped there. - Map Alignment/Class: In
mappress_map.php, the$classand$alignmentvariables are part of the object. Test if these can be used to break out of the<mappress-map>attributes:map={"class": '"><script>alert(1)</script>'}.
Summary
The MapPress Maps for WordPress plugin is vulnerable to unauthenticated stored Cross-Site Scripting due to a lack of authorization checks in its AJAX saving routines and insufficient output escaping of map attributes. An attacker can submit a malicious map configuration containing JavaScript, which is then executed in the context of any user viewing a page where the map is rendered.
Vulnerable Code
// mappress_map.php line 56 $name = (isset($vars['name']) ? $vars['name'] : 'noname'); // ... // mappress_map.php line 59 return "<div></div>\r\n<mappress-map id={$name} {$atts}>\r\n$pois\r\n</mappress-map>\r\n";
Security Fix
@@ -56,7 +56,7 @@ $name = (isset($vars['name']) ? $vars['name'] : 'noname'); // Extra div forces web component out of phrasing elements like <p> - return "<div></div>\r\n<mappress-map id={$name} {$atts}>\r\n$pois\r\n</mappress-map>\r\n"; + return "<div></div>\r\n<mappress-map id=\"" . esc_attr($name) . "\" {$atts}>\r\n$pois\r\n</mappress-map>\r\n"; }
Exploit Outline
An unauthenticated attacker sends a POST request to admin-ajax.php with the action 'mapp_save' (or similar map-saving action), which is registered for unauthenticated users via wp_ajax_nopriv_ but lacks authorization checks. The attacker includes a 'map' JSON parameter containing a malicious payload in fields like the map 'name' or POI 'body'. When the map is subsequently rendered on a page via the [mappress] shortcode, the plugin's to_html() method in mappress_map.php outputs the unsanitized map ID and attributes directly into the HTML, triggering the stored script in the context of the victim's browser.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.