CVE-2026-3885

WP Shortcodes Plugin — Shortcodes Ultimate <= 7.4.9 - Authenticated (Contributor+) Stored Cross-Site Scripting via su_box Shortcode

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

Description

The WP Shortcodes Plugin — Shortcodes Ultimate plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'su_box' shortcode in all versions up to, and including, 7.4.9 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: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<=7.4.9
PublishedApril 15, 2026
Last updatedApril 16, 2026
Affected pluginshortcodes-ultimate

What Changed in the Fix

Changes introduced in v7.5.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps required to demonstrate the Stored Cross-Site Scripting (XSS) vulnerability in the **Shortcodes Ultimate** plugin (version <= 7.4.9). ### 1. Vulnerability Summary The **Shortcodes Ultimate** plugin fails to sanitize or escape user-supplied attributes within the…

Show full research plan

This research plan outlines the steps required to demonstrate the Stored Cross-Site Scripting (XSS) vulnerability in the Shortcodes Ultimate plugin (version <= 7.4.9).

1. Vulnerability Summary

The Shortcodes Ultimate plugin fails to sanitize or escape user-supplied attributes within the [su_box] shortcode. While the plugin provides a variety of shortcodes to enhance page layout, the rendering logic for the "Box" (su_box) shortcode inserts attribute values (specifically the title and potentially others) directly into the HTML output without passing them through WordPress escaping functions like esc_html() or esc_attr(). This allows a user with Contributor permissions or higher to embed malicious JavaScript within a post, which then executes in the context of any user (including Administrators) who views that post.

2. Attack Vector Analysis

  • Vulnerable Shortcode: [su_box]
  • Vulnerable Attribute: title (Inferred as the primary sink for su_box).
  • Authentication Level: Contributor+ (Users who can create or edit posts).
  • Payload Delivery: The payload is stored in the post_content field of the WordPress database via the standard post-editing interface.
  • Target: Administrators or other site visitors viewing the affected post.

3. Code Flow

  1. Input: A Contributor user saves a post containing: [su_box title="<script>alert(1)</script>"]Content[/su_box].
  2. Processing: When the post is rendered (frontend or preview), WordPress calls do_shortcode().
  3. Shortcode Handling: The plugin's registered handler for su_box (typically found in includes/functions-shortcodes.php, referenced by includes/class-shortcodes-ultimate.php's dependency loader) parses the attributes.
  4. Sink: The handler generates HTML for the box. It takes the title attribute and concatenates it into a <div> or <span> header tag.
  5. Output: Because the plugin fails to use esc_html() on the $atts['title'] variable, the raw <script> tag is sent to the browser.

4. Nonce Acquisition Strategy

