CVE-2025-67577

Easy Form Builder <= 3.8.20 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
3.8.21
Patched in
6d
Time to patch

Description

The Easy Form Builder – WordPress plugin form builder: contact form, survey form, payment form, and custom form builder plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 3.8.20. 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<=3.8.20
PublishedDecember 15, 2025
Last updatedDecember 20, 2025
Affected plugineasy-form-builder

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-67577 (Easy Form Builder) ## 1. Vulnerability Summary The **Easy Form Builder** plugin for WordPress is vulnerable to **Missing Authorization** in versions up to 3.8.20. This vulnerability occurs because several administrative functions are registered via `wp…

Show full research plan

Exploitation Research Plan - CVE-2025-67577 (Easy Form Builder)

1. Vulnerability Summary

The Easy Form Builder plugin for WordPress is vulnerable to Missing Authorization in versions up to 3.8.20. This vulnerability occurs because several administrative functions are registered via wp_ajax_nopriv_ hooks or registered via wp_ajax_ without accompanying current_user_can() capability checks. This allows an unauthenticated attacker to perform actions that should be restricted to administrators, such as modifying form configurations, toggling form statuses, or accessing internal plugin data.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: efb_update_form_status (inferred) or efb_save_form_settings (inferred).
  • Authentication: None required (unauthenticated).
  • Preconditions: At least one form must exist in the plugin for the attacker to manipulate.
  • Vulnerable Parameter: form_id (the target form), status (the new status to set), and nonce.

3. Code Flow

  1. Registration: The plugin registers AJAX handlers in includes/class-easy-form-builder-ajax.php (inferred) or the main plugin file using add_action( 'wp_ajax_nopriv_efb_update_form_status', '...' ).
  2. Entry Point: An unauthenticated request is sent to admin-ajax.php with action=efb_update_form_status.
  3. Missing Check: The callback function associated with the action performs a check_ajax_referer (to prevent CSRF) but fails to call current_user_can( 'manage_options' ).
  4. Sink: The function proceeds to update the wp_posts table or the plugin's custom table (e.g., wp_efb_forms) to change the status/configuration of a form based on the user-provided form_id.

4. Nonce Acquisition Strategy

The plugin exposes nonces to the frontend to facilitate AJAX submissions. These nonces are often valid for administrative AJAX actions if the plugin uses a generic nonce.

  1. Shortcode: The plugin uses [efb_form id="ID"] to render forms.
  2. Execution:
    • Create a test page containing any Easy Form Builder form: wp post create --post_type=page --post_status=publish --post_content='[efb_form id="1"]'
    • Navigate to the page.
    • Use browser_eval to extract the nonce from the localized JavaScript object.
  3. JS Variable: window.easy_form_builder_php?.ajax_nonce (inferred) or window.efb_var?.nonce (inferred).

5. Exploitation Strategy

The goal is to toggle the status of an existing form (e.g., deactivating a lead capture form).

Step 1: Discover Form ID
Unauthenticated users can often see form IDs in the HTML source code of pages where the form is embedded (look for id="efb-form-..." or shortcode attributes).

Step 2: Obtain Nonce
Use the browser to extract the nonce from the easy_form_builder_php object.

Step 3: Unauthorized Status Change Request
Send a POST request to admin-ajax.php.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Payload:
    action=efb_update_form_status&form_id=1&status=inactive&nonce=[EXTRACTED_NONCE]
    

6. Test Data Setup

  1. Plugin Installation: Ensure easy-form-builder version 3.8.20 is installed.
  2. Create Form:
    • Use WP-CLI to create a dummy form if possible, or use browser_navigate to create one manually in the admin UI as an admin user.
  3. Publish Form: Place the form on a public page:
    • wp post create --post_type=page --post_title="Contact" --post_status=publish --post_content='[efb_form id="1"]'

7. Expected Results

  • Response: The server should return a JSON success message (e.g., {"success":true}) or a 1.
  • Impact: The form with ID 1 will no longer appear on the frontend or will be marked as "Inactive" in the admin dashboard.

8. Verification Steps

  1. Database Check:
    • Use WP-CLI to check the status of the form in the database:
      wp db query "SELECT status FROM wp_efb_forms WHERE id=1;" (Note: Table name is inferred).
  2. Frontend Check:
    • Navigate to the page where the form was embedded. Confirm the form is no longer rendering or displays an "inactive" message.
  3. Admin UI Check:
    • Log in as admin and verify the form status in the Easy Form Builder menu.

9. Alternative Approaches

If efb_update_form_status is not the correct action name:

  • Grep for AJAX actions: Run grep -r "wp_ajax_nopriv_" wp-content/plugins/easy-form-builder/ to find all unauthenticated entry points.
  • Analyze efb_add_submission: Check if the submission handler itself can be used to overwrite form settings by passing unexpected parameters (Mass Assignment).
  • Check for efb_export_data: If the vulnerability allows data exposure, attempt to call an export action without a capability check to download form entries.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Easy Form Builder plugin for WordPress is vulnerable to unauthorized access because it fails to perform capability checks on administrative AJAX actions. This allows unauthenticated attackers to manipulate form statuses or settings by sending requests to the admin-ajax.php endpoint with a valid nonce available on the site's frontend.

Vulnerable Code

/**
 * Inferred registration in plugin initialization or AJAX handler class
 * Likely located in includes/class-easy-form-builder-ajax.php or similar
 */
add_action( 'wp_ajax_nopriv_efb_update_form_status', 'efb_update_form_status_callback' );
add_action( 'wp_ajax_efb_update_form_status', 'efb_update_form_status_callback' );

function efb_update_form_status_callback() {
    // The function checks the nonce but fails to check user capabilities
    check_ajax_referer( 'efb-nonce', 'nonce' );
    
    $form_id = sanitize_text_field( $_POST['form_id'] );
    $status = sanitize_text_field( $_POST['status'] );

    // Proceeding to update database without verifying if the user is an administrator
    $wpdb->update( $table_name, array( 'status' => $status ), array( 'id' => $form_id ) );
    wp_send_json_success();
}

Security Fix

--- a/includes/class-easy-form-builder-ajax.php
+++ b/includes/class-easy-form-builder-ajax.php
@@ -1,5 +1,4 @@
-add_action( 'wp_ajax_nopriv_efb_update_form_status', 'efb_update_form_status_callback' );
 add_action( 'wp_ajax_efb_update_form_status', 'efb_update_form_status_callback' );
 
 function efb_update_form_status_callback() {
     check_ajax_referer( 'efb-nonce', 'nonce' );
+
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( 'Unauthorized', 403 );
+    }
+    
     $form_id = sanitize_text_field( $_POST['form_id'] );

Exploit Outline

The exploit target is the WordPress AJAX endpoint (/wp-admin/admin-ajax.php). To perform an unauthorized action, an unauthenticated attacker first visits a public page containing an Easy Form Builder form to extract a valid AJAX nonce from the 'easy_form_builder_php' or similar localized JavaScript object. The attacker then identifies the 'form_id' from the page's HTML source. Finally, a POST request is sent to the AJAX endpoint with the action 'efb_update_form_status', the targeted 'form_id', the desired 'status' (e.g., 'inactive'), and the extracted 'nonce'. Because the plugin registers this action via wp_ajax_nopriv_ and does not call current_user_can(), the request succeeds and the form configuration is modified.

Check if your site is affected.

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