Kali Forms <= 2.4.8 - Insecure Direct Object Reference to Authenticated (Contributor+) Sensitive Form Data Exposure
Description
The Kali Forms plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 2.4.8. This is due to the `get_items_permissions_check()` permission callback on the `/kaliforms/v1/forms/{id}` REST API endpoint only checking for the `edit_posts` capability without verifying that the requesting user has ownership or authorization over the specific form resource. This makes it possible for authenticated attackers, with Contributor-level access and above, to read form configuration data belonging to other users (including administrators) by enumerating form IDs. Exposed data includes form field structures, Google reCAPTCHA secret keys (if configured), email notification templates, and server paths.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=2.4.8Source Code
WordPress.org SVN# Research Plan: CVE-2026-1860 - Kali Forms IDOR Sensitive Data Exposure ## 1. Vulnerability Summary The Kali Forms plugin (versions <= 2.4.8) contains an Insecure Direct Object Reference (IDOR) vulnerability within its REST API implementation. Specifically, the endpoint `/wp-json/kaliforms/v1/form…
Show full research plan
Research Plan: CVE-2026-1860 - Kali Forms IDOR Sensitive Data Exposure
1. Vulnerability Summary
The Kali Forms plugin (versions <= 2.4.8) contains an Insecure Direct Object Reference (IDOR) vulnerability within its REST API implementation. Specifically, the endpoint /wp-json/kaliforms/v1/forms/{id} uses a permission callback, get_items_permissions_check(), that only verifies if the current user possesses the edit_posts capability.
In WordPress, the Contributor role and above are granted edit_posts by default. The vulnerability exists because the plugin fails to verify if the requesting user is the owner of the form or possesses administrative privileges before returning the full configuration of a specific form ID. This allows any authenticated user with Contributor-level access to retrieve sensitive configuration data for any form on the system, including those created by administrators.
2. Attack Vector Analysis
- Endpoint:
/wp-json/kaliforms/v1/forms/{id}(where{id}is the numeric ID of a form). - Method:
GET - Authentication: Authenticated (Contributor role or higher).
- Vulnerable Parameter: The
{id}path variable. - Sensitive Data Exposed:
- Form field structures and logic.
- Google reCAPTCHA secret keys.
- Email notification templates (containing internal email addresses and logic).
- Server paths and internal configuration metadata.
- Preconditions: An attacker must have a valid account with at least
Contributorpermissions. At least one form must exist (created by another user, e.g., an Administrator).
3. Code Flow
- Registration: The plugin registers REST routes during the
rest_api_inithook. The route/kaliforms/v1/forms/(?P<id>\d+)is mapped to a controller class (likely a subclass ofWP_REST_Controller). - Permission Check: When a request hits the endpoint, WordPress calls the
permission_callbackdefined for that route. In Kali Forms, this isget_items_permissions_check().- Vulnerable Logic: The function likely contains
return current_user_can( 'edit_posts' );. - Missing Logic: It lacks a check such as
get_post_field( 'post_author', $id ) == get_current_user_id()or a check formanage_options.
- Vulnerable Logic: The function likely contains
- Data Retrieval: Once permissions are "validated," the
get_item()method is called. This method fetches the form object (likely stored as a Custom Post Type or in a custom table) and returns the full configuration array as a JSON response.
4. Nonce Acquisition Strategy
Since this is a REST API exploit requiring authentication, a _wpnonce (specifically for the wp_rest action) is required to bypass WordPress's default REST API CSRF protection for authenticated requests.
- Login: Log in as the Contributor user.
- Navigate to Admin: Access the WordPress Dashboard (
/wp-admin/). - Extract Nonce: WordPress enqueues the
wp-apiscript in the dashboard, which localizes the REST nonce into thewpApiSettingsobject. - Execution Agent Steps:
browser_navigate(URL + "/wp-admin/")REST_NONCE = browser_eval("window.wpApiSettings?.nonce")
- Usage: This nonce must be sent in the
X-WP-NonceHTTP header during the exploit.
5. Exploitation Strategy
- Discovery: Identify target form IDs. Since form IDs are usually sequential integer values, they can be easily enumerated.
- Request Construction: Craft a GET request to the REST API endpoint.
- Payload via
http_request:- Method:
GET - URL:
http://vulnerable-site.com/wp-json/kaliforms/v1/forms/{id} - Headers:
X-WP-Nonce: [EXTRACTED_NONCE]Content-Type: application/jsonCookie: [CONTRIBUTOR_COOKIES]
- Method:
- Looping: If the specific form ID is unknown, iterate from
id=1toid=100.
6. Test Data Setup
To demonstrate the impact, the following setup is required:
- Install Kali Forms <= 2.4.8.
- Administrator Setup:
- Create a form named "Sensitive Admin Form".
- In the form settings, configure a "Secret" value, such as a reCAPTCHA Secret Key (
6LeIxAcTAAAAAGG-vFI1TnRWxMZNF65lSclD5IIJ) or a custom email notification template with a sensitive "To" address (internal-archive@company.local). - Identify the Form ID (e.g., look at the URL when editing the form:
post=123).
- Contributor Setup:
- Create a user with the
Contributorrole. - Do not grant this user any special permissions or ownership over the Administrator's form.
- Create a user with the
7. Expected Results
- The API should return a
200 OKresponse. - The response body will be a JSON object containing the complete configuration of the form.
- Confirmation of Vulnerability: The JSON will contain the
recaptcha_secretor notification email details set by the Administrator, which should be inaccessible to a Contributor.
8. Verification Steps
- Check Response Body: Look for keys like
notifications,settings,recaptcha_v2_secret_key, orrecaptcha_v3_secret_key. - WP-CLI Comparison: Run
wp post get [ID] --format=jsonas an admin to verify the data returned via the API matches the actual stored configuration. - Role Verification: Use
wp user get [USER_ID]to confirm the attacker user only has thecontributorrole.
9. Alternative Approaches
- Endpoint Enumeration: If
/kaliforms/v1/forms/{id}is blocked or changed, check for the collection endpoint/kaliforms/v1/forms. If theget_items()(plural) permission check is also broken, it may leak the entire list of forms and their configs at once. - X-WP-Nonce Bypass: Check if the plugin registered the route without
permission_callbackentirely (unlikely based on the description) or if it uses a custom header for authentication. - Draft Forms: Verify if the IDOR extends to "draft" or "private" forms that haven't been published yet.
Summary
The Kali Forms plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) in versions up to 2.4.8. The plugin's REST API endpoint for retrieving individual form configurations only checks for the 'edit_posts' capability, allowing authenticated users with Contributor-level access or higher to view sensitive form data belonging to other users, including reCAPTCHA secret keys and email templates.
Vulnerable Code
// Inferred from Research Plan and Vulnerability Description // Likely located in includes/api/class-kali-forms-rest-controller.php or similar public function get_items_permissions_check( $request ) { if ( ! current_user_can( 'edit_posts' ) ) { return new WP_Error( 'rest_forbidden', __( 'You do not have permission to view these forms.', 'kali-forms' ), array( 'status' => 401 ) ); } return true; }
Security Fix
@@ -1,5 +1,5 @@ public function get_items_permissions_check( $request ) { - if ( ! current_user_can( 'edit_posts' ) ) { + if ( ! current_user_can( 'manage_options' ) ) { return new WP_Error( 'rest_forbidden', __( 'You do not have permission to view these forms.', 'kali-forms' ), array( 'status' => 401 ) ); }
Exploit Outline
The exploit involves an authenticated attacker with Contributor-level permissions using the WordPress REST API to retrieve sensitive form configurations. First, the attacker logs into the WordPress dashboard and extracts the REST API nonce from the 'wpApiSettings' JavaScript object. Next, the attacker sends a GET request to the '/wp-json/kaliforms/v1/forms/{id}' endpoint, where {id} is the ID of a target form (often discovered through simple integer enumeration). By including the 'X-WP-Nonce' header in the request, the attacker bypasses standard CSRF protections. The server, failing to verify resource ownership or administrative privileges, responds with a JSON object containing the complete form configuration, exposing sensitive data such as Google reCAPTCHA secret keys, server paths, and internal email notification templates.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.