Il sito si apre regolarmente, le pagine sono quelle di sempre, lo scanner del plugin di sicurezza non segnala nulla. Poi arriva la mail di un cliente: aprendo il sito gli è comparso un avviso che chiedeva di aggiornare il browser, oppure una verifica «non sono un robot» che gli chiedeva di premere una combinazione di tasti. Ha seguito le istruzioni, e ora il suo antivirus segnala un malware. Oppure è Google a mostrare la pagina rossa di Safe Browsing con l’avviso di contenuti ingannevoli.
Non si tratta di un problema del computer del cliente. È una delle famiglie di infezioni più diffuse sui siti WordPress compromessi: uno script iniettato che trasforma il sito in un punto di distribuzione di malware per i visitatori, e che fa di tutto per non farsi vedere dal proprietario. In questo articolo descriviamo come funzionano le esche dei finti aggiornamenti e dei falsi CAPTCHA, perché chi gestisce il sito difficilmente le vede, dove si nasconde l’iniezione e come trovarla e rimuoverla. Le descrizioni servono a riconoscere il problema: non riportiamo codice malevolo funzionante.
Il sito come strumento per colpire i visitatori
La maggior parte delle infezioni che trattiamo in questo blog sfrutta il sito per qualcosa che interessa all’attaccante: posizionare pagine di spam, inviare posta, rubare i dati di pagamento. In questa famiglia il bersaglio vero sono i computer di chi visita il sito. L’attaccante non ha bisogno di convincere le persone a visitare un dominio sospetto: usa la reputazione di un sito legittimo, che i visitatori conoscono e di cui si fidano, per presentare un’esca credibile.
Lo schema è sempre a più stadi. Nel sito compromesso c’è solo un piccolo caricatore JavaScript; questo contatta un’infrastruttura esterna che decide se il visitatore è un bersaglio interessante e, in caso positivo, restituisce l’esca vera e propria; l’esca convince la persona a scaricare ed eseguire un file o un comando; il programma finale è di solito un infostealer, che ruba password salvate nel browser, cookie di sessione e portafogli di criptovalute, oppure uno strumento di accesso remoto. Separare gli stadi permette di cambiare esca e payload senza toccare i siti infetti.
Finti aggiornamenti del browser: SocGholish e ClearFake
L’esca più longeva è il finto aggiornamento: una pagina, o un livello sovrapposto alla pagina, che imita la grafica di Chrome, Firefox o Edge e avvisa che il browser è obsoleto e va aggiornato per visualizzare il contenuto. Il pulsante scarica un file che non ha nulla a che vedere con il browser. Proofpoint, nella sua analisi dell’ottobre 2023 sui finti aggiornamenti, ha descritto quattro gruppi distinti che usano questa esca su siti compromessi, con codice JavaScript o HTML iniettato che porta il traffico verso domini controllati dagli attaccanti.
Il più noto è SocGholish, chiamato anche FakeUpdates, che Proofpoint attribuisce al gruppo TA569 e che è attivo da oltre cinque anni. Sucuri, che lo osserva sui siti che ripulisce, ne ha documentato la diffusione su WordPress: nel 2022 descriveva iniezioni poste subito prima della chiusura di </head> o in cima e in fondo a file .js legittimi, e visitatori selezionati tra quelli su Windows che arrivano per la prima volta da un motore di ricerca. Nel 2024 la stessa Sucuri ha descritto un’ondata di infezioni tramite falsi plugin, copie modificate di plugin reali installate con credenziali di amministratore rubate, che iniettano lo script solo nelle pagine viste da utenti non amministratori.
ClearFake è comparso nel 2023 con la stessa esca, ma con un’infrastruttura più originale. Guardio Labs l’ha documentato con il nome di EtherHiding: lo script iniettato nei siti WordPress non scarica lo stadio successivo da un server, ma lo legge da uno smart contract sulla BNB Smart Chain con una chiamata eth_call, un’operazione di sola lettura che non costa nulla e non lascia transazioni. Un contratto non si può sequestrare né spegnere come un dominio, e l’attaccante può aggiornarne il contenuto quando vuole. Un’analisi di Trend Micro del maggio 2026 descrive una variante che usa la rete di test della BNB Smart Chain, con il caricatore inserito nell’<head> come tag <script> con sorgente data:text/javascript;base64, senza alcun dominio esterno visibile nel codice della pagina.
Falsi CAPTCHA e ClickFix: il visitatore infetta se stesso
Dal 2024 si è affermata un’esca diversa. Invece di far scaricare un file, che browser e antivirus hanno imparato a bloccare, la pagina mostra una verifica che imita reCAPTCHA di Google o Turnstile di Cloudflare. Dopo il clic su «Non sono un robot», compaiono istruzioni per una «verifica aggiuntiva»: premere Win+R, poi Ctrl+V, poi Invio. Nel frattempo, la pagina ha già copiato negli appunti un comando PowerShell offuscato. Chi segue le istruzioni apre la finestra Esegui di Windows, incolla il comando e lo esegue con i propri privilegi. La tecnica è nota come ClickFix.
Sekoia ha descritto la tecnica in un rapporto del marzo 2025 su ClearFake, che dal dicembre 2024 usava finti reCAPTCHA e Turnstile e che a febbraio 2025 risultava presente su oltre 9.300 siti, per lo più WordPress; i payload osservati includevano gli infostealer Lumma e Vidar. Microsoft Threat Intelligence, nella sua analisi di ClickFix dell’agosto 2025, cita i siti compromessi tra i canali di diffusione, accanto a phishing e pubblicità malevola, e riporta varianti per macOS che chiedono di incollare il comando nel Terminale. Nel gennaio 2026 Sekoia ha documentato IClickFix, un framework dedicato ai siti WordPress che contava oltre 3.800 siti compromessi e distribuiva lo strumento di accesso remoto NetSupport.
Per il sito la conseguenza è la stessa del finto aggiornamento, ma più grave dal punto di vista della reputazione: il visitatore ha eseguito lui stesso il comando, spesso su un computer aziendale, e ricorderà il sito in cui è successo.
Perché il proprietario non vede nulla
Questi script non sono pensati per colpire tutti. Mostrare l’esca a ogni visita farebbe scoprire l’infezione in poche ore; mostrarla solo ai visitatori giusti la fa durare settimane. Le condizioni documentate nelle analisi citate si combinano tra loro:
- utente non collegato: chi ha effettuato l’accesso a WordPress, cioè quasi sempre il proprietario o l’agenzia, riceve la pagina pulita, perché l’iniezione lato PHP controlla i cookie di accesso o le capacità dell’utente;
- prima visita: dopo aver mostrato l’esca una volta, lo script imposta un cookie o un altro valore memorizzato nel browser e non la mostra più allo stesso browser;
- provenienza: l’esca compare solo a chi arriva da un motore di ricerca, non a chi digita l’indirizzo o usa un segnalibro;
- sistema operativo e browser: Windows per le esche con PowerShell, macOS per quelle con il Terminale, mentre i dispositivi mobili sono spesso esclusi;
- indirizzo IP e user agent: i sistemi di distribuzione del traffico filtrano le richieste per escludere scanner di sicurezza, crawler e visitatori già colpiti.
Il risultato è che il proprietario, collegato al pannello, che apre il sito dal proprio computer digitando l’indirizzo, soddisfa quasi tutte le condizioni per non vedere l’esca. È lo stesso meccanismo dei redirect condizionali, applicato a un obiettivo più pericoloso, ed è anche il motivo per cui molti scanner di sicurezza che analizzano la pagina da un unico punto di vista non trovano nulla.
Dove si nasconde l’iniezione in WordPress
Il caricatore deve finire in ogni pagina, o almeno in quelle più visitate, e ci sono molti modi per ottenerlo. Nei siti che bonifichiamo lo troviamo più spesso in questi punti:
- file del tema:
header.php,footer.phpofunctions.php, con una funzione agganciata awp_headowp_footer; - file JavaScript legittimi: codice aggiunto in cima o in fondo a librerie del tema o dei plugin, come jQuery o script di slider, che vengono caricati su ogni pagina;
- database: opzioni di plugin che inseriscono codice nell’intestazione, widget HTML,
theme_mods, contenuti diwp_posts, spesso in forma di valori serializzati; - plugin falsi: cartelle con nomi plausibili, che imitano plugin reali, installate con un account di amministratore compromesso;
- mu-plugins e drop-in: file caricati automaticamente che non compaiono nell’elenco dei plugin, come spiegato nell’articolo sui mu-plugins usati come backdoor.
Spesso l’iniezione è presente in più punti contemporaneamente, ed è sempre accompagnata da una backdoor che permette di reinserirla. Togliere lo script dal footer.php senza trovare il resto significa vederlo ricomparire dopo poche ore, magari in una forma diversa.
Vedere il sito come un visitatore nuovo
Il primo controllo è semplice: scaricare la pagina senza cookie, con user agent diversi e con un referrer di un motore di ricerca, e confrontare i risultati. Se le risposte cambiano a seconda di chi chiede, qualcosa nel sito sta decidendo cosa mostrare. curl non esegue JavaScript, quindi non mostra l’esca, ma mostra i tag <script> presenti nel codice HTML restituito, ed è lì che si trova il caricatore.
UA_WIN='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36'
URL='https://www.esempio.it/'
# Visitatore nuovo da Windows che arriva da Google
curl -s -A "$UA_WIN" -e 'https://www.google.com/' "$URL" -o win-google.html
# Stesso visitatore senza referrer, e un client generico
curl -s -A "$UA_WIN" "$URL" -o win-diretto.html
curl -s "$URL" -o curl.html
# Dimensioni e impronte: differenze inattese vanno spiegate
sha256sum win-google.html win-diretto.html curl.html
diff <(grep -o '<script[^>]*>' curl.html) <(grep -o '<script[^>]*>' win-google.html)
# Tutti gli script della pagina: sorgenti esterne e data URI
grep -oE '<script[^>]*(src="[^"]*"|data:text/javascript[^"]*)' win-google.html | sort -u
Pagine che contengono cache o numeri casuali cambiano impronta a ogni richiesta, per cui il confronto va fatto sugli elenchi di script, non solo sugli hash. Ogni script va ricondotto a un componente noto: un dominio che nessun plugin installato giustifica, un tag con sorgente data: in base64, un blocco inline offuscato con atob( o eval( sono i candidati da esaminare. Per vedere l’esca vera, invece, serve un browser reale in un ambiente isolato, senza sessione, meglio se con un indirizzo IP residenziale: operazione da fare solo in una macchina virtuale usa e getta, senza mai eseguire ciò che la pagina chiede.
Cercare nel database e nei file
Dal lato del server la ricerca non dipende dalle condizioni del visitatore, ed è quindi più affidabile. Nel database si cercano tag script e tracce delle infrastrutture note, come le chiamate ai nodi RPC della blockchain usate da ClearFake; nei file, le modifiche recenti a temi, plugin e JavaScript.
# Opzioni e contenuti con script, data URI o riferimenti a blockchain
wp db query "SELECT option_id, option_name, LENGTH(option_value) FROM wp_options
WHERE option_value REGEXP '<script|data:text/javascript|eth_call|bsc-|atob[(]'"
wp db query "SELECT ID, post_type, post_modified FROM wp_posts
WHERE post_content REGEXP '<script|data:text/javascript|eth_call'"
# Integrità di core e plugin del repository ufficiale
wp core verify-checksums
wp plugin verify-checksums --all
# File PHP e JavaScript modificati negli ultimi 30 giorni in temi e plugin
find wp-content/themes wp-content/plugins wp-content/mu-plugins \
\( -name '*.php' -o -name '*.js' \) -mtime -30 -printf '%T+ %p\n' | sort
# Aggancio alle intestazioni nei file del tema attivo
grep -rnE "add_action\(\s*'wp_(head|footer)'" wp-content/themes/$(wp theme list --status=active --field=name)/
La verifica dei checksum copre solo i componenti distribuiti dal repository di WordPress.org: temi e plugin commerciali vanno confrontati con una copia integra scaricata dal fornitore. I plugin falsi, in particolare, vanno cercati per esclusione: ogni cartella in wp-content/plugins deve corrispondere a un componente che qualcuno ha installato consapevolmente. Le date dei file non sono una prova, perché il malware le modifica spesso per confonderle con quelle dei file vicini; per questo nelle nostre analisi le incrociamo con i log del server e con il cambio di stato (ctime), molto più difficile da falsificare.
Bonifica, Safe Browsing e cosa dire ai visitatori
La rimozione dello script è l’ultimo passo, non il primo. Prima vanno trovati la backdoor e il vettore di ingresso: un plugin vulnerabile, credenziali di amministratore rubate, un accesso FTP compromesso. Le campagne con falsi plugin partono quasi sempre da password di amministratore sottratte, e in quel caso il cambio delle credenziali, delle chiavi di wp-config.php e la revisione degli utenti sono parte integrante della bonifica. Il resto segue il percorso descritto nell’articolo sulle prime due ore dopo un attacco.
Se Google ha rilevato l’esca, il sito può comparire nel rapporto sui problemi di sicurezza di Search Console come contenuto ingannevole o ingegneria sociale, e i browser mostrano un avviso a pagina intera. La richiesta di revisione va inviata solo quando tutti i problemi sono risolti su tutte le pagine, come spiegato nella guida alla rimozione dalle blacklist di Google.
Resta la parte più scomoda: i visitatori che potrebbero aver seguito le istruzioni. Se qualcuno segnala di averlo fatto, deve considerare compromesso il proprio computer e tutte le password salvate nel browser, e rivolgersi al proprio referente informatico. Se il sito ha utenti registrati, clienti o dipendenti che lo usano quotidianamente, un avviso chiaro è un atto di responsabilità, e in alcuni casi può essere opportuno valutare con il proprio consulente anche gli aspetti di protezione dei dati. Il messaggio da ricordare a tutti è semplice: nessun sito legittimo chiede di aprire la finestra Esegui o il Terminale per dimostrare di essere umani.
Queste infezioni sono difficili proprio perché il sito sembra sano a chi lo controlla. Nei nostri interventi analizziamo le risposte del sito da più punti di vista insieme a file, database e log del server, e i vettori non ancora classificati passano da un’analisi assistita da modelli di intelligenza artificiale eseguiti in locale. La pulizia è garantita in 6, 12 o 24 ore per ogni installazione WordPress; se un visitatore ti ha segnalato un finto aggiornamento o un CAPTCHA sospetto sul tuo sito, contattaci anche se tu non riesci a vederlo.