Quando ricostruiamo come è stato compromesso un sito WordPress, la risposta più frequente non è un attacco sofisticato. È un plugin con una vulnerabilità nota, corretta da settimane o da mesi, rimasto alla versione vecchia perché nessuno si era accorto che quell’aggiornamento era diverso dagli altri. Il bollettino esisteva, era pubblico, spesso aveva anche un numero CVE. Semplicemente, non era arrivato a chi gestiva il sito.
Un bollettino di sicurezza serve a una cosa sola: accorciare il tempo tra la pubblicazione di una vulnerabilità e il momento in cui il tuo sito smette di esserne esposto. Tutto il resto è contorno.
In questo articolo mettiamo in fila le fonti che usiamo ogni giorno, cioè i database di Wordfence Intelligence, WPScan e Patchstack, il sistema CVE con NVD e CVSS, gli annunci di WordPress.org e il catalogo KEV della CISA, e spieghiamo come leggere un advisory senza farsi ingannare dal punteggio, come incrociare automaticamente un feed con i plugin installati e come evitare che gli avvisi diventino rumore che nessuno legge più.
Da dove nasce un bollettino
Il percorso tipico di una vulnerabilità in un plugin è questo: un ricercatore la trova e la segnala, spesso attraverso il programma di bug bounty di una delle aziende che gestiscono un database; l’azienda verifica la segnalazione, contatta lo sviluppatore e, se serve, il team dei plugin di WordPress.org; lo sviluppatore pubblica una versione corretta; a quel punto la vulnerabilità viene resa pubblica con un identificativo CVE e compare nei database e nei feed. Wordfence, WPScan e Patchstack sono tutti e tre CVE Numbering Authority, cioè enti autorizzati ad assegnare direttamente i numeri CVE, come risulta dalle schede del programma CVE per Wordfence, WPScan e Patchstack.
Questo ha una conseguenza pratica: per l’ecosistema WordPress i database specializzati sono quasi sempre più rapidi e più precisi di quelli generalisti, perché la stessa organizzazione che assegna il CVE ne scrive anche la scheda, con lo slug esatto del plugin e gli intervalli di versione. Le tre fonti si sovrappongono in gran parte ma non del tutto, e capita che una stessa vulnerabilità abbia descrizioni o intervalli di versione leggermente diversi a seconda di chi l’ha pubblicata. Per questo conviene conoscerle tutte.
Wordfence Intelligence, WPScan e Patchstack
Wordfence Intelligence mette a disposizione un database consultabile sul web e un feed JSON completo in due varianti: production, con schede analizzate e complete di CVSS, CWE e rimedio, e scanner, più essenziale e pensata per il confronto automatico. Con la versione 3 dell’API l’accesso richiede una chiave, generata gratuitamente dal proprio account wordfence.com; nell’annuncio del cambiamento Wordfence ha confermato che l’accesso resta gratuito e ha introdotto un limite predefinito di una richiesta ogni trenta minuti, dato che il feed completo pesa oltre cento megabyte. Per un controllo quotidiano è più che sufficiente, a patto di scaricarlo una volta e riutilizzare la copia locale.
WPScan, di proprietà di Automattic, è il database storico dell’ecosistema ed è anche lo strumento a riga di comando che molti conoscono per le scansioni esterne. Secondo la pagina dei piani, l’accesso gratuito all’API è riservato a ricercatori e usi non commerciali, con un tetto di 25 richieste al giorno, mentre l’uso commerciale richiede una licenza a pagamento; gli stessi dati alimentano il plugin Jetpack Protect. L’API v3 risponde per singolo plugin o per singola versione, con un’intestazione Authorization: Token token=…, il che la rende adatta a controlli mirati più che al confronto massivo.
Patchstack pubblica un database consultabile liberamente e gestisce programmi di divulgazione delle vulnerabilità per conto degli sviluppatori. La sua versione gratuita rileva le vulnerabilità nei plugin, nei temi e nel core di un numero limitato di siti, tre secondo la documentazione attuale, e invia avvisi via email; le integrazioni API e la protezione attiva con regole virtuali sono nei piani a pagamento. Molti hosting gestiti integrano Patchstack nei propri pannelli, quindi può darsi che tu riceva già i suoi avvisi senza saperlo.
Le condizioni cambiano nel tempo: prima di costruire un’integrazione, soprattutto se è per clienti e quindi commerciale, conviene rileggere i termini d’uso aggiornati.
CVE, NVD e CVSS: il lessico comune
Il numero CVE è un identificativo, non una valutazione: dice che due fonti stanno parlando della stessa vulnerabilità, niente di più. Il National Vulnerability Database del NIST raccoglie i CVE e li arricchisce con metadati e punteggi, ma per i plugin WordPress è spesso un passo indietro rispetto ai database specializzati, sia nei tempi sia nella precisione degli intervalli di versione. Resta utile come riferimento neutro e come fonte per strumenti generalisti.
Il CVSS è il sistema di punteggio da 0 a 10 che accompagna quasi ogni bollettino. La specifica di FIRST è esplicita: il punteggio base misura la gravità tecnica di una vulnerabilità, non il rischio per un’organizzazione specifica, e chi lo usa dovrebbe integrarlo con le metriche di minaccia e di contesto. Nei bollettini WordPress si trova quasi sempre solo il punteggio base, con il suo vettore, cioè la stringa che spiega come è stato calcolato. Imparare a leggere il vettore è più utile che guardare il numero: AV:N significa sfruttabile dalla rete, PR:N senza alcun privilegio, PR:L con un account di basso livello, UI:R con l’interazione di un utente, per esempio un amministratore che clicca su un link.
Come leggere un bollettino senza farsi ingannare dal punteggio
Un advisory ben scritto risponde a cinque domande, e conviene leggerle in quest’ordine:
- Quale software, esattamente? Lo slug del plugin, non il nome commerciale. Plugin con nomi simili sono frequenti, e le versioni gratuite e premium dello stesso prodotto hanno a volte slug diversi e correzioni pubblicate in date diverse.
- Quali versioni sono vulnerabili? L’intervallo, con attenzione agli estremi: «fino a 3.2.1 inclusa» e «prima della 3.2.1» non sono la stessa cosa.
- Esiste una versione corretta? Se non c’è, l’unica mitigazione è disattivare il plugin o filtrarne gli endpoint, e il bollettino diventa urgente per definizione.
- Serve autenticazione, e di che livello? È la domanda che più spesso ridimensiona o aggrava un punteggio.
- È sfruttata attivamente? Un’informazione che il CVSS base non contiene, e che va cercata altrove.
La quarta domanda merita un esempio. Una stored XSS che richiede un account con ruolo di collaboratore ha di solito un punteggio medio, attorno a 6; su un sito aziendale con due soli amministratori è poco rilevante. Sullo stesso sito, però, se la registrazione è aperta e il ruolo predefinito dei nuovi utenti è stato cambiato per esigenze di un plugin di membership, quella stessa vulnerabilità diventa sfruttabile da chiunque. All’opposto, un 9,8 su un plugin installato ma disattivato è quasi sempre meno urgente di un 7,5 su un plugin attivo che espone un endpoint REST senza autenticazione. Il punteggio è un punto di partenza; il contesto del sito decide la priorità.
WordPress.org, changelog e catalogo KEV
Accanto ai database ci sono tre fonti che completano il quadro. La prima sono gli annunci di sicurezza di WordPress.org per il core: le versioni di manutenzione e sicurezza vengono installate automaticamente per impostazione predefinita, ma solo se gli aggiornamenti automatici non sono stati disattivati, cosa che nei siti che ereditiamo capita più spesso di quanto si pensi.
La seconda è la chiusura dei plugin nella directory ufficiale. Quando un problema di sicurezza viene segnalato, il team dei plugin di WordPress.org di norma chiude il plugin per impedirne nuovi download finché non viene corretto. La pagina del plugin mostra allora un avviso di chiusura, a volte con la motivazione, ma i siti che lo hanno già installato non ricevono alcuna notifica. Un plugin chiuso e mai più aggiornato è un rischio permanente, e un controllo periodico delle pagine dei plugin installati, o degli errori restituiti dall’API di wordpress.org, lo fa emergere.
La terza è il catalogo KEV della CISA, l’agenzia statunitense per la sicurezza delle infrastrutture, che elenca le vulnerabilità di cui è documentato lo sfruttamento attivo ed è disponibile anche in JSON. Contiene poche voci relative a plugin WordPress, perché è orientato a software aziendale e infrastrutturale, ma quando una vulnerabilità del tuo stack compare lì, non c’è discussione sulla priorità. Per i plugin, le informazioni sullo sfruttamento attivo arrivano più spesso dagli articoli dei fornitori di WAF e dai loro rapporti periodici sugli attacchi bloccati, e dai log del tuo stesso server, come spieghiamo nell’articolo sulle vulnerabilità 0-day nei plugin.
Infine, il changelog dello sviluppatore. Molti aggiornamenti di sicurezza sono annunciati con formule generiche come «miglioramenti alla sicurezza», e il diff tra le due versioni, scaricabili entrambe da wordpress.org, dice molto più del testo: un current_user_can() aggiunto in un callback AJAX, un permission_callback che non restituisce più __return_true, un esc_sql() dove prima non c’era. È anche l’unico modo di valutare un aggiornamento prima che esca il bollettino, oppure quando, come negli attacchi alla filiera, è l’aggiornamento stesso a essere il problema.
Incrociare l’inventario dei plugin con un feed
Leggere i bollettini a mano funziona per un sito. Con dieci o cento siti serve un confronto automatico tra ciò che è installato e ciò che è vulnerabile. Il primo ingrediente è l’inventario, che WP-CLI produce in JSON:
# Inventario di plugin e temi, con stato e versione
wp --path=/var/www/esempio.it/public_html plugin list --fields=name,status,version,update_version --format=json > plugin.json
wp --path=/var/www/esempio.it/public_html theme list --fields=name,status,version --format=json > temi.json
# Feed production di Wordfence Intelligence (v3, chiave gratuita): una volta al giorno
curl -sf -H "Authorization: Bearer $WF_API_KEY" \
-o /var/cache/vuln/wordfence.json \
https://www.wordfence.com/api/intelligence/v3/vulnerabilities/production
Il feed è un oggetto JSON in cui ogni vulnerabilità ha un elenco di software, ciascuno con type, slug, gli intervalli affected_versions (con from_version, to_version e i flag di inclusione degli estremi, dove l’asterisco significa «qualunque») e le patched_versions. Il confronto delle versioni è la parte delicata, e conviene affidarlo a PHP, che ha già version_compare() e si trova su qualunque server WordPress:
<?php
// confronta-feed.php — uso: php confronta-feed.php wordfence.json plugin.json
$feed = json_decode( file_get_contents( $argv[1] ), true );
$installati = array_column( json_decode( file_get_contents( $argv[2] ), true ), null, 'name' );
$nel_range = function ( $v, $r ) {
$da = '*' === $r['from_version'] || version_compare( $v, $r['from_version'], $r['from_inclusive'] ? '>=' : '>' );
$a = '*' === $r['to_version'] || version_compare( $v, $r['to_version'], $r['to_inclusive'] ? '<=' : '<' );
return $da && $a;
};
foreach ( $feed as $vuln ) {
foreach ( $vuln['software'] as $sw ) {
$p = $installati[ $sw['slug'] ] ?? null;
if ( 'plugin' !== $sw['type'] || ! $p ) {
continue;
}
foreach ( $sw['affected_versions'] as $r ) {
if ( $nel_range( $p['version'], $r ) ) {
printf( "%s\t%s\t%s\t%s\tCVSS %s\tcorretto in: %s\t%s\n",
$p['status'], $sw['slug'], $p['version'], $vuln['cve'] ?? '-',
$vuln['cvss']['score'] ?? '?',
implode( ',', $sw['patched_versions'] ) ?: 'NESSUNA PATCH',
$vuln['title'] );
break;
}
}
}
}
L’output è una riga per ogni corrispondenza, con lo stato del plugin in prima colonna: un inactive si può rimuovere subito, un active con NESSUNA PATCH richiede una decisione immediata. Lo stesso schema vale per i temi, cambiando il tipo e il file di inventario. Due avvertenze. La prima: i plugin premium non distribuiti da wordpress.org possono avere slug diversi da quelli usati nei database, e vanno verificati a mano la prima volta. La seconda: lo script legge un file che hai scaricato da una fonte esterna, quindi va eseguito da un utente di servizio, non dall’utente del sito e mai come root.
Se preferisci uno strumento già pronto, Wordfence CLI ha un comando di scansione delle vulnerabilità che fa lo stesso confronto sui file del sito, mentre il client wpscan analizza un sito dall’esterno, come farebbe un attaccante, e con un token API riporta le vulnerabilità note dei componenti che riesce a identificare:
# Scansione esterna: rileva plugin e versioni visibili e li confronta con il database WPScan
wpscan --url https://www.esempio.it --api-token "$WPSCAN_API_TOKEN" --enumerate vp,vt --plugins-detection mixed
La scansione esterna vede solo ciò che il sito espone, quindi può mancare plugin che non caricano risorse pubbliche; il confronto interno con l’inventario è più completo. I due controlli sono complementari.
Rumore e segnale: chi avvisare, e quando
Il feed completo di Wordfence contiene decine di migliaia di vulnerabilità, e ogni settimana se ne aggiungono di nuove. Iscriversi a tutto significa smettere di leggere dopo pochi giorni. Il filtro deve essere il tuo inventario, e l’avviso deve arrivare solo quando cambia qualcosa: una nuova corrispondenza, non la stessa ripetuta ogni notte. Basta salvare l’output del giorno prima e inviare la differenza:
php confronta-feed.php /var/cache/vuln/wordfence.json plugin.json | sort > oggi.tsv
comm -13 ieri.tsv oggi.tsv > nuove.tsv
[ -s nuove.tsv ] && mail -s "Nuove vulnerabilità su esempio.it" sicurezza@esempio.it < nuove.tsv
mv oggi.tsv ieri.tsv
Poi viene l’instradamento. Una corrispondenza con un plugin attivo, sfruttabile senza autenticazione e senza patch va a una persona, subito, con un canale che si legge anche fuori orario. Una corrispondenza con patch disponibile e privilegi elevati richiesti può aspettare la finestra di manutenzione della settimana. Un plugin disattivato va semplicemente rimosso. Scrivere queste regole prima dell’emergenza evita di discuterne durante.
Quando il bollettino arriva dopo l’attacco
Aggiornare chiude la porta, ma non dice se qualcuno è già entrato. Ogni volta che un bollettino riguarda un plugin rimasto vulnerabile per giorni, e in particolare se era sfruttabile senza autenticazione, la domanda successiva è se sia stato sfruttato. La scheda di solito indica l’endpoint o il parametro coinvolto, e questo basta per una ricerca mirata nei log di accesso del periodo di esposizione: richieste a quell’azione AJAX, a quella rotta REST, a quel file del plugin. Se i log mostrano tentativi andati a buon fine, o se compaiono file nuovi, amministratori che nessuno ricorda o opzioni modificate, non si tratta più di un aggiornamento ma di un incidente, da gestire come descritto nell’articolo sulle prime due ore.
È qui che i bollettini mostrano il loro limite strutturale: raccontano le vulnerabilità note, non quelle che qualcuno sta già sfruttando senza averle segnalate, e non dicono nulla di ciò che un attaccante ha lasciato sul server dopo essere entrato. Nella nostra pipeline di analisi i feed sono il primo filtro; per i vettori che non corrispondono a nessuna scheda usiamo modelli di intelligenza artificiale eseguiti in locale, come raccontiamo nell’articolo sull’analisi dei log con Qwen e DeepSeek, e poi la ricerca della persistenza a livello di sistema, dai cron ai processi in memoria. Se un bollettino ti ha fatto scoprire di essere stato esposto e i log non ti rassicurano, scrivici: verifichiamo il sito a livello applicativo e di sistema, con una bonifica garantita in 6, 12 o 24 ore per ogni installazione WordPress.