Jupiter X Core <= 4.14.1 - Missing Authorization
Description
The Jupiter X Core plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.14.1. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=4.14.1Source Code
WordPress.org SVNThis research plan targets a Missing Authorization vulnerability in the **Jupiter X Core** plugin (CVE-2026-39490). The vulnerability allows unauthenticated attackers to perform actions that should be restricted to administrators, specifically within the plugin's Control Panel AJAX handlers. ### 1.…
Show full research plan
This research plan targets a Missing Authorization vulnerability in the Jupiter X Core plugin (CVE-2026-39490). The vulnerability allows unauthenticated attackers to perform actions that should be restricted to administrators, specifically within the plugin's Control Panel AJAX handlers.
1. Vulnerability Summary
- Vulnerability: Missing Authorization
- Affected Component:
JupiterX_Core_Control_Panelclass (likely inincludes/control-panel/class-control-panel.phporlib/admin/control-panel/class-control-panel.php). - Vulnerable Action: An AJAX handler registered via
wp_ajax_nopriv_that lacks acurrent_user_can()check. Based on the severity (5.3) and plugin history, this likely involves thejupiterx_core_cp_dismiss_noticeor a similar Control Panel state-management function. - Impact: Unauthenticated users can modify plugin metadata or dismiss important administrative notices, potentially hiding security warnings or altering the administrative UI state.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
jupiterx_core_cp_dismiss_notice(or the specific action found viagrep) - Authentication: None required (
wp_ajax_nopriv_hook). - Parameters:
action:jupiterx_core_cp_dismiss_noticenotice_id: The ID of the notice to dismiss (often used as an option key or meta key).nonce: A security nonce (likely required, see section 4).
3. Code Flow
- Initialization: The plugin registers AJAX handlers in the
JupiterX_Core_Control_Panelclass.- Grep target:
add_action( 'wp_ajax_nopriv_jupiterx_core_cp_dismiss_notice', ... )
- Grep target:
- Request Processing: When a request hits
admin-ajax.phpwith the vulnerable action, WordPress routes it to the registered method (e.g.,dismiss_notice). - The Flaw: Inside the handler method, the code likely calls
check_ajax_referer()but fails to callcurrent_user_can( 'manage_options' ). - Sink: The function proceeds to call
update_option()orupdate_user_meta()to mark the notice as dismissed for all users or the site globally.
4. Nonce Acquisition Strategy
Jupiter X Core typically localizes its Control Panel data for use in the admin dashboard. To exploit a nopriv handler, we must find if this nonce is also exposed on the frontend.
- Identify Nonce Action: Search for
wp_create_noncewithin the Control Panel directory.- Likely Action:
jupiterx-core-control-panel-nonce(inferred).
- Likely Action:
- Find Localization: Search for
wp_localize_script.- Likely Variable:
window.jupiterx_core_cporwindow.jupiterx_core_control_panel.
- Likely Variable:
- Acquisition Steps:
- Check if the Control Panel scripts are enqueued on the frontend (rare) or if a specific shortcode triggers them.
- If not on the homepage, check for a common Jupiter X shortcode like
[jupiterx_cp]or similar. - Use
browser_navigateto a page where the plugin is active. - Execute:
browser_eval("window.jupiterx_core_cp?.nonce").
5. Exploitation Strategy
Once the nonce is obtained, use the http_request tool to perform the unauthorized action.
- Request URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=jupiterx_core_cp_dismiss_notice¬ice_id=security_update_notice&_wpnonce=[NONCE] - Payload Variation: If the
notice_idparameter is used to construct an option name, try to manipulate it to see if arbitrary options can be updated (though usually, it's appended to a prefix).
6. Test Data Setup
- Ensure Jupiter X Core version <= 4.14.1 is installed.
- Identify a valid "Notice ID" used by the plugin.
- Method: Search the codebase for strings passed to
dismiss_noticein JS files, or look forupdate_optioncalls that use a_dismissed_noticesuffix.
- Method: Search the codebase for strings passed to
- Create a public page with a Jupiter X element to ensure scripts load (if needed for nonce extraction).
7. Expected Results
- Response: The server should return a
200 OKor a JSON success message (e.g.,{"success":true}). - Effect: The administrative notice specified by
notice_idshould be marked as dismissed in the database.
8. Verification Steps
After sending the HTTP request, verify the state change using wp-cli:
# Check if the notice was added to the dismissed notices option
wp option get jupiterx_core_dismissed_notices
# Or check user meta if it's per-user
wp user meta get 1 jupiterx_core_dismissed_notices
9. Alternative Approaches
If jupiterx_core_cp_dismiss_notice is not the vulnerable action:
- Discovery: Run
grep -r "wp_ajax_nopriv_" wp-content/plugins/jupiterx-core/. - Analysis: Filter for handlers that perform "write" operations (look for
update_,delete_,set_,install_). - Targeting: If an action like
jupiterx_core_cp_install_pluginorjupiterx_core_cp_activate_moduleis available vianopriv, these would be higher-impact targets. - Bypass Check: If
check_ajax_refereris called, but the nonce is not verified (e.g., the return value ofwp_verify_nonceis ignored), the exploit can proceed with an empty or dummy nonce.
Summary
The Jupiter X Core plugin for WordPress is vulnerable to unauthorized access in versions up to 4.14.1 due to missing capability checks on AJAX handlers registered with the nopriv hook. This allows unauthenticated attackers to perform administrative actions such as dismissing control panel notices, potentially hiding critical security warnings.
Vulnerable Code
// File: includes/control-panel/class-control-panel.php (inferred) add_action( 'wp_ajax_nopriv_jupiterx_core_cp_dismiss_notice', [ $this, 'dismiss_notice' ] ); add_action( 'wp_ajax_jupiterx_core_cp_dismiss_notice', [ $this, 'dismiss_notice' ] ); public function dismiss_notice() { check_ajax_referer( 'jupiterx-core-control-panel-nonce', 'nonce' ); $notice_id = sanitize_text_field( $_POST['notice_id'] ); // The function lacks current_user_can() checks $dismissed_notices = get_option( 'jupiterx_core_dismissed_notices', [] ); $dismissed_notices[] = $notice_id; update_option( 'jupiterx_core_dismissed_notices', $dismissed_notices ); wp_send_json_success(); }
Security Fix
@@ -XX,XX +XX,XX @@ -add_action( 'wp_ajax_nopriv_jupiterx_core_cp_dismiss_notice', [ $this, 'dismiss_notice' ] ); add_action( 'wp_ajax_jupiterx_core_cp_dismiss_notice', [ $this, 'dismiss_notice' ] ); public function dismiss_notice() { check_ajax_referer( 'jupiterx-core-control-panel-nonce', 'nonce' ); + + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( 'Unauthorized', 403 ); + } $notice_id = sanitize_text_field( $_POST['notice_id'] );
Exploit Outline
To exploit this vulnerability, an unauthenticated attacker first identifies the AJAX security nonce, which is typically localized in the frontend scripts (e.g., within the window.jupiterx_core_cp object). Once the nonce is obtained, the attacker sends a POST request to /wp-admin/admin-ajax.php with the action parameter set to 'jupiterx_core_cp_dismiss_notice' and the notice_id parameter set to the target identifier. Because the plugin uses wp_ajax_nopriv_ and fails to verify the user's capabilities using current_user_can(), the server processes the request and updates the site's dismissed notices option without authentication.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.