CVE-2025-15510

NEX-Forms – Ultimate Forms Plugin for WordPress <= 9.1.8 - Missing Authorization to Unauthenticated Sensitive Information Exposure

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
9.1.9
Patched in
1d
Time to patch

Description

The NEX-Forms – Ultimate Forms Plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the NF5_Export_Forms class constructor in all versions up to, and including, 9.1.8. This makes it possible for unauthenticated attackers to export form configurations, that may include sensitive data, such as email addresses, PayPal API credentials, and third-party integration keys by enumerating the nex_forms_Id parameter.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=9.1.8
PublishedJanuary 30, 2026
Last updatedJanuary 31, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-15510 ## 1. Vulnerability Summary The **NEX-Forms – Ultimate Forms Plugin for WordPress** (<= 9.1.8) contains a missing authorization vulnerability in the `NF5_Export_Forms` class constructor. The plugin fails to verify the requester's capabilities or check f…

Show full research plan

Exploitation Research Plan - CVE-2025-15510

1. Vulnerability Summary

The NEX-Forms – Ultimate Forms Plugin for WordPress (<= 9.1.8) contains a missing authorization vulnerability in the NF5_Export_Forms class constructor. The plugin fails to verify the requester's capabilities or check for valid security nonces before executing the export logic. An unauthenticated attacker can instantiate this class by providing specific HTTP parameters (notably nex_forms_Id), allowing them to download form configurations. These configurations often contain sensitive data, including administrative email addresses, PayPal API credentials, and third-party integration keys.

2. Attack Vector Analysis

  • Vulnerable Class: NF5_Export_Forms
  • Vulnerable Parameter: nex_forms_Id (used to specify the form ID to export).
  • Entry Point (Inferred): Likely triggered via an init or admin_init hook that instantiates NF5_Export_Forms if nex_forms_Id is present in the GET or POST request, or through an unauthenticated AJAX action (wp_ajax_nopriv_...).
  • Authentication: None required (Unauthenticated).
  • Preconditions: At least one form must exist in the NEX-Forms system.

3. Code Flow

  1. Request Initialization: The attacker sends a request to the WordPress site (likely admin-ajax.php or any front-end URL) containing the nex_forms_Id parameter.
  2. Hook Execution: During the WordPress lifecycle (e.g., plugins_loaded or init), the plugin checks for parameters related to form export.
  3. Vulnerable Instantiation: The code likely contains a pattern such as:
    if ( isset( $_GET['nex_forms_Id'] ) && ... ) {
        new NF5_Export_Forms();
    }
    
  4. Constructor Execution: Inside the NF5_Export_Forms::__construct() method, the code retrieves the form data from the database using the provided nex_forms_Id.
  5. Data Sink: The constructor then proceeds to set HTTP headers (e.g., Content-Type: application/json or Content-Disposition: attachment) and echoes the form configuration data before calling die() or exit(), bypassing any subsequent authorization checks that might exist in the UI layer.

4. Nonce Acquisition Strategy

According to the vulnerability description, this is a Missing Authorization issue leading to Unauthenticated Information Exposure. This typically implies that either:

  1. No nonce check is performed at all in the constructor.
  2. The nonce check is bypassable or uses a generic action.

If a nonce is discovered to be required during initial discovery:

  1. Shortcode: NEX-Forms uses the shortcode [nex_forms id="FORM_ID"].
  2. Page Creation: wp post create --post_type=page --post_status=publish --post_content='[nex_forms id="1"]'
  3. Extraction: Navigate to the page and use browser_eval to find localized script data.
    • Search for nex_forms_ajax or nf_logic variables.
    • Example: browser_eval("window.nex_forms_ajax?.nonce")

5. Exploitation Strategy

The goal is to trigger the export of a specific form ID and capture the sensitive configuration JSON.

Step 1: Discovery of Entry Point

Search the plugin files for the string NF5_Export_Forms to find where the class is instantiated.

grep -rn "NF5_Export_Forms" /var/www/html/wp-content/plugins/nex-forms-express-wp-form-builder/

Also, search for where nex_forms_Id is processed:

grep -rn "nex_forms_Id" /var/www/html/wp-content/plugins/nex-forms-express-wp-form-builder/

Step 2: Form Enumeration/Export Request

Based on common NEX-Forms patterns, the export is likely triggered via a GET request.

Payload Template:

GET /?nex_forms_Id=1 HTTP/1.1
Host: target.local

Or via AJAX if a specific action is mapped:

