Gutenberg Blocks with AI by Kadence WP – Page Builder Features <= 3.5.32 - Incorrect Authorization to Authenticated (Contributor+) Post Publication
Description
The Gutenberg Blocks with AI by Kadence WP – Page Builder Features plugin for WordPress is vulnerable to unauthorized post publication in all versions up to, and including, 3.5.32 due to a misconfigured capability check on the 'get_items_permission_check' function permission callback of the 'process_pattern' REST API endpoint. This makes it possible for authenticated attackers, with Contributor-level access and above, to create and immediately publish posts of any type (including pages), bypassing the standard WordPress review workflow where contributors must submit posts for administrator approval.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.5.32Source Code
WordPress.org SVNThis research plan outlines the steps to investigate and exploit a vulnerability in the Kadence Blocks plugin (<= 3.5.32) that allows users with Contributor-level access to bypass the review workflow and publish posts or pages directly via the REST API. --- ### 1. Vulnerability Summary * **Vulne…
Show full research plan
This research plan outlines the steps to investigate and exploit a vulnerability in the Kadence Blocks plugin (<= 3.5.32) that allows users with Contributor-level access to bypass the review workflow and publish posts or pages directly via the REST API.
1. Vulnerability Summary
- Vulnerability: Incorrect Authorization to Authenticated (Contributor+) Post Publication.
- Location:
process_patternREST API endpoint in the Kadence Blocks plugin. - Function:
get_items_permission_check(inferred as the permission callback). - Cause: The permission callback for the
process_patternendpoint likely checks for theedit_postscapability (which Contributors possess) but the endpoint logic allows the creation of posts with apublishstatus. In WordPress, Contributors can create and edit their own posts but lack thepublish_postscapability, requiring an Administrator or Editor to approve their work. This endpoint fails to enforce that restriction.
2. Attack Vector Analysis
- Endpoint:
/wp-json/kadence-blocks/v1/process_pattern(inferred namespace and route). - HTTP Method:
POST - Authentication: Authenticated, Contributor-level or higher.
- Payload Parameters:
post_type: The type of post to create (e.g.,post,page).post_status: Set topublish.post_title: The title of the malicious post.post_content: The block content or pattern to be inserted._wpnonce: A valid REST API nonce (action:wp_rest).
3. Code Flow (Inferred)
- Registration: The plugin registers a REST route
kadence-blocks/v1/process_patternusingregister_rest_route. - Permission Check: The
permission_callbackpoints to a function (likelyget_items_permission_check) that performs a check likecurrent_user_can( 'edit_posts' ). - Execution: The
callbackfunction for the route (the "sink") receives the request parameters. It useswp_insert_post()or a similar function to create a post based on user input. - Bypass: Because the permission check passes for Contributors, and the execution logic does not verify if the user has
publish_postsbefore settingpost_statustopublish, the post is created in a published state immediately.
4. Nonce Acquisition Strategy
Since this is a REST API vulnerability requiring Contributor authentication, we need a wp_rest nonce for that specific user session.
- Login: Authenticate as the Contributor user.
- Navigation: Use
browser_navigateto go to the WordPress Dashboard (/wp-admin/). - Extraction: In the WordPress dashboard, the
wp-apiscripts are usually enqueued, exposing the REST nonce in the globalwpApiSettingsobject. - JS Command:
browser_eval("window.wpApiSettings?.nonce") - Alternative: If
wpApiSettingsis not available, look for the nonce in the localized script for Kadence Blocks by checking the page source forkadence_blocks_paramsor similar:browser_eval("window.kadence_blocks_params?.nonce")
5. Exploitation Strategy
Step 1: Discover the Endpoint and Parameters
Confirm the exact route and parameters by searching the plugin source:
grep -rn "register_rest_route" wp-content/plugins/kadence-blocks/ --include="*.php"
Look for the route containing process_pattern. Once found, identify the class and method responsible for the callback.
Step 2: Prepare the Exploit Payload
Construct a JSON payload for the POST request.
- URL:
http://<target>/wp-json/kadence-blocks/v1/process_pattern - Headers:
Content-Type: application/jsonX-WP-Nonce: <extracted_nonce>
- Body:
{ "post_type": "page", "post_title": "Published by Contributor", "post_content": "<!-- wp:paragraph --><p>This page was published without admin approval.</p><!-- /wp:paragraph -->", "post_status": "publish" }
Step 3: Execute the Request
Use the http_request tool to send the payload from the context of the logged-in Contributor.
6. Test Data Setup
- Plugin Installation: Ensure Kadence Blocks <= 3.5.32 is active.
- User Creation: Create a user with the
contributorrole.wp user create attacker attacker@example.com --role=contributor --user_pass=password123
7. Expected Results
- The REST API should return a
200 OKor201 Createdresponse with the details of the new post. - The response should indicate
"status": "publish". - A new page with the specified title should be visible on the frontend of the site without any administrative intervention.
8. Verification Steps
- Check Post Status via CLI:
Confirm that a post authored by the Contributor exists with the statuswp post list --post_type=page --post_status=publish --fields=ID,post_title,post_author,post_statuspublish. - Verify Frontend Accessibility:
Attempt to access the URL of the new post in a logged-out browser state to confirm it is indeed public.
9. Alternative Approaches
- Parameter Variation: If
post_statusis not directly accepted, check if the endpoint accepts atemplate_idorpattern_idthat, when processed, defaults to a published state. - Gaining Access to Other Post Types: Test if
post_typecan be set to sensitive internal types likewp_blockor custom types that might lead to further exploitation (e.g., Stored XSS via block patterns). - REST API Discovery: If the route is not exactly as inferred, use the REST API Index to find it:
# Request the index to find registered routes http_request http://<target>/wp-json/
Summary
The Kadence Blocks plugin allows Contributor-level users to bypass the standard WordPress editorial review workflow and publish posts or pages directly. This occurs because the 'process_pattern' REST API endpoint fails to verify if the user possesses the 'publish_posts' capability before creating a post with a 'publish' status.
Vulnerable Code
// Inferred location based on research plan: includes/class-kadence-blocks-rest-api.php register_rest_route( 'kadence-blocks/v1', '/process_pattern', array( 'methods' => 'POST', 'callback' => array( $this, 'process_pattern' ), 'permission_callback' => array( $this, 'get_items_permission_check' ), ) ); --- // Permission check only verifies the ability to edit posts, not publish them. public function get_items_permission_check( $request ) { return current_user_can( 'edit_posts' ); }
Security Fix
@@ -100,5 +100,8 @@ public function get_items_permission_check( $request ) { - return current_user_can( 'edit_posts' ); + if ( ! current_user_can( 'edit_posts' ) ) { + return false; + } + if ( 'publish' === $request->get_param( 'post_status' ) && ! current_user_can( 'publish_posts' ) ) { + return false; + } + return true; }
Exploit Outline
The exploit involves an authenticated Contributor-level user utilizing the plugin's REST API to create content that would normally require administrative approval. 1. Authenticate to the target site as a user with the 'Contributor' role. 2. Retrieve a valid WordPress REST API nonce from the dashboard (e.g., via the 'wpApiSettings.nonce' JavaScript object). 3. Send a POST request to the endpoint '/wp-json/kadence-blocks/v1/process_pattern'. 4. Construct a JSON payload including 'post_type' (e.g., 'page'), 'post_title', 'post_content', and set 'post_status' to 'publish'. 5. Upon successful execution, the plugin creates the post immediately in a published state, bypassing the mandatory 'Pending Review' status usually enforced for Contributors.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.