NEX-Forms – Ultimate Forms Plugin for WordPress <= 9.1.8 - Missing Authorization to Unauthenticated Sensitive Information Exposure
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:NTechnical Details
<=9.1.8Source Code
WordPress.org SVN# 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
initoradmin_inithook that instantiatesNF5_Export_Formsifnex_forms_Idis present in theGETorPOSTrequest, 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
- Request Initialization: The attacker sends a request to the WordPress site (likely
admin-ajax.phpor any front-end URL) containing thenex_forms_Idparameter. - Hook Execution: During the WordPress lifecycle (e.g.,
plugins_loadedorinit), the plugin checks for parameters related to form export. - Vulnerable Instantiation: The code likely contains a pattern such as:
if ( isset( $_GET['nex_forms_Id'] ) && ... ) { new NF5_Export_Forms(); } - Constructor Execution: Inside the
NF5_Export_Forms::__construct()method, the code retrieves the form data from the database using the providednex_forms_Id. - Data Sink: The constructor then proceeds to set HTTP headers (e.g.,
Content-Type: application/jsonorContent-Disposition: attachment) andechoes the form configuration data before callingdie()orexit(), 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:
- No nonce check is performed at all in the constructor.
- The nonce check is bypassable or uses a generic action.
If a nonce is discovered to be required during initial discovery:
- Shortcode: NEX-Forms uses the shortcode
[nex_forms id="FORM_ID"]. - Page Creation:
wp post create --post_type=page --post_status=publish --post_content='[nex_forms id="1"]' - Extraction: Navigate to the page and use
browser_evalto find localized script data.- Search for
nex_forms_ajaxornf_logicvariables. - Example:
browser_eval("window.nex_forms_ajax?.nonce")
- Search for
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:
- Create a Form: Use WP-CLI or the plugin UI to create a NEX-Forms form.
- 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.
- Verify Form ID: Identify the ID of the created form (usually
1for 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/jsonortext/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:
- Query Database:
wp db query "SELECT form_data FROM wp_nex_forms WHERE id = 1;" - Compare: Ensure the JSON returned by the
http_requesttool matches theform_datastored in the database. - Check Sensitivity: Confirm that fields like
paypal_emailare indeed present in the leaked output.
9. Alternative Approaches
- POST Request: If
GETfails, attempt the same parameters viaPOSTwithContent-Type: application/x-www-form-urlencoded. - Action Parameter: If the constructor is inside an AJAX handler, try adding
action=nex_forms_export_formoraction=export_formto 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.phpusage: Check if the plugin usesadmin_post_nopriv_...hooks for exports.
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
@@ -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.