Master Slider – Responsive Touch Slider <= 3.10.8 - Authenticated (Contributor+) Stored Cross-Site Scripting
Description
The Master Slider – Responsive Touch Slider plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.10.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.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
What Changed in the Fix
Changes introduced in v3.10.9
Source Code
WordPress.org SVN# Vulnerability Research Plan: CVE-2026-48968 (Master Slider Stored XSS) ## 1. Vulnerability Summary The **Master Slider – Responsive Touch Slider** plugin (<= 3.10.8) contains a stored cross-site scripting (XSS) vulnerability via the `[masterslider_pb]` shortcode. The vulnerability exists in the r…
Show full research plan
Vulnerability Research Plan: CVE-2026-48968 (Master Slider Stored XSS)
1. Vulnerability Summary
The Master Slider – Responsive Touch Slider plugin (<= 3.10.8) contains a stored cross-site scripting (XSS) vulnerability via the [masterslider_pb] shortcode. The vulnerability exists in the rendering logic for shortcode attributes, where the title parameter is concatenated into the page output without sanitization or output escaping. Authenticated users with Contributor privileges (who can create/edit posts but do not have unfiltered_html capabilities) can exploit this to execute arbitrary JavaScript in the context of any user (including Administrators) viewing the page.
2. Attack Vector Analysis
- Shortcode Name:
masterslider_pb(registered inincludes/msp-shortcodes.php) - Vulnerable Parameter:
title - Required Authentication: Contributor-level access or higher.
- Preconditions: The attacker must be able to publish a post or have a published post they can edit containing the malicious shortcode.
3. Code Flow
- Hook Registration: In
includes/msp-shortcodes.php, the plugin registers the shortcode:add_shortcode( 'masterslider_pb', 'msp_masterslider_pb_shortcode' ); - Input Processing: When a post is rendered,
msp_masterslider_pb_shortcode($atts, $content)is invoked. - Attribute Extraction: The function uses
shortcode_attsandextractto populate variables:$mixed = shortcode_atts( array( 'id' => '', 'title' => '', 'class' => '' ), $atts, 'masterslider_pb' ); extract( $mixed ); // Populates $title from user-provided shortcode attribute - The Sink (Unescaped Output): The
$titlevariable is passed directly into asprintfcall without usingesc_html()orwp_kses():$the_title_tag = empty( $title ) ? '' : sprintf( '<h2>%s</h2>', $title ); - Rendering: The resulting
$the_title_tagis concatenated into$outputand returned to be rendered on the page.
4. Nonce Acquisition Strategy
While the vulnerability is triggered by viewing a post (which requires no nonce), creating the post as a Contributor via the WordPress web interface requires a standard WordPress post-editing nonce.
- Shortcode Context: The plugin enqueues its assets when a shortcode is present. To find the script localization data (if needed for other endpoints), create a page with
[masterslider_pb]. - Acquiring Post Nonce:
- Navigate to
/wp-admin/post-new.phpas a Contributor. - Use
browser_evalto extract the nonce:document.querySelector('#_wpnonce').value
- Navigate to
- Note on
wp_ajax: The provided source does not show any AJAX handlers requiring nonces for this specific exploit, as the attack relies on the standardedit_postscapability and the[masterslider_pb]shortcode renderer.
5. Exploitation Strategy
Step 1: Authentication
Authenticate as a user with the Contributor role.
Step 2: Payload Construction
Construct a shortcode that breaks out of the <h2> context or simply executes within it.
Payload: [masterslider_pb title='<script>alert(document.domain)</script>']
Step 3: Injection via HTTP Request
Submit a request to create/save a post containing the payload.
- Method: POST
- URL:
http://<target>/wp-admin/post.php - Content-Type:
application/x-www-form-urlencoded - Body Parameters:
action:editpostpost_ID: (The ID of a newly created draft)_wpnonce: (The nonce obtained frompost-new.php)post_title:XSS Testcontent:[masterslider_pb title='<script>alert(document.domain)</script>']post_status:publish(orpendingif Contributor cannot publish)
Step 4: Execution
Navigate to the URL of the created post (e.g., /?p=[ID]). The <h2> tag will be rendered as:
<h2><script>alert(document.domain)</script></h2>
6. Test Data Setup
- User: Create a user
contributor_userwith the rolecontributor. - Plugin: Ensure "Master Slider" is activated.
- Draft Post: Optionally create a draft post via WP-CLI to get a
post_IDfor thehttp_requeststep:wp post create --post_type=post --post_title='Draft' --post_author=$(wp user get contributor_user --field=ID)
7. Expected Results
- When the post is viewed, the browser should trigger an alert box containing the site's domain.
- The raw HTML response should contain the literal string:
<h2><script>alert(document.domain)</script></h2>.
8. Verification Steps
- Check DB: Verify the post content is stored exactly as sent:
wp post get [ID] --field=post_content - Check Output: Use
http_requestto fetch the post and grep for the unescaped payload. - Browser Verification: Use
browser_navigateto the post URL and check for any alert dialogs or console errors.
9. Alternative Approaches
If masterslider_pb is restricted, check the ms_slider shortcode (also in includes/msp-shortcodes.php). Although its output logic was truncated in the source snippet, its huge list of attributes (like class, template_class, inline_style) are often similarly unescaped or insufficiently sanitized. Specifically, check the $output construction in msp_masterslider_wrapper_shortcode.
Summary
The Master Slider plugin for WordPress is vulnerable to Stored Cross-Site Scripting via shortcode attributes, most notably the 'title' parameter in the [masterslider_pb] shortcode. This occurs because the plugin fails to sanitize or escape user-provided attributes before rendering them in an HTML context, allowing contributors to execute arbitrary JavaScript.
Vulnerable Code
// includes/msp-shortcodes.php:32 function msp_masterslider_pb_shortcode( $atts, $content = null ) { $mixed = shortcode_atts( array( 'id' => '', 'title' => '', 'class' => '' ), $atts, 'masterslider_pb' ); extract( $mixed ); $wrapper_open_tag = sprintf( '<div class="avt_masterslider_el %s" >', esc_attr( $class ) ); $the_title_tag = empty( $title ) ? '' : sprintf( '<h2>%s</h2>', $title ); $wrapper_close_tag = '</div>'; $slider_markup = get_masterslider( $id ); $output = $wrapper_open_tag . $the_title_tag . $slider_markup . $wrapper_close_tag; return apply_filters( 'masterslider_pb_shortcode', $output, $slider_markup, $wrapper_open_tag, $the_title_tag, $wrapper_close_tag ); }
Security Fix
@@ -39,7 +39,7 @@ extract( $mixed ); $wrapper_open_tag = sprintf( '<div class="avt_masterslider_el %s" >', esc_attr( $class ) ); - $the_title_tag = empty( $title ) ? '' : sprintf( '<h2>%s</h2>', $title ); + $the_title_tag = empty( $title ) ? '' : sprintf( '<h2>%s</h2>', wp_kses_post( $title ) ); $wrapper_close_tag = '</div>'; $slider_markup = get_masterslider( $id ); $output = $wrapper_open_tag . $the_title_tag . $slider_markup . $wrapper_close_tag; @@ -762,7 +762,7 @@ $slide_content .= "\t".sprintf('<a href="%s" %s %s %s %s %s>%s</a>', $link, $att_link_target, $att_link_rel, $att_link_title, $att_link_class, - $att_link_id, $title )."\n"; + $att_link_id, wp_kses_post( $title ) )."\n"; } // add layers that passed as content @@ -780,7 +780,7 @@ // markup for thumb in tab $tab_image = empty( $tab_thumb ) ? '' : sprintf('<img class="ms-tab-thumb" src="%s" alt="%s" />', msp_get_the_absolute_media_url( $tab_thumb ), esc_attr( $alt ) )."\n"; - $tab_context = empty( $tab ) ? '' : sprintf('<div class="ms-tab-context">%s</div>', str_replace( '"e;', '"', wp_specialchars_decode( $tab ) ), $alt )."\n"; + $tab_context = empty( $tab ) ? '' : sprintf('<div class="ms-tab-context">%s</div>', wp_kses_post( str_replace( '"e;', '"', wp_specialchars_decode( $tab ) ), $alt ))."\n"; // tab markup if( ! empty( $tab_image ) || ! empty( $tab_context ) ) {
Exploit Outline
To exploit this vulnerability, an attacker requires Contributor-level authentication or higher to create or edit a post. The attacker injects a malicious payload into the 'title' parameter of the [masterslider_pb] shortcode (e.g., [masterslider_pb title='<script>alert(1)</script>']). When a user (such as an administrator) views the post, the plugin processes the shortcode and inserts the raw, unescaped payload directly into the page's HTML within an <h2> tag, causing the browser to execute the script.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.