CVE-2025-68562

MapSVG <= 8.7.3 - Authenticated (Contributor+) Arbitrary File Upload

highUnrestricted Upload of File with Dangerous Type
8.8
CVSS Score
8.8
CVSS Score
high
Severity
8.7.4
Patched in
14d
Time to patch

Description

The MapSVG – Vector maps, Image maps, Google Maps plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in all versions up to, and including, 8.7.3. This makes it possible for authenticated attackers, with Contributor-level access and above, to upload arbitrary files on the affected site's server which may make remote code execution possible.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=8.7.3
PublishedDecember 24, 2025
Last updatedJanuary 6, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2025-68562**, an authenticated arbitrary file upload vulnerability in the **MapSVG** WordPress plugin. As this is a **Contributor+** level vulnerability, the exploitation relies on a failure in the plugin's AJAX/REST handlers to properly verify both user capabilities…

Show full research plan

This research plan targets CVE-2025-68562, an authenticated arbitrary file upload vulnerability in the MapSVG WordPress plugin. As this is a Contributor+ level vulnerability, the exploitation relies on a failure in the plugin's AJAX/REST handlers to properly verify both user capabilities (current_user_can('upload_files')) and the file extension/MIME type.


1. Vulnerability Summary

  • Vulnerability: Authenticated (Contributor+) Arbitrary File Upload.
  • Plugin: MapSVG (slug: mapsvg-lite-interactive-vector-maps).
  • Affected Versions: <= 8.7.3.
  • Root Cause: The plugin registers AJAX actions that handle file uploads for authenticated users but fails to restrict these actions to users with administrative privileges or validate that the uploaded files are restricted to safe types (like SVGs or images).
  • Sinks: move_uploaded_file() or wp_handle_upload() used without a strict mimes filter.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php.
  • Action (Inferred): mapsvg_upload or mapsvg_save. Based on previous MapSVG research, the plugin often uses a generic upload handler for maps and markers.
  • Authentication: Requires a user with at least Contributor role.
  • Preconditions:
    1. The attacker must have valid Contributor credentials.
    2. A valid WordPress nonce associated with the MapSVG AJAX action must be obtained.
    3. The plugin must be active.

3. Code Flow (Inferred)

  1. Entry Point: An AJAX request is sent to admin-ajax.php with action=mapsvg_upload.
  2. Hook Registration: The plugin likely registers the action via:
    add_action('wp_ajax_mapsvg_upload', array($this, 'mapsvg_upload_function'));
  3. Vulnerable Handler: The handler function (likely in an includes/ or matches/ directory) checks for the presence of $_FILES.
  4. Missing Security: The handler likely checks for a nonce but fails to call current_user_can('manage_options').
  5. Sink: The code proceeds to save the file using a path relative to wp-content/uploads/mapsvg/ without validating if the extension is .php.

4. Nonce Acquisition Strategy

MapSVG often localizes its configuration and nonces for the admin dashboard, but these scripts may also be enqueued on the frontend if a map is present.

  1. Identify Shortcode: MapSVG uses the [mapsvg id="..."] shortcode.
  2. Setup Page: Use WP-CLI to create a page containing a map to trigger script enqueuing.
  3. Extract Nonce:
    • Navigate to the newly created page as the Contributor user.
    • Look for the localized JavaScript object. Based on MapSVG structure, this is often mapsvg_vars or mapsvg_options.
    • JS Variable: window.mapsvg_vars?.nonce or window.mapsvg_options?.nonce.

5. Test Data Setup

  1. Create Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Identify/Create Map:
    Ensure at least one MapSVG map exists. If not, create a dummy one via CLI or by checking the database:
    wp post list --post_type=mapsvg
  3. Create Trigger Page:
    Create a page with the MapSVG shortcode to ensure scripts load:
    wp post create --post_type=page --post_status=publish --post_title="Map Page" --post_content='[mapsvg id="1"]' (replace ID with an actual map ID found in step 2).

6. Exploitation Strategy

Step 1: Authentication & Nonce Extraction

  1. Log in as the Contributor user using the browser_navigate and browser_type tools.
  2. Navigate to the page created in the "Test Data Setup".
  3. Execute JavaScript to find the nonce:
    browser_eval("window.mapsvg_vars?.nonce || window.MapSVGDev?.nonce")
  4. Note the nonce value.

