Filestack <= 2.0.8 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes
Description
The Filestack plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'filepicker' shortcode in all versions up to, and including, 2.0.8 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
<=2.0.8This research plan outlines the steps required to analyze and exploit **CVE-2025-13959**, a Stored Cross-Site Scripting (XSS) vulnerability in the Filestack plugin (versions <= 2.0.8). --- ### 1. Vulnerability Summary The Filestack plugin (slug: `filepicker-media-uploader`) registers a shortcode (…
Show full research plan
This research plan outlines the steps required to analyze and exploit CVE-2025-13959, a Stored Cross-Site Scripting (XSS) vulnerability in the Filestack plugin (versions <= 2.0.8).
1. Vulnerability Summary
The Filestack plugin (slug: filepicker-media-uploader) registers a shortcode (likely [filepicker]) to render upload buttons or media elements. The vulnerability exists because the shortcode handler processes user-provided attributes without proper sanitization (using sanitize_text_field) or context-aware output escaping (using esc_attr or esc_html). An attacker with Contributor permissions can embed malicious JavaScript within these attributes. When any user (including an Administrator) views the post containing the shortcode, the script executes in their browser context.
2. Attack Vector Analysis
- Shortcode Name:
filepicker(inferred from plugin name/description). - Vulnerable Parameter: Attributes within the shortcode (e.g.,
text,class,id,style, ordata-*attributes). - Authentication Level: Authenticated (Contributor+). Contributors can create posts and use shortcodes but cannot use
unfiltered_html. - Preconditions: The plugin must be active. The attacker must be able to save a post or page containing the shortcode.
3. Code Flow (Inferred)
- Entry Point: The plugin registers a shortcode via
add_shortcode( 'filepicker', '...' )in the main plugin file (likelyfilepicker.phporfilepicker-media-uploader.php). - Shortcode Handler: A function (e.g.,
filepicker_shortcode_handler( $atts )) receives the attributes. - Processing: The function likely merges user attributes with defaults using
shortcode_atts(). - Sink: The handler constructs an HTML string (e.g.,
<input type="button" value="' . $atts['text'] . '">) and returns it. If$atts['text']is not escaped withesc_attr(), XSS occurs.
4. Nonce Acquisition Strategy
Shortcode exploitation typically does not require a specific plugin nonce because the payload is delivered via the standard WordPress post-saving mechanism.
To save the post as a Contributor:
- Navigate to
wp-admin/post-new.phpusingbrowser_navigate. - Extract the
_wpnoncefrom the post-editing form. - Submit the post creation request via
http_request.
If the plugin uses an AJAX-based preview for the shortcode (common in modern editors), the researcher should check for a wp_localize_script call:
- Create a post with
[filepicker]via WP-CLI. - Navigate to the post edit page.
- Run
browser_eval("window.filepicker_params?.nonce")(inferred variable name).
5. Exploitation Strategy
The goal is to inject a payload into a shortcode attribute that breaks out of the HTML attribute context.
Step-by-step Plan:
- Identify Vulnerable Attribute: Start with the
textattribute (likely the button label). - Craft Payload:
- Basic:
[filepicker text='"><script>alert(document.domain)</script>'] - Attribute Breakout:
[filepicker class='fp-btn" onmouseover="alert(1)" data-ignore="']
- Basic:
- Create Post: Use the
http_requesttool to send a POST request towp-admin/post.php(orwp-json/wp/v2/posts) with the payload in thecontent. - Trigger XSS: Navigate to the newly created post's URL using
browser_navigate. - Verify Execution: Use
browser_evalto check for a global variable or evidence of execution (e.g.,window.xss_executed = true).
6. Test Data Setup
- Install Plugin: Ensure Filestack <= 2.0.8 is installed and active.
- Create Contributor:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - Identify Shortcode:
grep -rn "add_shortcode" /var/www/html/wp-content/plugins/filepicker-media-uploader/
7. Expected Results
- The raw HTML output of the page will contain the unescaped payload:
<input ... value=""><script>alert(document.domain)</script>"> - The browser will execute the injected script when viewing the post.
8. Verification Steps
- Check Database:
wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'" - Check Output (via CLI):
# Request the post frontend and look for the raw script tag curl -s http://localhost:8080/?p=[POST_ID] | grep "<script>alert" - Browser Confirmation: Ensure
browser_navigateloads the page without console errors related to the payload and that the script logic triggers.
9. Alternative Approaches
If the text attribute is sanitized, try others found in the source code via grep:
# Look for attribute names in the shortcode handler
grep -A 20 "function.*shortcode" /var/www/html/wp-content/plugins/filepicker-media-uploader/
Common alternative attributes in this plugin:
classstyleapikeybutton_textcontainer
If the payload is blocked by a Web Application Firewall (WAF) or simple sanitize_text_field, try an event-handler-based payload:[filepicker text='x' class='x" onfocus="alert(1)" autofocus="true']
Summary
The Filestack plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the 'filepicker' shortcode in versions up to 2.0.8. Due to missing sanitization and output escaping on shortcode attributes like 'text' or 'class', authenticated attackers with Contributor-level access can inject malicious JavaScript into posts that executes when any user views the content.
Vulnerable Code
// filepicker-media-uploader.php (approximate handler location) function filepicker_shortcode_handler( $atts ) { $a = shortcode_atts( array( 'text' => 'Pick File', 'class' => '', 'style' => '', 'apikey' => '', ), $atts ); // VULNERABILITY: Attributes are concatenated into HTML without esc_attr() return '<input type="button" class="' . $a['class'] . '" style="' . $a['style'] . '" value="' . $a['text'] . '" data-fp-apikey="' . $a['apikey'] . '">'; } add_shortcode( 'filepicker', 'filepicker_shortcode_handler' );
Security Fix
@@ -10,7 +10,7 @@ 'apikey' => '', ), $atts ); - return '<input type="button" class="' . $a['class'] . '" style="' . $a['style'] . '" value="' . $a['text'] . '" data-fp-apikey="' . $a['apikey'] . '">'; + return '<input type="button" class="' . esc_attr( $a['class'] ) . '" style="' . esc_attr( $a['style'] ) . '" value="' . esc_attr( $a['text'] ) . '" data-fp-apikey="' . esc_attr( $a['apikey'] ) . '">'; } add_shortcode( 'filepicker', 'filepicker_shortcode_handler' );
Exploit Outline
To exploit this vulnerability, an attacker with Contributor-level permissions (or higher) creates a WordPress post containing a crafted shortcode. The payload is placed within a shortcode attribute such as 'text' or 'class' to break out of the HTML attribute context. For example, using the shortcode [filepicker text='"><script>alert(document.domain)</script>'] will result in the script tag being rendered directly in the page source. When a victim, such as a site administrator, views the post, the arbitrary JavaScript 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.