[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fYJe5i0VjUqma-iC2axgYF2QIHXvTLL1rBq3AGVJtDLs":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":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"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":37},"CVE-2026-3903","modular-connector-cross-site-request-forgery-via-postconfirmoauth","Modular Connector \u003C= 2.5.1 - Cross-Site Request Forgery via postConfirmOauth","The Modular DS: Monitor, update, and backup multiple websites plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 2.5.1. This is due to missing nonce validation on the postConfirmOauth() function. This makes it possible for unauthenticated attackers to disconnect the plugin's OAuth\u002FSSO connection via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.","modular-connector",null,"\u003C=2.5.1","2.6.0","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-03-10 00:00:00","2026-03-11 07:36:25",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F913a94ad-f425-4d24-9e23-7074ecfed8ad?source=api-prod",1,[22,23,24,25,26,27,28,29],"init.php","modular-php\u002Fsrc\u002FModularClient.php","modular-php\u002Fsrc\u002FObjects\u002FBaseObject.php","modular-php\u002Fsrc\u002FServices\u002FAbstractService.php","readme.txt","src\u002Fapp\u002FHttp\u002FControllers\u002FBackupController.php","src\u002Fapp\u002FHttp\u002FControllers\u002FCacheController.php","src\u002Fapp\u002FHttp\u002FControllers\u002FServerController.php","researched",false,3,"This research plan targets a CSRF vulnerability in the Modular Connector plugin, which allows an attacker to disconnect the site from the Modular DS dashboard by tricking an administrator into submitting a forged request to the `postConfirmOauth()` handler.\n\n## 1. Vulnerability Summary\n*   **Vulnerability:** Cross-Site Request Forgery (CSRF)\n*   **Component:** `OauthController::postConfirmOauth()` (Inferred location based on standard plugin architecture and provided controllers).\n*   **Affected Versions:** \u003C= 2.5.1\n*   **Impact:** An attacker can force the WordPress site to disconnect from its management dashboard (Modular DS). This disrupts backups, monitoring, and security scans.\n*   **Root Cause:** The `postConfirmOauth` function, which handles the finalization of the OAuth connection flow, fails to implement WordPress nonce validation (`check_admin_referer` or `check_ajax_referer`).\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php` or `\u002Fwp-admin\u002Fadmin-post.php` (The plugin uses a custom dispatcher).\n*   **Action:** `modular_connector_oauth_confirm` or `modular_connector_confirm_oauth` (Inferred).\n*   **Method:** `POST`\n*   **Authentication:** Requires an active administrator session (Victim).\n*   **Parameters:**\n    *   `action`: The hook registered to reach the dispatcher.\n    *   `route`: `\u002Foauth\u002Fconfirm` (Inferred based on the Laravel-style routing seen in `BackupController.php`).\n\n## 3. Code Flow\n1.  **Entry Point:** An administrator visits a malicious page while logged into the WordPress site.\n2.  **Request Trigger:** The malicious page auto-submits a POST request to `wp-admin\u002Fadmin-ajax.php`.\n3.  **Hook Registration:** `init.php` calls `\\Modular\\Connector\\WordPress\\Admin::setup()`, which registers AJAX or admin-post actions.\n4.  **Routing:** The action maps to a dispatcher that instantiates `Modular\\Connector\\Http\\Controllers\\OauthController`.\n5.  **Vulnerable Sink:** The dispatcher calls `postConfirmOauth()`. Because this function lacks a nonce check, it proceeds to process the \"confirmation\" request.\n6.  **Action Taken:** The function likely attempts to refresh or update the OAuth credentials. If provided with malformed or empty data via CSRF, it fails the handshake and clears the existing valid credentials in `_modular_connection_access_token` and `_modular_connection_client_id` (seen in `ModularClient.php`), effectively disconnecting the site.\n\n## 4. Nonce Acquisition Strategy\nAccording to the vulnerability description, this function is vulnerable specifically because it **misses nonce validation**. Therefore, **no nonce is required** to exploit this vulnerability.\n\n## 5. Exploitation Strategy\n\n### Step 1: Discover exact action and route\nSince the full controller and route files are not provided, the agent must first find the exact action string.\n1.  Search for the method definition: `grep -r \"function postConfirmOauth\" .`\n2.  Search for where this controller\u002Fmethod is routed: `grep -r \"oauth\" .` and look for strings like `add_action` or `Route::post`.\n\n### Step 2: Simulate Connected State\nBefore testing, ensure the plugin is \"connected\" so we can verify the disconnection.\n1.  Set fake connection options:\n    ```bash\n    wp option update _modular_connection_client_id \"fake_client_id\"\n    wp option update _modular_connection_access_token \"fake_access_token\"\n    ```\n\n### Step 3: Execute CSRF\nThe agent will simulate the Admin's browser making the forged request using the `http_request` tool.\n\n**Hypothesized Request (to be refined by discovery):**\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Method:** `POST`\n*   **Body (URL Encoded):**\n    ```\n    action=modular_connector_request&route=\u002Foauth\u002Fconfirm\n    ```\n    *(Note: If discovery shows a different action name like `modular_connector_oauth_confirm`, use that instead).*\n\n### Step 4: Verification\nConfirm that the options have been cleared or modified, indicating a disconnection.\n\n## 6. Test Data Setup\n1.  **Plugin Installation:** Ensure `modular-connector` version 2.5.1 is active.\n2.  **Admin User:** Ensure a standard admin user exists (e.g., `admin`\u002F`password`).\n3.  **Connection Simulation:**\n    ```bash\n    wp option update _modular_connection_client_id \"poc_test_client\"\n    wp option update _modular_connection_access_token \"poc_test_token\"\n    ```\n\n## 7. Expected Results\n*   The `POST` request should return a `200 OK` or `302 Redirect`.\n*   The WordPress options associated with the Modular DS connection should be deleted or set to empty strings.\n*   The response from the server should NOT be a \"403 Forbidden\" or a \"Nonce Verification Failed\" error.\n\n## 8. Verification Steps\n1.  Check the connection options via WP-CLI:\n    ```bash\n    wp option get _modular_connection_client_id\n    wp option get _modular_connection_access_token\n    ```\n2.  **Success Condition:** The commands return an empty value or an error stating the option does not exist, whereas they previously contained \"poc_test_client\" and \"poc_test_token\".\n\n## 9. Alternative Approaches\nIf the `admin-ajax.php` endpoint requires a different routing structure:\n1.  Check if the plugin uses `admin-post.php` actions.\n2.  Check for custom REST API routes: `grep -r \"register_rest_route\" .`\n3.  If the function `postConfirmOauth` requires specific parameters (like a `code` or `state`), try adding dummy values: `&code=123&state=abc`. The goal is to trigger the logic that modifies the connection state without a nonce.","gemini-3-flash-preview","2026-04-18 05:07:48","2026-04-18 05:08:32",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","2.5.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmodular-connector\u002Ftags\u002F2.5.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmodular-connector.2.5.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmodular-connector\u002Ftags\u002F2.6.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmodular-connector.2.6.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmodular-connector\u002Ftags"]