
Le difese di cui si parla di più guardano fuori: i tentativi di brute force sulla pagina di login, le falle da chiudere prima che qualcuno le usi, il firewall davanti al sito. Un supply chain attack, un attacco alla catena di fornitura, entra dall’altra parte. Il codice malevolo arriva dallo stesso canale da cui arriva il codice buono, un aggiornamento, un pacchetto scaricato dal fornitore o uno script caricato da un CDN, perché a essere compromesso è chi quel codice lo pubblica.
Chi ne è vittima di solito ha fatto le cose giuste. Ha aggiornato, ha comprato la licenza, ha scaricato dal sito ufficiale. Per questo gli attacchi alla catena di fornitura sono difficili da vedere, e per questo le difese che funzionano sono diverse da quelle contro un attacco che arriva da fuori.
Questa guida mette in fila i casi documentati dal 2017 a oggi, cosa controlla WordPress.org prima di distribuire un aggiornamento e quali difese vedono cosa sul tuo sito. Le fonti sono gli avvisi di chi ha scoperto gli attacchi, i post ufficiali del team che gestisce i plugin su WordPress.org e il codice sorgente di WordPress 7.1, verificati il 1° ottobre 2026. I comportamenti descritti nelle sezioni sugli aggiornamenti e sulle difese li ho provati il 29 settembre in un WordPress 7.1.2 in italiano, con WP-CLI 2.12 e un database MariaDB.
Cos’è un supply chain attack, e cosa non lo è
Un sito WordPress gira su codice scritto da altri: il core, i plugin, il tema, le librerie che questi si portano dietro, gli script che il browser carica da servizi esterni. Ogni fornitore è un anello della catena. Nel 2017 Wordfence, ricostruendo una serie di plugin usati per distribuire spam, descriveva gli attacchi alla catena di fornitura con due esempi che valgono ancora. Qualcuno entra nei sistemi di un’azienda di software e ne infetta il codice, che arriva ai clienti per la via normale. Oppure ruba l’account di uno sviluppatore e lo usa per pubblicare codice malevolo a nome suo.
La definizione lascia fuori un caso che spesso ci finisce dentro, la vulnerabilità. Nel novembre 2018 WP GDPR Compliance, un plugin con oltre 100.000 installazioni, non controllava i permessi in una delle sue azioni AJAX fino alla versione 1.4.2, e chiunque poteva cambiare le impostazioni del sito. Gli attaccanti attivavano la registrazione con il ruolo di amministratore e si iscrivevano. Il codice del fornitore era difettoso, non malevolo, e la cura era aggiornare alla 1.4.3.
Come gli attacchi DDoS e brute force, una vulnerabilità si sfrutta da fuori, e le difese sono quelle di sempre: aggiornare presto, filtrare le richieste. In un supply chain attack il codice malevolo sta dentro l’aggiornamento, e le stesse difese cambiano segno.
I due mondi però si toccano. A giugno 2026 chi ha colpito OptinMonster è entrato nel server del sito di marketing dell’azienda sfruttando una vulnerabilità nota di un plugin, UpdraftPlus. Lì ha trovato la chiave del CDN, e con quella ha modificato lo script che i clienti caricano dai server del fornitore. Per il fornitore era una falla non corretta, per i suoi clienti un attacco alla catena di fornitura. Come si legge un avviso di vulnerabilità, e come si capisce se riguarda il tuo sito, ha una guida in calendario.
Quattro strade per lo stesso ingresso: i casi documentati
I casi che seguono, tutti con una fonte primaria, entrano da quattro strade diverse. Le prime due passano dal repository di WordPress.org, le altre due no, e la differenza pesa quando si arriva alle difese.
Il plugin cambia proprietario
Display Widgets serviva a scegliere su quali pagine mostrare i widget, e lo usavano circa 200.000 siti. Nel 2017 gli autori lo vendettero. Dalla versione 2.6.1, del 30 giugno, un file chiamato geolocation.php permetteva ai nuovi proprietari di pubblicare, modificare e cancellare contenuti su ogni sito che lo usava, e li nascondeva agli utenti collegati: chi gestiva il sito non vedeva lo spam che Google intanto indicizzava. Il plugin fu tolto dalla directory quattro volte e riammesso tre, fino alla rimozione dell’8 settembre. Per ripulire i siti, WordPress.org pubblicò poi una versione 2.7 con il codice della vecchia 2.05.
Tre mesi dopo toccò a Captcha, un plugin con oltre 300.000 installazioni che BestWebSoft aveva ceduto annunciando il cambio di proprietà il 5 settembre 2017. Il 4 dicembre entrò nel repository un aggiornamento che scaricava un pacchetto da un server esterno e lo installava sopra il plugin. Dentro c’era una backdoor che chiunque poteva attivare: apriva una sessione da amministratore con l’utente numero 1 e poi si cancellava, e un secondo scaricamento rimetteva i file puliti, così sul disco non restava traccia. Il team dei plugin di WordPress.org, con Wordfence, preparò la 4.4.5 ripulita e la distribuì con l’aggiornamento automatico, che in un fine settimana la portò su oltre 100.000 siti. Il plugin è chiuso dal 22 dicembre 2017.
Wordfence ricondusse Display Widgets a una campagna più lunga: nove plugin fra il 2013 e il 2017, in qualche caso comprati, più spesso pagati per ospitare codice pubblicitario, tutti legati alla stessa persona dai pagamenti o dai domini da cui arrivava la pubblicità. Nel caso Captcha trovò legami con la stessa rete, senza poter dire chi avesse scritto la backdoor. Allora come oggi, chi usa un plugin non riceve nessun avviso quando cambia il proprietario.
Qualcuno entra nell’account di chi pubblica
Il 23 e 24 giugno 2024 qualcuno è entrato in cinque account di WordPress.org provando combinazioni di nome utente e password rubate su altri siti, e ha pubblicato aggiornamenti malevoli dei plugin che quegli account potevano modificare. Erano Social Warfare, Blaze Widget, Wrapper Link Element, Contact Form 7 Multi-Step Addon e Simply Show Hooks. Il codice aggiunto creava un amministratore, mandava i suoi dati a un server esterno e inseriva nel footer uno script che riempiva il sito di spam. WordPress.org ha sospeso per un periodo i rilasci, ha imposto il cambio di password a tutti gli autori di plugin e dal 1° ottobre 2024 ha reso obbligatoria l’autenticazione a due fattori per chi può pubblicare.
Il caso più recente di questa famiglia è del 28 luglio 2026. Nella versione 10.8.7 di Advanced Responsive Video Embedder, circa 20.000 installazioni, è comparso un file dal nome innocuo, fn-update-check.php. Conteneva una funzione che a ogni richiesta controllava un parametro e, con il valore giusto scritto nel codice, faceva entrare come amministratore, mandando a un server esterno l’indirizzo del sito e il nome dell’utente usato. Secondo Wordfence, che l’ha trovata in meno di due ore, la backdoor era arrivata con ogni probabilità dall’account dello sviluppatore. Il team dei plugin ha chiuso il plugin 26 minuti dopo la segnalazione, e la versione malevola non è mai uscita dall’API degli aggiornamenti: era ancora ferma nell’attesa che da giugno precede ogni rilascio.
Viene compromessa l’infrastruttura del fornitore
I plugin commerciali non passano dal repository. Si scaricano dal sito del fornitore e si aggiornano dai suoi server. Nel luglio 2025 qualcuno ha modificato i pacchetti di Gravity Forms offerti per il download manuale. Erano infetti la 2.9.11.1 scaricata a mano o installata con Composer il 9 e il 10 luglio, e la 2.9.12 scaricata a mano il 10. Chi aveva aggiornato dalla bacheca non era esposto, perché il servizio che gestisce licenze e aggiornamenti automatici non era stato toccato. Il codice aggiunto bloccava gli aggiornamenti successivi, scaricava altro codice e provava a creare un amministratore. Patchstack ha pubblicato il pezzo che contattava gravityapi.org, un dominio registrato l’8 luglio che imita quello vero, gravityapi.com. I file che scriveva prendevano la data del file index.php della cartella dei plugin, per non comparire fra quelli modificati di recente. Se n’è accorto chi l’ha segnalato a Patchstack, perché il suo monitoraggio vedeva una richiesta lentissima verso quel dominio. La versione pulita è la 2.9.13.
Nel giugno 2026 è venuto fuori il caso di ShapedPlugin, che distribuisce versioni gratuite dei suoi plugin su WordPress.org e versioni Pro dal proprio sito. Secondo Wordfence qualcuno è entrato nella catena di build del fornitore e ha iniettato un caricatore nelle versioni Pro distribuite dal canale di aggiornamento ufficiale, quello che il cliente usa con la licenza. Le versioni gratuite del repository erano pulite. Il caricatore installava un plugin finto, con un nome quasi uguale a quello di WooCommerce Subscriptions, che si toglieva dall’elenco dei plugin, registrava le password inserite al login e rubava i segreti della 2FA di quattro plugin diffusi. Con quei segreti in mano, cambiare la password non basta a chiudere fuori chi è entrato.
Wordfence sottolinea che chi è stato colpito aveva fatto quello che si raccomanda: licenza regolare e aggiornamenti dal sistema ufficiale del fornitore.
Il codice arriva mentre il sito è in funzione
Non tutto il codice di un sito sta sul suo disco. Il 12 giugno 2026, per alcune ore, lo script che OptinMonster e TrustPulse fanno caricare dal loro CDN è stato sostituito da uno modificato, e lo stesso è successo a PushEngage, dello stesso gruppo. Secondo Sansec, che l’ha scoperto, i siti che usano quei plugin sono più di 1,2 milioni. Il codice partiva solo se la pagina era aperta da un amministratore collegato: creava un amministratore nascosto, installava un plugin che si nascondeva dalla bacheca e mandava le credenziali a un dominio che imitava quello di un servizio di chat. L’ingresso era il sito di marketing con il plugin non aggiornato, e la chiave del CDN salvata su quel server.
Ad agosto 2026 lo stesso schema è arrivato senza toccare un solo file. Sette plugin di BdThemes, tutti nel repository, leggevano da un archivio online del fornitore i dati dei banner promozionali mostrati in bacheca, e li inserivano nella pagina senza pulirli. Qualcuno ha ottenuto l’accesso in scrittura a quell’archivio e ha sostituito i dati con codice che partiva a ogni pagina della bacheca aperta da un amministratore. Creava amministratori, installava un plugin con una webshell e lasciava due mu-plugin con la data di mesi prima, uno dei quali toglieva dall’elenco degli utenti gli account creati.
Per diventare vittima non serviva nessun aggiornamento, e un controllo che confronta i file non aveva niente da trovare. Wordfence lo collega agli stessi autori di ARVE e di OptinMonster.
| Caso | Quando | Portata | Da dove è entrato il codice | Cosa faceva |
|---|---|---|---|---|
| Display Widgets | giugno-settembre 2017 | circa 200.000 siti | aggiornamenti pubblicati dai nuovi proprietari | pubblicava spam nascosto agli utenti collegati |
| Captcha | dicembre 2017 | oltre 300.000 siti | aggiornamento dei nuovi proprietari, con un pacchetto preso da un server esterno | accesso da amministratore senza password |
| Cinque plugin del repository | giugno 2024 | 5 plugin | account di chi pubblica, con password rubate altrove | nuovo amministratore e spam nel footer |
| Gravity Forms | luglio 2025 | pacchetti scaricati il 9 e 10 luglio | download manuali e Composer dal sito del fornitore | bloccava gli aggiornamenti, scaricava altro codice, creava un amministratore |
| ShapedPlugin | maggio-giugno 2026 | versioni Pro | canale di aggiornamento del fornitore | plugin finto nascosto, furto di password e segreti della 2FA |
| OptinMonster, TrustPulse, PushEngage | giugno 2026 | oltre 1,2 milioni di siti che li usano | script servito dal CDN del fornitore | amministratore e plugin nascosti, solo con un amministratore collegato |
| Advanced Responsive Video Embedder | luglio 2026 | circa 20.000 installazioni | account di chi pubblica, secondo Wordfence | accesso da amministratore con un valore fisso; mai distribuito |
| BdThemes | agosto 2026 | 7 plugin del repository | dati remoti letti dal plugin in bacheca | amministratori nascosti e mu-plugin, nessun file del plugin modificato |
Metà dei casi della tabella sono del 2026, e in tre di quei quattro il codice malevolo non è passato da un rilascio del repository.
Cosa controlla WordPress.org prima che un aggiornamento arrivi
Dal giugno 2024 il repository ha aggiunto un controllo dopo l’altro, e oggi un aggiornamento passa da parecchi filtri prima di arrivare a un sito. Alcuni riguardano chi pubblica, altri il rilascio.
| Da quando | Cosa | Per chi |
|---|---|---|
| aprile 2021 | Release Confirmation: ogni nuova versione va confermata da un committer con un link ricevuto per email, e si può chiedere che la confermino in due | facoltativa, per i plugin che la attivano |
| maggio 2023 | autenticazione a due fattori sugli account di WordPress.org | facoltativa |
| settembre-ottobre 2024 | password SVN separate da quella dell’account; dal 1° ottobre 2FA obbligatoria per chi può pubblicare plugin e temi | tutti gli owner e i committer |
| agosto 2025 | rilascio graduale: gli aggiornamenti automatici della nuova versione partono 24 ore dopo | facoltativo, per chi usa la Release Confirmation (lo rispettano i siti da WordPress 6.6) |
| 27 ottobre 2025 | Plugin Check su ogni aggiornamento, con i risultati al team | tutti i plugin |
| 5 giugno 2026 | un’attesa prima della distribuzione, oggi di 6 ore, che vale anche per l’aggiornamento con un clic dalla bacheca | tutti i plugin e i temi |
| 9 settembre 2026 | revisione automatica di ogni rilascio, con più modelli di AI e Jetpack Scan: quelli ad alto rischio si bloccano da soli | tutti i plugin |
Il caso ARVE mostra come i pezzi lavorano insieme. La versione malevola è stata trovata e chiusa mentre era ancora nell’attesa, e nessun sito l’ha ricevuta dall’API. Nel post che annuncia la revisione automatica il team scrive che quell’episodio ha mostrato il pezzo mancante: un blocco che scatti da solo, senza dipendere da qualcuno del team disponibile in quel momento. Il rilascio graduale e il Plugin Check sugli aggiornamenti sono descritti in due post del 2025.
Tutto questo vale per una sola delle quattro strade. I plugin commerciali si aggiornano dai server dei fornitori, come Gravity Forms e ShapedPlugin; gli script arrivano dai loro CDN, come nel caso OptinMonster; i dati remoti non passano da nessun rilascio, come nel caso BdThemes. La revisione, scrive il team, misura il rischio e non l’intenzione, e i falsi positivi sono pochi ma non zero.
C’è anche un controllo che WordPress non fa più. Dalla 5.2 il core chiedeva di verificare la firma dei pacchetti di aggiornamento, in una modalità che al massimo mostrava un avviso. Dalla 6.6, uscita a luglio 2024, la verifica è spenta per core, plugin e temi, “almeno finché la firma del software non sarà pienamente implementata su wordpress.org”. Oggi l’integrità di un aggiornamento dipende dalla connessione cifrata con WordPress.org e da chi ha le credenziali per pubblicarlo, ed è per questo che i controlli della tabella stanno tutti sugli account e sui rilasci.
Aggiornamenti automatici: portano l’attacco e anche la cura
Il canale degli aggiornamenti porta in tutte e due le direzioni. A dicembre 2017 ha portato la backdoor di Captcha, e meno di due settimane dopo la versione ripulita su oltre 100.000 siti. A giugno 2024 ha portato gli aggiornamenti malevoli dei cinque plugin, e poi le versioni corrette pubblicate dal team. Con Gravity Forms, nel 2025, chi aggiornava dalla bacheca non è stato esposto, e chi scaricava lo zip a mano sì. WordPress.org ha due leve su questo canale, e il core le rispetta. Nel codice di WordPress 7.1 un’offerta di aggiornamento può arrivare con il flag autoupdate, che la fa installare anche dove l’aggiornamento automatico di quel plugin è disabilitato: è la leva che permette al team di spingere una versione. Oppure con disable_autoupdate, che la sospende, ed è il meccanismo del rilascio graduale. Tutte e due vengono prima della scelta del sito, e dopo tutte c’è un filtro, auto_update_plugin, che ha l’ultima parola (WP_Automatic_Updater::should_update()).
Ho provato le combinazioni su WordPress 7.1.2, chiamando quella funzione su un’offerta di aggiornamento costruita a mano per un plugin installato.
| Situazione | Si aggiorna da solo |
|---|---|
| Offerta normale, aggiornamenti automatici del plugin disabilitati | No |
| Offerta normale, aggiornamenti automatici del plugin abilitati | Sì |
Offerta con autoupdate, aggiornamenti automatici del plugin disabilitati | Sì |
Offerta con autoupdate e il filtro auto_update_plugin a false | No |
Offerta con autoupdate e il filtro plugins_auto_update_enabled a false | Sì |
Offerta con disable_autoupdate, aggiornamenti automatici del plugin abilitati | No |
La terza e la quarta riga sono quelle da ricordare.
Il link “Disabilita gli aggiornamenti automatici” della schermata Plugin toglie il plugin dagli aggiornamenti normali e lascia passare quelli forzati. Il filtro spegne anche quelli, qualunque cosa si scelga nella schermata:
add_filter( 'auto_update_plugin', '__return_false' );
Se quella riga sta nel tema o in un mu-plugin del tuo sito, il canale da cui nel 2017 è arrivata la versione ripulita di Captcha è chiuso. Il primo comando dice se qualcosa si è agganciato al filtro (risponde bool(true) o bool(false)), il secondo dove cercarlo. Nella cartella dei plugin il filtro può comparire per motivi legittimi, per esempio nei plugin che gestiscono gli aggiornamenti.
wp eval 'var_dump( has_filter( "auto_update_plugin" ) );' grep -rn "auto_update_plugin" wp-content/themes wp-content/mu-plugins
Il filtro plugins_auto_update_enabled fa un’altra cosa: toglie dalla schermata la colonna “Aggiornamenti automatici”, ma lascia passare le offerte forzate. Per un plugin che non vuoi aggiornare da solo, la strada resta il link del singolo plugin. Il criterio con cui scelgo quali aggiornamenti automatici tenere accesi è nella guida alla manutenzione, e i controlli da fare prima e dopo ogni aggiornamento in quella dedicata.
Un’ultima cosa sul ripristino automatico arrivato con la 6.6. Dopo l’aggiornamento automatico di un plugin WordPress apre la home del sito e, se trova un errore fatale, rimette la versione precedente. Guarda solo gli errori fatali, e una backdoor è scritta apposta per non causarne nessuno.
I segnali che si vedono prima, e quelli che WordPress non mostra
Il cambio di proprietario non arriva con un avviso. Sulla scheda di un plugin nel repository, il nome sotto il titolo dal febbraio 2025 è quello del profilo WordPress.org del proprietario, non più un testo scelto dallo sviluppatore. Se quel nome cambia, il plugin può essere passato di mano, e conviene capire perché. È un controllo da fare prima di installare un plugin che non si conosce, e da ripetere sui plugin già installati a ogni giro di manutenzione ordinaria, insieme alla data dell’ultimo aggiornamento.
La chiusura si vede, ma non dalla bacheca. Quando WordPress.org chiude un plugin, la sua scheda mostra la data e il motivo, per esempio “Security Issue”; il sito che lo ha installato smette di ricevere aggiornamenti e basta, perché nel codice di WordPress 7.1 non c’è niente che segnali un plugin chiuso. Non ogni chiusura vuol dire codice malevolo: secondo la guida ufficiale i plugin con una segnalazione di sicurezza vengono in genere chiusi finché il problema non è risolto. Ogni chiusura però va capita. Wordfence la segnala da solo, e nella sua scansione un plugin rimosso dal repository è un problema critico.
L’abbandono si misura in due modi. La scheda del repository mostra un avviso quando il plugin non è stato testato con le ultime tre versioni maggiori di WordPress, e Wordfence considera abbandonato un plugin fermo da più di due anni. Nessuna delle due dice che il plugin è pericoloso. Dicono che nessuno lo sta seguendo, e che quindi nessuno si accorgerebbe per primo di un problema.
In Display Widgets come in Gravity Forms, il primo segnale è stato una richiesta verso un server che prima non c’era. Display Widgets fu segnalato la prima volta perché aveva cominciato a scaricare un database di geolocalizzazione da 38 MB dal server dei nuovi autori; la backdoor di Gravity Forms è saltata fuori da una richiesta troppo lenta. Sul tuo sito, le richieste fatte con le funzioni HTTP di WordPress durante una pagina si leggono in Query Monitor, con il componente che le ha fatte.
Le difese sul sito, e cosa vede ciascuna
Nessuna difesa copre tutte e quattro le strade. Prima di contarci conviene sapere cosa lascia scoperto ciascuna.
| Difesa | Cosa copre | Cosa lascia scoperto |
|---|---|---|
Confronto dei file con il repository (Wordfence, wp plugin verify-checksums) | un file cambiato sul disco in un plugin o tema del repository | una versione malevola pubblicata nel repository, che per il confronto è l’originale; i plugin commerciali |
| Scanner a firme | il codice malevolo già catalogato | quello nuovo; nella versione gratuita di Wordfence regole e firme arrivano 30 giorni dopo |
| Avvisi sulle vulnerabilità (Patchstack, Wordfence) | le versioni segnalate, comprese quelle malevole | quello che nessuno ha ancora segnalato |
| Blocco delle richieste in uscita | le chiamate del server fatte con le funzioni HTTP di WordPress | cURL usato direttamente, e tutto quello che fa il browser |
| Disco e database letti dal server | tutto quello che c’è, anche ciò che la bacheca nasconde | niente, ma bisogna sapere cosa cercare |
| Account da amministratore usato solo quando serve | riduce le occasioni per il codice che parte solo con un amministratore collegato | il resto |
Il confronto con il repository è il più preciso, e il più frainteso. Con WP-CLI si lancia con wp plugin verify-checksums --all. Nella prova, su un plugin intatto ha risposto “Success: Verified 1 of 1 plugins.”, e dopo una riga aggiunta in fondo al file principale ha risposto con un errore e il nome del file (“Checksum does not match”). Un plugin che nel repository non c’è viene saltato, e il comando lanciato solo su quello chiude con “Success: Verified 0 of 1 plugins (1 skipped)”, un successo che non ha verificato niente. I checksum, poi, sono quelli della versione pubblicata. Una backdoor messa nella versione ufficiale, come nei cinque plugin del 2024, li supera, e lo stesso vale per la scansione di Wordfence, che confronta i file con le stesse versioni. Per le modifiche fatte sul disco dopo l’installazione resta il controllo migliore.
Gli scanner a firme e gli avvisi sulle vulnerabilità arrivano dopo: servono a sapere presto. A giugno 2024 Wordfence avvisava i suoi utenti delle versioni malevole attraverso il controllo delle vulnerabilità. Nel caso ARVE la regola del firewall è arrivata ai clienti Premium il 28 luglio 2026 e agli utenti della versione gratuita il 27 agosto, i 30 giorni di ritardo che il readme di Wordfence dichiara. Quale plugin di sicurezza scegliere lo racconto nel confronto fra cinque plugin di sicurezza.
Il blocco delle richieste in uscita è una difesa del core, e ferma proprio il tipo di chiamata usata nel caso Gravity Forms, dove la backdoor contattava gravityapi.org con wp_remote_post(). Con due costanti in wp-config.php WordPress rifiuta ogni richiesta fatta con le sue funzioni HTTP verso indirizzi diversi dal sito stesso e da quelli elencati:
// In wp-config.php, sopra la riga che carica wp-settings.php define( 'WP_HTTP_BLOCK_EXTERNAL', true ); define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,downloads.wordpress.org' );
Nella prova, con quei due indirizzi in elenco, una wp_remote_post() verso un altro dominio è tornata con l’errore “L’utente ha bloccato le richieste HTTP indirizzate all’URL”, mentre il controllo degli aggiornamenti ha continuato a funzionare. Togliendo api.wordpress.org dall’elenco il sito smette di vedere gli aggiornamenti. Per i plugin commerciali vanno aggiunti gli indirizzi da cui prendono licenze e aggiornamenti, e con gravityapi.com in elenco gravityapi.org restava bloccato, che è esattamente la differenza del caso del 2025. Il jolly vale per i sottodomini: *.wordpress.org ammette api e downloads ma non wordpress.org.
I limiti sono due. Il blocco vale solo per le funzioni HTTP di WordPress, e dallo stesso sito una chiamata con cURL diretto verso il dominio bloccato è passata. E non vede niente di quello che fa il browser, dove sono successi i casi OptinMonster e BdThemes.
In tre dei casi del 2026 il codice malevolo, una volta entrato, si nascondeva. Ho provato le due tecniche descritte da Wordfence e da Sansec: un plugin che si toglie dall’elenco agganciando il filtro all_plugins, e un mu-plugin che toglie un amministratore da ogni ricerca sugli utenti.
| Dove guardi | Plugin che si nasconde | Amministratore nascosto |
|---|---|---|
| Schermate Plugin e Utenti della bacheca | assente | assente, ma il conteggio “Amministratore (2)” non torna |
API REST (/wp/v2/plugins, /wp/v2/users) | presente | assente |
wp plugin list, wp user list | assente | assente |
Gli stessi comandi con --skip-plugins | presente | assente, perché i mu-plugin si caricano comunque |
Cartella wp-content/plugins, wp db query | presente | presente |
Il conteggio della schermata Utenti ha tradito il mio mu-plugin di prova, che non lo correggeva; quello del caso BdThemes correggeva anche quello. L’avviso di OptinMonster e l’analisi di Sansec danno la stessa regola, fidarsi del disco e non della bacheca, e per gli utenti vale lo stesso con il database. Dal server:
ls -la wp-content/plugins wp-content/mu-plugins wp plugin list --skip-plugins --skip-themes wp db query "SELECT u.ID, u.user_login, u.user_registered FROM wp_users u JOIN wp_usermeta m ON m.user_id = u.ID WHERE m.meta_key = 'wp_capabilities' AND m.meta_value LIKE '%administrator%'"
wp db query parla con il database senza caricare WordPress, quindi nessun plugin può cambiarne il risultato. Se il prefisso delle tabelle del tuo sito non è wp_, va cambiato nei due nomi di tabella e nella chiave wp_capabilities. Le date dei file aiutano meno di quanto sembri: nei casi Gravity Forms, ShapedPlugin e BdThemes i file scritti dal codice malevolo avevano date copiate da file legittimi, o di mesi prima.
L’ultima difesa costa poco. Nei casi OptinMonster e BdThemes il codice partiva solo quando la pagina era aperta da un amministratore collegato. Lavorare ogni giorno con un account da editore, e usare quello da amministratore solo per le operazioni che lo richiedono, riduce le occasioni. I controlli generali, dalla provenienza dei plugin alla scansione dei file, sono nella checklist di sicurezza WordPress.
Se un plugin che usi è stato compromesso
Gli avvisi dei casi recenti dicono la stessa cosa: se sul sito c’è stata la versione compromessa, il sito va trattato come compromesso, anche se non si vede niente. L’ordine che segue mette insieme le loro indicazioni.
Togli la versione compromessa. Aggiorna alla versione pulita se esiste, altrimenti elimina il plugin. Gravity Forms raccomandava di disattivare ed eliminare la versione infetta dalla schermata Plugin, e di non usare la disinstallazione nelle impostazioni del plugin, che avrebbe cancellato moduli e dati.
Guarda il disco e il database. I comandi della sezione precedente, sulle cartelle dei plugin e dei mu-plugin e sugli amministratori, sono il punto di partenza.
Valuta il ripristino. La strada più solida, scriveva Gravity Forms, è il backup più recente fatto prima del giorno della compromissione. Funziona solo con backup che conservano più versioni, non soltanto l’ultima.
Cambia tutto quello che può essere stato letto. Le chiavi di sicurezza di wp-config.php, che chiudono tutte le sessioni aperte. Le password degli amministratori. Le password delle applicazioni, che sopravvivono al cambio della password e delle chiavi e vanno revocate a parte. I segreti della 2FA, da riconfigurare da capo, perché nel caso ShapedPlugin venivano rubati e con quelli in mano la password nuova non basta. Se il codice ha potuto leggere wp-config.php, come in quel caso, anche la password del database.
Come si riconosce e si ripulisce un sito compromesso, dall’inizio alla fine, ha una guida in calendario.
Se pubblichi plugin o temi, la catena comincia da te
Per chi pubblica su WordPress.org, le difese sono negli strumenti che il repository mette già a disposizione. La 2FA è obbligatoria dal 2024, e per i commit si usa una password SVN separata da quella dell’account, revocabile senza toccare il resto. La Release Confirmation fa confermare ogni nuova versione con un link ricevuto per email, e scrivendo a [email protected] si può chiedere che servano due committer: una password SVN rubata, da sola, non basta più a pubblicare. Chi la usa può scegliere anche il rilascio graduale, che ritarda di 24 ore gli aggiornamenti automatici. Dopo i fatti del 2024 il team ha consigliato di tenere pochi committer e di rivederli con regolarità, e di non intestare mai l’account del proprietario o di un committer a un indirizzo condiviso come quello del supporto, da cui chiunque abbia accesso alla casella può reimpostare la password. Plugin Check fa in locale, o in una GitHub Action a ogni commit, gran parte dei controlli che il repository applica ai plugin nuovi.
Fuori dal repository le difese sono tutte a carico tuo, e i casi del 2025 e del 2026 dicono dove guardare. C’è la catena di build e il sistema che consegna i pacchetti ai clienti, dove è entrato l’attacco a ShapedPlugin. Ci sono le chiavi di servizio salvate su server che non sembrano importanti: OptinMonster ha perso quella del CDN su un sito di marketing con un plugin non aggiornato. Ci sono i dati che il plugin legge dai tuoi server e mostra in bacheca, da trattare come qualunque input esterno e da pulire prima di stamparli, cosa che il codice di BdThemes non faceva.
Poi le dipendenze. I file composer.lock e package-lock.json vanno nel repository del codice, composer audit (disponibile dalla versione 2.4 di Composer, agosto 2022) e npm audit confrontano i pacchetti con gli avvisi noti, Dependabot o Renovate propongono gli aggiornamenti e CodeQL analizza il codice a ogni modifica.
Se trovi una vulnerabilità nel plugin di qualcun altro, la pagina sulla sicurezza di WordPress.org chiede di scriverne allo sviluppatore e al team dei plugin, senza pubblicarla; le falle del core vanno al team di sicurezza di WordPress. Il team dei plugin lavora con volontari, e a marzo 2026 ne cercava di nuovi, perché gli invii di plugin nuovi erano quadruplicati rispetto al 2024. Ai Contributor Day di WordCamp Europe ha tavoli suoi: a Basilea, nel 2025, il tema annunciato era Plugin Check.
Su questo sito
Questo sito, a fine settembre 2026, usa diciassette plugin. Dieci arrivano dal repository di WordPress.org, e i loro aggiornamenti passano dall’attesa e dalla revisione automatica descritte sopra. Sette sono commerciali, di cinque fornitori diversi, e si aggiornano dai server dei fornitori, dove quei controlli non si applicano; tre di questi sette vengono da Gravity Forms, compreso il plugin che qui gestisce il modulo contatti. wp plugin verify-checksums --all verificherebbe dieci plugin su diciassette e salterebbe gli altri sette.
Poi c’è la parte che gira nel browser. La Content Security Policy del sito elenca undici origini esterne da cui il browser può caricare script: gestione dei tag e statistiche di Google, reCAPTCHA, il servizio per il consenso ai cookie, i pulsanti di condivisione, le icone, le statistiche di Cloudflare e il CDN delle immagini. Ognuna è un anello della catena, come il CDN di OptinMonster. La policy tiene fuori le origini che non sono in elenco, e non protegge da un’origine in elenco compromessa, perché in quel caso il file modificato arriva dall’indirizzo di sempre.
Domande frequenti
Un supply chain attack è la stessa cosa di una vulnerabilità?
Sono due cose diverse. In una vulnerabilità il codice del fornitore ha un difetto e qualcuno lo sfrutta da fuori, come nel 2018 con WP GDPR Compliance, e la cura è aggiornare. In un supply chain attack il codice malevolo arriva dal fornitore stesso, perché qualcuno ne ha preso il controllo o ha compromesso i suoi sistemi, e arriva proprio con l’aggiornamento. Le due cose si toccano quando una vulnerabilità nei sistemi del fornitore diventa la porta per compromettere il suo codice, come nel caso OptinMonster del 2026.
Spegnere gli aggiornamenti automatici protegge da un supply chain attack?
Solo in parte, e in cambio chiude il canale della cura. Dal giugno 2026 ogni rilascio di plugin e temi su WordPress.org aspetta sei ore prima di arrivare ai siti, e dal settembre 2026 i rilasci dei plugin passano da una revisione automatica che blocca quelli ad alto rischio. WordPress.org può anche forzare l’installazione di una versione ripulita, ed è così che nel 2017 la versione corretta del plugin Captcha è arrivata su oltre 100.000 siti. Disabilitare gli aggiornamenti automatici del singolo plugin lascia passare queste versioni forzate, mentre il filtro auto_update_plugin impostato a false le blocca tutte.
Come faccio a sapere se un plugin che uso è stato venduto o chiuso?
WordPress non lo segnala. Se cambia il nome sotto il titolo della scheda nel repository, che è il profilo del proprietario, il plugin è passato di mano; se è chiuso, la scheda mostra data e motivo, e Wordfence lo segnala nella sua scansione.
I plugin a pagamento sono più sicuri di quelli del repository?
Per la catena di fornitura hanno meno controlli, non di più. Quelli che WordPress.org ha aggiunto dal 2024, dalla 2FA obbligatoria per chi pubblica all’attesa di sei ore e alla revisione automatica dei rilasci, valgono solo per il repository. Un plugin commerciale si aggiorna dai server del fornitore, e la sua sicurezza dipende da come il fornitore protegge i propri sistemi. Nel 2025 e nel 2026 Gravity Forms e ShapedPlugin hanno distribuito pacchetti modificati dai propri canali.
Un plugin di sicurezza vede una backdoor arrivata con un aggiornamento?
La risposta cambia con il tipo di controllo. Il confronto dei file con il repository non la vede, perché i file coincidono con la versione pubblicata. Gli scanner a firme la riconoscono dopo che qualcuno l’ha catalogata, e nella versione gratuita di Wordfence le firme arrivano con 30 giorni di ritardo. Gli avvisi sulle vulnerabilità la segnalano appena la versione viene dichiarata malevola. Per il codice che si nasconde dalla bacheca bisogna guardare dal server la cartella dei plugin, quella dei mu-plugin e il database.
Cosa faccio se un plugin che uso risulta compromesso?
Considera compromesso il sito, anche se non vedi niente. Aggiorna o elimina il plugin, controlla dal server plugin, mu-plugin e amministratori e valuta un backup precedente alla compromissione. Poi cambia chiavi di sicurezza e password, revoca le password delle applicazioni e riconfigura la 2FA da capo.
Da qui in avanti
Contro un supply chain attack il sito da solo può poco, perché le difese principali stanno nei sistemi dei fornitori e nei controlli del repository. A chi gestisce il sito restano tre cose: sapere da quale strada arriva ogni pezzo di codice, lasciare aperto il canale da cui arrivano le correzioni e guardare il disco e il database quando qualcosa non torna. Sono controlli da rifare a ogni giro di manutenzione, e ogni volta che un fornitore cambia.
Una versione precedente di questo articolo conteneva quattro errori, corretti qui sopra. Datava al 2023 e attribuiva a Patchstack il caso del plugin Captcha, che è del dicembre 2017, fu scoperto da Wordfence e riguardava una backdoor su oltre 300.000 siti. Presentava come attacco alla catena di fornitura il caso WP GDPR Compliance del 2018, che era una vulnerabilità. Attribuiva a Wordfence oltre 30 plugin colpiti nel 2023, mentre l’articolo citato documentava cinque plugin compromessi a giugno 2024. E consigliava di disattivare gli aggiornamenti automatici con un filtro che blocca anche quelli forzati da WordPress.org per le correzioni di sicurezza. Fonti verificate il 1° ottobre 2026.
Se preferisci che lo faccia io
Tenere d’occhio i fornitori di un sito, controllare dal server cosa c’è sul disco e, se serve, ripristinare una copia pulita fa parte del lavoro sulla sicurezza dei siti WordPress che faccio per i clienti. Se vuoi che me ne occupi io, scrivimi quali plugin usi e come li aggiorni oggi.

Lascia un commento