CVE-2025-14446

Popup Builder <= 1.1.37 - Missing Authorization to Authenticated (Subscriber+) Arbitrary Plugin Settings Reset

mediumMissing Authorization
5.4
CVSS Score
5.4
CVSS Score
medium
Severity
1.1.39
Patched in
105d
Time to patch

Description

The Popup Builder (Easy Notify Lite) plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the easynotify_cp_reset() function in all versions up to, and including, 1.1.37. This makes it possible for authenticated attackers, with Subscriber-level access and above, to reset plugin settings to their default values.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.1.37
PublishedDecember 12, 2025
Last updatedMarch 27, 2026
Affected plugineasy-notify-lite

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

# Research Plan: CVE-2025-14446 - Popup Builder (Easy Notify Lite) Arbitrary Settings Reset ## 1. Vulnerability Summary The **Popup Builder (Easy Notify Lite)** plugin for WordPress is vulnerable to **Missing Authorization** in versions up to and including 1.1.37. The vulnerability exists within th…

Show full research plan

Research Plan: CVE-2025-14446 - Popup Builder (Easy Notify Lite) Arbitrary Settings Reset

1. Vulnerability Summary

The Popup Builder (Easy Notify Lite) plugin for WordPress is vulnerable to Missing Authorization in versions up to and including 1.1.37. The vulnerability exists within the easynotify_cp_reset() function. Because this function is hooked to a broad action (likely admin_init) without a capability check (e.g., current_user_can('manage_options')) or a valid/enforced nonce check, authenticated users with Subscriber-level permissions or higher can trigger the function to reset the plugin's settings to their default values.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin.php or any admin page (e.g., /wp-admin/index.php, /wp-admin/profile.php).
  • Trigger: An HTTP GET or POST request containing a specific trigger parameter (inferred: easynotify_cp_reset or reset).
  • Authentication: Authenticated (Subscriber-level or higher).
  • Preconditions: The plugin must be active. The attacker needs a valid session cookie for a Subscriber user.

3. Code Flow (Inferred)

  1. Hook Registration: The plugin likely registers the reset handler in the main plugin file or an admin controller:
    add_action('admin_init', 'easynotify_cp_reset');
  2. Entry Point: When any authenticated user (including a Subscriber) accesses a page in the /wp-admin/ directory, the admin_init hook fires.
  3. Vulnerable Function: The easynotify_cp_reset() function is executed.
  4. Logic Check: The function checks for the presence of a specific request parameter:
    function easynotify_cp_reset() {
        if ( isset( $_GET['easynotify_cp_reset'] ) ) { // Parameter name (inferred)
            // Missing: if ( ! current_user_can( 'manage_options' ) ) return;
            // Missing: check_admin_referer( 'easynotify_reset_action' );
            
            // Logic to reset settings
            update_option( 'easynotify_options', $default_settings ); 
        }
    }
    
  5. Sink: The update_option or delete_option function is called, overwriting the legitimate configuration with defaults.

4. Nonce Acquisition Strategy

Based on the "Missing Authorization" description, it is highly probable that either:

  1. No nonce check is performed at all.
  2. A nonce is checked but is available to Subscriber-level users in the admin dashboard.

To identify the nonce (if required):

  1. Search the source code for easynotify_cp_reset to see if check_admin_referer or wp_verify_nonce is called.
  2. If a nonce is needed, search for where that nonce is created: wp_create_nonce( '...' ).
  3. If the nonce is created on a page accessible to Subscribers (like the Profile page or the Dashboard), use browser_eval to extract it.

Note: If the function is hooked to admin_init and lacks a capability check, the reset might be triggered simply by appending the parameter to a URL.

5. Exploitation Strategy

The goal is to reset the plugin settings using a Subscriber account.

  1. Log in as Subscriber: Use the http_request tool to obtain a session cookie for a Subscriber user.
  2. Identify Trigger Parameter: Grep the plugin source for the easynotify_cp_reset function definition to find the exact $_GET or $_POST parameter it listens for (e.g., reset, easynotify_reset, easynotify_cp_reset).
  3. Execute Reset: Send a GET request to /wp-admin/ with the trigger parameter.

Payload Example (Inferred):

GET /wp-admin/index.php?easynotify_cp_reset=1 HTTP/1.1
Host: localhost
Cookie: [Subscriber Cookies]

6. Test Data Setup

  1. Install Plugin: Ensure easy-notify-lite version 1.1.37 is installed and active.
  2. Modify Settings: Use WP-CLI to change a plugin setting from its default to a custom value to verify the reset:
    wp option update easynotify_options '{"custom_text":"Vulnerable_State"}' (Note: Option name easynotify_options is inferred and should be verified).
  3. Create Subscriber:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password123

7. Expected Results

  • The server responds with a 200 OK (or a 302 redirect).
  • The plugin's configuration option in the wp_options table is reverted to its default value (or deleted if that is the reset mechanism).
  • Any active notifications/popups configured by the admin disappear or revert to default text/behavior.

8. Verification Steps

After sending the exploit request, verify the database state via WP-CLI:

  1. Check Option Value:
    wp option get easynotify_options
  2. Compare: Confirm the value no longer contains the "Vulnerable_State" string and matches the plugin's default configuration.

9. Alternative Approaches

If the admin_init approach fails:

  • AJAX Handler: Check if the reset is handled via AJAX. Grep for wp_ajax_easynotify_reset. If so, the request would target /wp-admin/admin-ajax.php with the action parameter.
  • Menu Page Bypass: If the reset logic is tied to a specific settings page check (e.g., if ($_GET['page'] == 'easynotify-settings')), the Subscriber can still request admin.php?page=easynotify-settings&reset=1. Even if they see a "Permissions" error, the admin_init logic may execute before the page content is blocked.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Popup Builder (Easy Notify Lite) plugin is vulnerable to unauthorized data modification due to a missing capability check in the easynotify_cp_reset() function. This allows authenticated users with Subscriber-level permissions or higher to reset the plugin's configuration to its default values.

Vulnerable Code

// File: easy-notify-lite.php (or similar admin handler)
// Function likely hooked to admin_init

function easynotify_cp_reset() {
    if ( isset( $_GET['easynotify_cp_reset'] ) ) {
        // Vulnerability: Missing current_user_can() check
        // Vulnerability: Missing nonce verification

        $default_settings = easynotify_get_default_settings();
        update_option( 'easynotify_options', $default_settings );
    }
}

Security Fix

--- a/easy-notify-lite.php
+++ b/easy-notify-lite.php
@@ -10,7 +10,13 @@
 function easynotify_cp_reset() {
-    if ( isset( $_GET['easynotify_cp_reset'] ) ) {
+    if ( isset( $_GET['easynotify_cp_reset'] ) ) {
+        if ( ! current_user_can( 'manage_options' ) ) {
+            wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
+        }
+
+        check_admin_referer( 'easynotify_reset_action', 'easynotify_nonce' );
+
         $default_settings = easynotify_get_default_settings();
         update_option( 'easynotify_options', $default_settings );
     }
 }

Exploit Outline

To exploit this vulnerability, an attacker first authenticates as a Subscriber-level user on the target WordPress site. Since the vulnerable function is hooked to admin_init, it executes whenever an authenticated user accesses the administration dashboard. The attacker sends a GET request to any admin page (e.g., /wp-admin/index.php) appended with the trigger parameter identified in the code (e.g., ?easynotify_cp_reset=1). Because the plugin fails to verify the user's capabilities or check for a security nonce, the backend logic executes the reset routine, overwriting the site's notification and popup settings with the plugin's default configuration.

Check if your site is affected.

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