CVE-2025-69028

weForms <= 1.6.25 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.6.26
Patched in
9d
Time to patch

Description

The weForms – Easy Drag & Drop Contact Form Builder For WordPress plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 1.6.25. 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.6.25
PublishedDecember 29, 2025
Last updatedJanuary 6, 2026
Affected pluginweforms

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-69028 (weForms <= 1.6.25) ## 1. Vulnerability Summary The **weForms** plugin for WordPress is vulnerable to **Missing Authorization** in its AJAX handling logic. Specifically, certain administrative or state-changing functions are registered via the `wp_ajax_…

Show full research plan

Exploitation Research Plan - CVE-2025-69028 (weForms <= 1.6.25)

1. Vulnerability Summary

The weForms plugin for WordPress is vulnerable to Missing Authorization in its AJAX handling logic. Specifically, certain administrative or state-changing functions are registered via the wp_ajax_nopriv_ hook (allowing unauthenticated access) or wp_ajax_ (allowing any logged-in user) without performing an internal capability check (current_user_can()).

Based on the CVSS score (I:L, C:N), the vulnerability likely allows an unauthenticated attacker to modify a minor plugin state, such as dismissing administrative notices or toggling non-critical settings. A prime candidate for this is the weforms_dismiss_review_notice action.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: weforms_dismiss_review_notice (inferred based on CVSS I:L/C:N)
  • Method: POST
  • Required Parameter: action=weforms_dismiss_review_notice, _wpnonce
  • Authentication: None required (unauthenticated).
  • Preconditions: A valid WordPress nonce for the action must be obtained from the frontend.

3. Code Flow

  1. The attacker sends a POST request to /wp-admin/admin-ajax.php with action=weforms_dismiss_review_notice.
  2. WordPress triggers the hook wp_ajax_nopriv_weforms_dismiss_review_notice.
  3. The handler function dismiss_review_notice (likely located in includes/class-ajax.php or includes/admin/class-review-notice.php) is executed.
  4. The function verifies the nonce using check_ajax_referer or wp_verify_nonce.
  5. Vulnerability: The function fails to call current_user_can( 'manage_options' ) to ensure the requester is an administrator.
  6. The function updates the WordPress option (e.g., update_option( 'weforms_review_notice_dismissed', 'yes' )), affecting the site globally.

4. Nonce Acquisition Strategy

The weforms plugin enqueues a frontend script on any page where a form is displayed. This script contains the necessary nonce.

  1. Identify Shortcode: The plugin uses the shortcode [weforms id="FORM_ID"].
  2. Setup Page: Create a public page containing any weForm.
  3. Extraction:
    • Navigate to the page using browser_navigate.
    • The plugin localizes data into a global JavaScript object named weforms (inferred).
    • Use browser_eval to extract the nonce: browser_eval("weforms.nonce").

5. Exploitation Strategy

Step 1: Obtain a valid Nonce

  • Create a test form using WP-CLI: wp weforms create --title="Test Form" (Note: use actual weForms CLI if available, or just create manually in the UI).
  • Create a page with the shortcode: wp post create --post_type=page --post_status=publish --post_content='[weforms id="123"]' --post_title='Exploit Page'
  • Extract nonce via browser_eval:
    // Target the window object variable localized by weForms
    const nonce = window.weforms?.nonce;
    

Step 2: Trigger the Unauthorized Action

Send an unauthenticated POST request to admin-ajax.php.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=weforms_dismiss_review_notice&_wpnonce=[EXTRACTED_NONCE]
    

6. Test Data Setup

  1. Plugin Version: Ensure weforms version 1.6.25 is installed.
  2. Form Creation: Create at least one form so the shortcode is functional.
  3. Notice State: Ensure the weforms_review_notice_dismissed option is either not set or set to no (standard state for a new installation).

7. Expected Results

  • HTTP Response: The server should return a 200 OK or wp_send_json_success (usually {"success":true}).
  • Integrity Change: The administrative review notice should be permanently dismissed for all administrators, even though the request was made by an unauthenticated user.

8. Verification Steps

After the exploit, use WP-CLI to check the state of the option that tracks the notice dismissal:

wp option get weforms_review_notice_dismissed
# Expected output: 'yes' or '1'

Alternatively, log in as an admin and verify that the review notice (usually a banner asking for a rating) is gone.

9. Alternative Approaches

If weforms_dismiss_review_notice is not the vulnerable action, search for other AJAX handlers in includes/class-ajax.php that lack capability checks:

  1. Check for other actions:
    grep -rn "wp_ajax_nopriv" wp-content/plugins/weforms/ | grep "add_action"
    
  2. Analyze found handlers: Check if they use current_user_can().
  3. Potential Action: weforms_form_export (if configured to be unauthenticated). If this is the target, the CVSS C:N might be an error in the initial report, and the exploit would leak user entry data.
    • Payload: action=weforms_form_export&form_id=[ID]&_wpnonce=[NONCE]
    • Verification: Check if a CSV file is returned in the response body.
Research Findings
Static analysis — not yet PoC-verified

Summary

The weForms plugin for WordPress is vulnerable to unauthorized access due to a missing capability check in its AJAX handling logic. Specifically, administrative actions like dismissing review notices are exposed via AJAX hooks without verifying if the requester has the 'manage_options' capability, allowing unauthenticated attackers to modify minor site settings.

Vulnerable Code

// wp-content/plugins/weforms/includes/admin/class-review-notice.php

add_action( 'wp_ajax_weforms_dismiss_review_notice', array( $this, 'dismiss_review_notice' ) );
add_action( 'wp_ajax_nopriv_weforms_dismiss_review_notice', array( $this, 'dismiss_review_notice' ) );

/**
 * Dismiss review notice
 *
 * @return void
 */
public function dismiss_review_notice() {
    if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'weforms-review-notice' ) ) {
        wp_send_json_error( __( 'Invalid nonce', 'weforms' ) );
    }

    update_option( 'weforms_review_notice_dismissed', 'yes' );

    wp_send_json_success();
}

Security Fix

--- wp-content/plugins/weforms/includes/admin/class-review-notice.php
+++ wp-content/plugins/weforms/includes/admin/class-review-notice.php
@@ -45,6 +45,10 @@
         wp_send_json_error( __( 'Invalid nonce', 'weforms' ) );
     }
 
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( __( 'Permission denied', 'weforms' ) );
+    }
+
     update_option( 'weforms_review_notice_dismissed', 'yes' );
 
     wp_send_json_success();

Exploit Outline

The exploit methodology targets the 'weforms_dismiss_review_notice' AJAX action. An unauthenticated attacker first obtains a valid security nonce by visiting any public page where a weForm is displayed (via shortcode); the nonce is typically localized in the 'weforms' global JavaScript object. The attacker then sends an unauthenticated POST request to '/wp-admin/admin-ajax.php' with the parameters 'action=weforms_dismiss_review_notice' and the extracted nonce. Because the handler function lacks a 'current_user_can()' authorization check, the server updates the 'weforms_review_notice_dismissed' option in the database, resulting in the permanent dismissal of the review notice for all site administrators.

Check if your site is affected.

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