GET /wp-admin/admin-ajax.php?action=nex_forms_export_form&nex_forms_Id=1 HTTP/1.1
Host: target.local

Step 3: Automated Enumeration

If ID 1 works, the agent should iterate from 1 to 20 to discover all form configurations.

6. Test Data Setup

To verify the exposure of sensitive data, the test environment must have a form with "sensitive" fields populated:

  1. Create a Form: Use WP-CLI or the plugin UI to create a NEX-Forms form.
  2. Add Sensitive Settings:
    • Set a "PayPal Email" in the form settings.
    • Add a custom integration key (e.g., Mailchimp API Key) if the plugin version supports it.
  3. Verify Form ID: Identify the ID of the created form (usually 1 for the first form).
# Example (if possible via CLI, otherwise manual UI setup is required)
# NEX-Forms stores forms in custom tables (e.g., wp_nex_forms)
wp db query "INSERT INTO wp_nex_forms (title, form_data) VALUES ('Exploit Test', '{\"paypal_email\":\"attacker-target@example.com\", \"api_key\":\"SECRET_12345\"}');"

7. Expected Results

  • Response Code: 200 OK
  • Response Headers: Likely Content-Type: application/json or text/plain. It might also trigger a file download (Content-Disposition).
  • Response Body: A JSON-encoded string or serialized PHP object containing the full configuration of the form.
  • Evidence: The presence of the string "paypal_email" or the specific API key injected during setup within the response body.

8. Verification Steps

After performing the HTTP request, verify the data leaked matches the database:

  1. Query Database: wp db query "SELECT form_data FROM wp_nex_forms WHERE id = 1;"
  2. Compare: Ensure the JSON returned by the http_request tool matches the form_data stored in the database.
  3. Check Sensitivity: Confirm that fields like paypal_email are indeed present in the leaked output.

9. Alternative Approaches

  • POST Request: If GET fails, attempt the same parameters via POST with Content-Type: application/x-www-form-urlencoded.
  • Action Parameter: If the constructor is inside an AJAX handler, try adding action=nex_forms_export_form or action=export_form to the request.
  • Direct File Access: Check if the export class is instantiated in a file that can be reached directly (though unlikely in modern WP plugins).
  • Search for admin-post.php usage: Check if the plugin uses admin_post_nopriv_... hooks for exports.
Research Findings
Static analysis — not yet PoC-verified

Summary

The NEX-Forms plugin for WordPress fails to implement authorization or nonce checks in its form export class constructor. This allows unauthenticated attackers to trigger a form export by providing a form ID, potentially exposing sensitive data like PayPal API credentials, administrative email addresses, and third-party integration keys.

Vulnerable Code

// nex-forms-express-wp-form-builder/includes/admin/classes/class.export-forms.php

class NF5_Export_Forms {
    public function __construct() {
        // Vulnerability: No check for user capabilities or nonces before processing the request
        if ( isset( $_REQUEST['nex_forms_Id'] ) ) {
            $this->export_form( $_REQUEST['nex_forms_Id'] );
        }
    }

    public function export_form( $form_id ) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'nex_forms';
        $form = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE id = %d", $form_id ) );

        if ( $form ) {
            header( 'Content-Type: application/json' );
            header( 'Content-Disposition: attachment; filename="nex-form-' . $form_id . '.json"' );
            echo json_encode( $form );
            exit;
        }
    }
}

Security Fix

--- a/includes/admin/classes/class.export-forms.php
+++ b/includes/admin/classes/class.export-forms.php
@@ -2,6 +2,9 @@
 class NF5_Export_Forms {
     public function __construct() {
         if ( isset( $_REQUEST['nex_forms_Id'] ) ) {
+            if ( ! current_user_can( 'manage_options' ) ) {
+                wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
+            }
             $this->export_form( $_REQUEST['nex_forms_Id'] );
         }
     }

Exploit Outline

1. Identify a target WordPress site using NEX-Forms version 9.1.8 or lower. 2. Construct a direct HTTP GET request to the site root or admin dashboard containing the vulnerable parameter: `https://example.com/?nex_forms_Id=1`. 3. Observe the response. If the form ID exists, the plugin will set headers for a JSON file download and output the raw database row for that form. 4. To extract all sensitive data, use a script to iterate through numeric IDs (e.g., 1 to 100) for the `nex_forms_Id` parameter. 5. Parse the resulting JSON payloads to locate sensitive configuration keys such as 'paypal_email', 'api_key', or other integration credentials stored within the form configuration.

Check if your site is affected.

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