While the primary exploit (saving a post) uses standard WordPress post nonces, the plugin's "Shortcode Generator" and "Preview" features use plugin-specific nonces. If the PoC agent needs to use the AJAX previewer to demonstrate the XSS:

  1. Identify Script Loading: The Shortcode Generator is enqueued in inc/core/generator.php via Su_Generator::enqueue_assets().
  2. Locate Nonce: The generator UI and AJAX handlers rely on a nonce localized in the WordPress admin head or footer.
  3. Extraction Path:
    • Create a post with any shortcode: wp post create --post_type=post --post_status=publish --post_content='[su_box]test[/su_box]' --post_author=CONTRIBUTOR_ID.
    • Navigate to the Post Edit screen (as Contributor).
    • Use browser_eval to find the localized data.
    • JS Variable: window.SUGL10n?.nonce (Inferred from common naming conventions in this plugin and inc/core/generator.php's use of wp_localize_script).
    • Alternative: The plugin often uses the global ajaxurl and a nonce named su_generator_nonce or simply nonce within the SUGL10n object.

5. Exploitation Strategy

The goal is to inject a script that triggers when an Administrator views the Contributor's post.

Step 1: Inject via Post Creation

  • Action: Create a new post as a Contributor.
  • HTTP Request: http_request (POST to wp-admin/post.php).
  • Payload:
    [su_box title='Box Title<script>alert(document.cookie)</script>']Content[/su_box]
    
  • Parameters:
    • post_title: XSS Test
    • content: [su_box title='<script>alert("XSS")</script>']Box Content[/su_box]
    • action: editpost
    • post_type: post
    • Status: pending (for Review)

Step 2: Trigger via Administrator View

  • Action: Navigate to the post as an Administrator.
  • URL: /?p=POST_ID or /wp-admin/post.php?post=POST_ID&action=edit.

6. Test Data Setup

  1. User Creation:
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Plugin Setup:
    • Ensure Shortcodes Ultimate is active.
  3. Target Content:
    • Create a draft post: wp post create --post_type=post --post_status=draft --post_title="Vulnerable Post" --post_author=attacker.

7. Expected Results

  • The HTTP response when viewing the post as an Administrator should contain the literal string <script>alert("XSS")</script> inside the HTML class or title area of the su_box element.
  • In a browser environment, an alert box should appear showing "XSS" or the document cookies.

8. Verification Steps

  1. DB Check: Use WP-CLI to confirm the payload is stored raw.
    • wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'"
  2. Response Verification:
    • Fetch the post frontend URL using http_request.
    • Regex check the body for: <div class="su-box-title">.*<script>alert (The exact class name su-box-title is inferred based on the plugin's CSS patterns in admin/css/admin.css).

9. Alternative Approaches

If the title attribute is sanitized in version 7.4.9, test other common attributes:

  • Box Color: [su_box title="Title" box_color='"><script>alert(1)</script>'] (Check if used in inline styles).
  • Class Attribute: [su_box title="Title" class='"><script>alert(1)</script>']. Note that includes/functions-helpers.php shows su_get_css_class uses esc_attr, but su_box might implement its own class handling.
  • AJAX Preview Exploit: Use wp_ajax_su_generator_preview to trigger the XSS in the admin dashboard.
    • Endpoint: /wp-admin/admin-ajax.php
    • Data: action=su_generator_preview&shortcode=[su_box title='<script>alert(1)</script>']&nonce=NONCE.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Shortcodes Ultimate plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'su_box' shortcode's title attribute in versions up to 7.4.9. Authenticated attackers with Contributor-level permissions or higher can inject arbitrary JavaScript into posts that will execute in the browser of any user (including administrators) viewing the content.

Vulnerable Code

// In includes/functions-shortcodes.php
function su_shortcode_box( $atts, $content = null ) {
    $atts = shortcode_atts( array(
        'title' => '',
        'style' => 'default',
        'box_color' => '#333333',
        'title_color' => '#FFFFFF',
        'radius' => '3',
        'class' => ''
    ), $atts, 'box' );

    $title = ( $atts['title'] !== '' ) ? '<div class="su-box-title">' . $atts['title'] . '</div>' : '';
    // ... (truncated)

Security Fix

--- a/includes/functions-shortcodes.php
+++ b/includes/functions-shortcodes.php
@@ -254,7 +254,7 @@
 		'class'       => '',
 	), $atts, 'box' );
 
-	$title = ( $atts['title'] !== '' ) ? '<div class="su-box-title">' . $atts['title'] . '</div>' : '';
+	$title = ( $atts['title'] !== '' ) ? '<div class="su-box-title">' . wp_kses_post( $atts['title'] ) . '</div>' : '';
 
 	return '<div class="su-box su-box-style-' . esc_attr( $atts['style'] ) . su_get_css_class( $atts ) . '" style="border-color:' . su_get_darken_color( $atts['box_color'], 10 ) . ';border-radius:' . esc_attr( $atts['radius'] ) . 'px"><div class="su-box-title" style="background-color:' . esc_attr( $atts['box_color'] ) . ';color:' . esc_attr( $atts['title_color'] ) . ';border-top-left-radius:' . ( $atts['radius'] - 1 ) . 'px;border-top-right-radius:' . ( $atts['radius'] - 1 ) . 'px">' . wp_kses_post( $atts['title'] ) . '</div><div class="su-box-content su-u-clearfix su-u-trim" style="border-bottom-left-radius:' . ( $atts['radius'] - 1 ) . 'px;border-bottom-right-radius:' . ( $atts['radius'] - 1 ) . 'px">' . do_shortcode( $content ) . '</div></div>';

Exploit Outline

The exploit involves an authenticated attacker with at least Contributor-level permissions (the ability to create or edit posts) embedding a malicious shortcode payload into a WordPress post. The payload utilizes the `[su_box]` shortcode, specifically targeting the `title` attribute, which is rendered directly into the page without escaping. A typical payload would look like: `[su_box title='<script>alert(document.cookie)</script>']Box Content[/su_box]`. Once the post is saved as a draft or published, the script will execute in the context of any user who views the post in the frontend or previews it in the backend, allowing for session hijacking or other administrative actions if an administrator views the post.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.