Step 2: Identify the Upload Action

Perform a grep on the plugin directory to find the exact AJAX action responsible for uploads:
grep -rn "wp_ajax_mapsvg" /var/www/html/wp-content/plugins/mapsvg-lite-interactive-vector-maps/
Common targets: mapsvg_upload, mapsvg_upload_file.

Step 3: Perform the Upload

Use the http_request tool to send a multipart POST request.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: multipart/form-data
  • Parameters:
    • action: (The action identified in Step 2, e.g., mapsvg_upload)
    • _wpnonce: (The extracted nonce)
    • file: (A PHP shell, e.g., <?php echo "VULNERABLE"; ?>)
    • name: shell.php

Step 4: Locate the Uploaded File

Files are typically uploaded to:
http://localhost:8080/wp-content/uploads/mapsvg/shell.php
Or a subdirectory within uploads/mapsvg/.

7. Expected Results

  • The server returns a 200 OK response, potentially containing a JSON object with the URL of the uploaded file.
  • Accessing the uploaded .php file executes the PHP code.

8. Verification Steps

  1. Verify via CLI: Check if the file exists in the uploads directory:
    ls -la /var/www/html/wp-content/uploads/mapsvg/shell.php
  2. Verify via HTTP: Request the shell and check for the "VULNERABLE" string:
    http_request(url="http://localhost:8080/wp-content/uploads/mapsvg/shell.php")

9. Alternative Approaches

If mapsvg_upload is not the correct action:

  1. Grep for Sinks: grep -rn "move_uploaded_file" . or grep -rn "wp_handle_upload" . to find the exact handler.
  2. Grep for Nonces: grep -rn "wp_create_nonce" . to see which action string is used for the upload nonce (e.g., 'mapsvg-upload-nonce').
  3. Check for REST API: If AJAX isn't used, check register_rest_route for MapSVG endpoints that accept file data.
Research Findings
Static analysis — not yet PoC-verified

Summary

The MapSVG plugin for WordPress (up to version 8.7.3) is vulnerable to arbitrary file uploads because its AJAX handlers fail to perform capability checks or validate file extensions. This allows authenticated users with Contributor-level permissions to upload PHP files, potentially leading to remote code execution.

Vulnerable Code

// Inferred from Research Plan Step 3 and Step 6
add_action('wp_ajax_mapsvg_upload', array($this, 'mapsvg_upload_function'));

public function mapsvg_upload_function() {
    // Handler lacks a call to current_user_can() to verify permissions
    if (isset($_FILES['file'])) {
        $file = $_FILES['file'];
        $upload_overrides = array('test_form' => false);
        // Missing 'mimes' validation in the $upload_overrides array
        $movefile = wp_handle_upload($file, $upload_overrides);
        echo json_encode($movefile);
    }
    wp_die();
}

Security Fix

--- a/mapsvg-lite.php
+++ b/mapsvg-lite.php
@@ -10,6 +10,10 @@
 public function mapsvg_upload_function() {
-    
+    if (!current_user_can('upload_files')) {
+        wp_send_json_error('Unauthorized');
+    }
+
     if (isset($_FILES['file'])) {
-        $upload_overrides = array('test_form' => false);
+        $upload_overrides = array(
+            'test_form' => false,
+            'mimes' => array(
+                'svg' => 'image/svg+xml',
+                'png' => 'image/png',
+                'jpg|jpeg' => 'image/jpeg'
+            )
+        );
         $movefile = wp_handle_upload($file, $upload_overrides);

Exploit Outline

The exploit involves an authenticated attacker with at least Contributor-level access retrieving a security nonce from localized JavaScript variables (e.g., mapsvg_vars) on the WordPress dashboard or a page where a MapSVG map is embedded. The attacker then sends a multipart POST request to /wp-admin/admin-ajax.php using the mapsvg_upload action, including the nonce and a PHP shell as the file payload. Due to the lack of server-side validation, the plugin saves the PHP file into the /wp-content/uploads/mapsvg/ directory, where the attacker can execute it to achieve remote code execution.

Check if your site is affected.

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