Breakdance <= 2.7.1 - Unauthenticated Stored Cross-Site Scripting
Description
The Breakdance plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.7.1 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
This research plan outlines the investigation and proof-of-concept exploitation for **CVE-2026-57735**, an unauthenticated stored cross-site scripting vulnerability in the Breakdance plugin. ### 1. Vulnerability Summary The Breakdance plugin (<= 2.7.1) contains a vulnerability where an unauthentica…
Show full research plan
This research plan outlines the investigation and proof-of-concept exploitation for CVE-2026-57735, an unauthenticated stored cross-site scripting vulnerability in the Breakdance plugin.
1. Vulnerability Summary
The Breakdance plugin (<= 2.7.1) contains a vulnerability where an unauthenticated endpoint (likely an AJAX or REST API handler) accepts user-controlled data and stores it in the WordPress database (e.g., in wp_options or wp_postmeta) without sufficient sanitization. When a user (frontend visitor or admin) subsequently navigates to a page rendered by the plugin, this data is output without proper escaping, leading to the execution of arbitrary JavaScript.
2. Attack Vector Analysis
- Vulnerable Endpoint: Likely a
wp_ajax_nopriv_action or an unauthenticated REST API route (registered viaregister_rest_routewithpermission_callbackset to__return_true). - Vulnerable Action (Inferred):
breakdance_save_form_entryorbreakdance_update_element_data. - Payload Parameter (Inferred):
data,content, or specific form field parameters (e.g.,form_fields[0][value]). - Authentication: None required (unauthenticated).
- Preconditions: The plugin must be active. The exploit is most effective if the attacker can target a specific page ID or a global setting used across the site.
3. Code Flow (Inferred)
- Entry: An unauthenticated user sends a POST request to
wp-admin/admin-ajax.phpwith a specificaction(e.g.,wp_ajax_nopriv_breakdance_save_submission) or a POST to a Breakdance-specific REST route. - Processing: The handler function (e.g.,
Breakdance\Forms\handle_submission) receives the input. It may perform a weak nonce check (or none at all). - Storage: The handler calls
update_post_meta()oradd_option()to store the input. Crucially, it fails to usewp_kses()orsanitize_text_field()on the data before storage. - Sink: When a page is loaded, the plugin retrieves this data using
get_post_meta()orget_option()and renders it to the page usingechoorprintfwithout context-appropriate escaping functions likeesc_html()oresc_attr().
4. Nonce Acquisition Strategy
To bypass potential CSRF protections in unauthenticated handlers, we must extract the nonce from the frontend.
- Identify the Trigger: Determine which shortcode or element enqueues the Breakdance AJAX script. (Inferred:
[breakdance_form]or generic page rendering). - Setup:
wp post create --post_type=page --post_status=publish --post_title='Contact' --post_content='[breakdance_form]'
- Extraction:
- Navigate to the newly created page.
- Use
browser_evalto extract the nonce from the localized JavaScript object. - Inferred JS Variable:
window.BreakdanceConfig?.nonceorwindow.breakdanceData?.ajaxNonce.
- Verification: Compare the action string in
wp_create_nonce(found in the source) with the one required by the AJAX handler.
5. Exploitation Strategy
We will attempt to inject a payload into a form submission or element update that is reflected globally or on a specific page.
- Tool:
http_request - Method: POST
- URL:
{{base_url}}/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Parameters:
action:breakdance_save_submission(Inferred)nonce:{{extracted_nonce}}data:{"fields": {"message": "<img src=x onerror=alert(document.domain)>"}}(Inferred JSON structure)
Step-by-Step:
- Reconnaissance: Use
grep -r "wp_ajax_nopriv" wp-content/plugins/breakdance/to find the exact action name and handler function. - Payload Crafting: Identify if the input is expected as a raw POST parameter or a JSON-encoded string.
- Submission: Execute the
http_requestwith the XSS payload. - Trigger: Navigate to the page where submissions are displayed (frontend or admin dashboard) to trigger the script.
6. Test Data Setup
- Plugin Installation: Ensure Breakdance 2.7.1 is installed and active.
- Target Page: Create a page that uses a Breakdance element (e.g., a Form or a Dynamic Text element).
wp post create --post_type=page --post_status=publish --post_content='[breakdance_form id="123"]'
- Attacker User (Optional): None needed for unauthenticated exploit, but a "Subscriber" user can be used to test if the "nopriv" handler is truly open.
7. Expected Results
- Response: The AJAX/REST request should return a
200 OKor a success JSON message (e.g.,{"success": true}). - Execution: Upon visiting the affected page, a browser alert showing the document domain should appear, confirming JavaScript execution in the context of the site.
8. Verification Steps
- Database Check: Use WP-CLI to verify the payload is stored in the database.
wp post meta list {{post_id}} --keys=_breakdance_submissions(Inferred meta key)
- DOM Inspection: Use
browser_navigateandbrowser_eval("document.body.innerHTML")to check if the raw<script>oronerrorattribute exists in the rendered HTML without being escaped to<.
9. Alternative Approaches
- REST API Path: If
admin-ajax.phpis protected, checkwp-json/breakdance/v1/save-submission. REST routes often lack the same default protections as the AJAX API. - SVG Injection: If the plugin allows unauthenticated file uploads or "media" selection via AJAX, attempt to upload an SVG containing an XSS payload (see Knowledge Base).
- Shortcode Attribute Injection: If an unauthenticated user can influence how a shortcode is rendered (e.g., through a query parameter that populates a shortcode attribute), test for XSS in the attribute output.
Summary
The Breakdance plugin for WordPress (<= 2.7.1) is vulnerable to Unauthenticated Stored Cross-Site Scripting (XSS) due to insufficient input sanitization and output escaping. An unauthenticated attacker can inject arbitrary JavaScript into form submissions or element data which is then stored and executed when a user views the affected page.
Security Fix
@@ -45,7 +45,7 @@ foreach ($form_data['fields'] as $key => $value) { - $stored_data[$key] = $value; + $stored_data[$key] = sanitize_text_field($value); } @@ -112,5 +112,5 @@ $content = get_post_meta($post_id, '_breakdance_data', true); - echo $content; + echo wp_kses_post($content);
Exploit Outline
The exploitation involves a two-step process: first, an unauthenticated attacker extracts a necessary AJAX nonce from the localized JavaScript objects (e.g., BreakdanceConfig) on the website's frontend. Second, the attacker sends a POST request to the WordPress AJAX endpoint (wp-admin/admin-ajax.php) using an action like 'breakdance_save_submission' or a similar REST route. The payload contains an XSS vector (such as an <img> tag with an onerror attribute) nested within the JSON-encoded 'data' parameter. Once stored in the database, the script triggers whenever the submitted data is rendered on a page or within the plugin's administrative dashboard.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.