Caso reale anonimizzato · maggio 2026
Quando un sito WordPress viene hackato sul serio, non ci si chiede se si recupera: ci si chiede quanto tempo ci vuole, quanto costa e quanti dati saltano. La risposta cambia molto a seconda di chi gestisce la pulizia.
Ecco la cronologia di un recupero che abbiamo chiuso in 6 ore sul sito di un cliente, gestito interamente da un sistema automatico. Tutti i nomi e i dettagli identificativi sono rimossi; i numeri e la sequenza tecnica sono reali.
Cosa è successo
Il sito era una rivista nautica con circa 200 articoli pubblicati. Una mattina i visitatori hanno iniziato a vedere redirect a pagine di spam. Il proprietario ha provato ad accedere a wp-admin: errore 500. Il sito era ufficialmente compromesso.
L'attacco lavorava su più livelli:
- 47 file PHP malware sparsi tra
/public_html/,/wp-content/mu-plugins/e/wp-includes/ - 8 mu-plugin con backdoor — questi sono i più insidiosi, perché WordPress li carica in automatico senza che compaiano nella lista dei plugin attivi
.htaccessmanipolato con regoleFilesMatchche davano accesso solo ai file backdoor- wp-config.php compromesso con credenziali DB cambiate dall'attaccante
- 6 utenti admin malevoli creati nel database (pattern di nomi:
khubaib,sys_,wp_*) - 1.411 post infettati con JavaScript obfuscato (
_0xhex variables, ~225KB injection per post) - 18 revisioni WordPress con la stessa injection (l'attaccante aveva esplicitamente sfruttato l'autosave WP per persistenza)
Perché questo caso era diverso dal solito
I tipici scanner WordPress (Wordfence, Sucuri, MalCare) cercano file .php con pattern noti tipo funzioni di code-execution dinamica, decoder base64, codice obfuscato. Qui invece ci siamo trovati davanti a:
- File
.php.php(doppia estensione) — molti scanner saltano l'estensione "doppia" perché il loro filtro cerca.phpletterale - JavaScript injected nel post_content del database — gli scanner filesystem non lo guardano
- Backdoor con nomi camuffati da plugin legittimi (es.
01-mu-AtlasDrift.php,01-mu-AuroraMesh.php) - Modifiche al Theme Builder Divi via DB row, non file — invisibile ai file scanner
Il timeline (6 ore totali)
Ora 0 → 0:30 · Triage iniziale Il sistema di monitoraggio rileva HTTP 500. Parte in automatico: backup completo via cPanel UAPI (tarball 58MB), snapshot DB completo, audit dei findings critici via external probe.
Ora 0:30 → 1:30 · Pulizia dei file Un helper PHP iniettato sul cliente via Fileman API scansiona ricorsivamente:
- 47 file PHP col profilo del malware → messi in quarantena con backup
.MALWARE-{ts}.bakaccanto /wp-content/mu-plugins/ricorsivo → 8 file rimossi (per i mu-plugin lo stub di neutralization deve essere noop, NON un halt — altrimenti WP si ferma al bootstrap, vedi caso WSOD a parte).htaccessripristinato con versione clean
Ora 1:30 → 2:30 · Pulizia degli utenti nel DB Query SQL diretta:
- 6 admin rogue identificati per pattern username
- Backup
wp_users+wp_usermeta+wp_posts(rows che referenziano quegli ID) - Riassegnati 1.411 post dall'utente rogue a un nuovo admin generato (username random + password 24 char + email del CRM)
- Cancellati gli utenti rogue + i loro usermeta + cleanup orphan
- Verifica: la query
?author=1ora restituisce 404, la sitemap users mostra solo il nuovo admin
Ora 2:30 → 4:00 · Pulizia dei contenuti Scan SQL su wp_posts.post_content con 6 pattern:
- Pattern A:
<?phpliteral injection (PHP) - Pattern B:
_0x[a-f0-9]{4,8}(JavaScript obfuscation) - Pattern C: decoder JS (atob, fromCharCode, unescape)
- Pattern D: redirect chain (location.replace, window.location)
- Pattern E: post > 50KB con
<script(size anomaly) - Pattern F: revisions WP con gli stessi pattern (NON skippare — sono storico ma riattivabili)
Pulizia:
- Taglio del contenuto al primo
<scripttag → si tiene il prefisso legittimo - Si tiene la coda dopo l'ultimo
</script>se sostanziale - DELETE delle revisioni WordPress infette (storico, non critiche)
Risultato: 5 post pubblicati ripuliti (da 225KB → ~300 byte ciascuno), 18 revisions cancellate.
Ora 4:00 → 5:00 · Pulizia delle tracce residue Lo step che gli scanner standard saltano: togliere gli "scarti del breach" che restano in wp_options:
admin_emailpuntata all'email dell'attaccante (intercetta il reset password)new_admin_emailcon il vecchio admin in pending changeauto_core_update_notifiedcon l'email del vecchio adminWPLANGcambiato in'en'(frontend<html lang="en">su un sito italiano)- Theme Builder con il typo "Releted news" (sbaglio da non madrelingua nel Divi layout)
- Post pubblicati con
post_content = 0 bytedopo la pulizia del malware
Ora 5:00 → 6:00 · Verifica visiva + hardening Controllo del rendering visivo con browser headless:
- Body inspection: home > 1KB, contiene i marker del tema
- Multi-endpoint:
/,/wp-login.php,/wp-json/ - Cloaking test: stesso md5 con UA Chrome e con Googlebot
- Hardening
.htaccess: blocco diwp-admin/install.php,readme.html,license.txt,xmlrpc.php - Email al cliente con il report di cosa è stato fatto + le nuove credenziali admin
- Schedule dell'auto-revoke delle credenziali dopo 7 giorni
Quello che il cliente NON ha dovuto fare
- Aprire un ticket di supporto
- Comprare la licenza Wordfence Premium
- Pagare un consulente esterno per il recupero
- Ripristinare un backup vecchio, perdendo X giorni di contenuti
- Cambiare hosting
Cosa puoi fare se non sei nostro cliente
Se gestisci un sito WP da solo:
- Verifica
/wp-content/mu-plugins/ogni mese · dovrebbe contenere 0-2 file di plugin che hai installato apposta tu. Tutti gli altri sono sospetti. - Cerca i file con doppia estensione in
/public_htmle/wp-contentcon:find . -name ".php."(deve dare 0 risultati) - Controlla gli utenti admin in wp-admin → Utenti → filtro "Amministratore". Se vedi nomi che non riconosci o pattern come
sys_owp_random, ti hanno già bucato. - Controlla
wp_optionsvia phpMyAdmin:admin_email,new_admin_email,auto_core_update_notified. Se contengono email che non sono le tue, hai un problema serio.
Come lo gestisce WPSonar
Sui siti dei nostri clienti, una catena come quella descritta sopra viene neutralizzata in autonomia entro 6 ore dalla prima detection, senza che il proprietario debba fare niente. Tutto finisce nel nostro audit trail (append-only), e il cliente riceve un report di cosa è successo, cosa abbiamo fatto e quali credenziali deve cambiare.
Il sistema scandaglia le 10 fonti pubbliche di threat intelligence (Patchstack, Wordfence Intelligence, Sucuri Blog, Reddit, WP Tavern e altre) ogni settimana per aggiornare i pattern di detection, così un attacco simile sul cliente successivo lo riconosciamo subito.
Domande frequenti
Quanto tempo serve per recuperare un sito WordPress hackato?
Dipende da quanto è profonda la compromissione. Un attacco su più livelli come quello descritto (file malware + database infetto + utenti rogue) chiede di solito 4-8 ore di lavoro tecnico. Con un sistema che opera da solo, il recupero completo si è chiuso in 6 ore dalla detection, senza aspettare che intervenisse una persona.
Posso recuperare il sito senza perdere i contenuti?
Sì, se la pulizia è chirurgica invece di ripristinare un backup vecchio. Nel caso descritto i 1.411 post sono stati ripuliti dal JavaScript injected tenendo il testo legittimo, e le revisioni infette sono state cancellate. Ripristinare un backup avrebbe fatto perdere tutti i contenuti pubblicati dopo la data del backup.
Come faccio a sapere se il mio sito WordPress ha file malware nascosti?
Controlla la cartella wp-content/mu-plugins/: dovrebbe contenere 0-2 file di plugin che hai installato apposta tu. Cerca i file con doppia estensione (find . -name '.php.' deve restituire zero risultati). Controlla gli utenti amministratore in wp-admin: nomi come sys_ o wp_ seguiti da caratteri random indicano una compromissione.
Gli scanner come Wordfence trovano tutto il malware?
No. Gli scanner filesystem standard non analizzano il contenuto del database (dove può vivere JavaScript injected nei post) e spesso saltano i file con doppia estensione .php.php. Un sito può sembrare pulito a uno scanner e avere comunque malware attivo nel database o nei mu-plugins.
Fonti tecniche
- Patchstack vulnerability database · CVE WP centralizzato
- Wordfence Threat Intelligence · feed plugin compromessi
- Sucuri Security Blog · case study e malware writeup
- WordPress.org news feed · release ufficiali e security advisories