Caso reale anonimizzato · maggio 2026
Quando un sito WordPress viene hackato in modo serio, la domanda non è "se" si può recuperare. È quanto tempo, quanti soldi, e quanti dati si perdono nel processo. La risposta varia molto a seconda di chi gestisce la pulizia.
Questo è il timeline di un recovery che abbiamo fatto in 6 ore su un sito di un nostro cliente, completamente in autonomia AI-driven. 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 era multilivello:
- 47 file PHP malware sparsi tra
/public_html/,/wp-content/mu-plugins/e/wp-includes/ - 8 mu-plugin con backdoor — questi sono particolarmente cattivi perché WordPress li carica automaticamente senza che siano nella lista 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. Questa volta avevamo invece:
- 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 Sistema di monitoraggio rileva HTTP 500. Avvia automaticamente: backup completo via cPanel UAPI (tarball 58MB), snapshot DB completo, audit dei findings critici via external probe.
Ora 0:30 → 1:30 · Filesystem cleanup Helper PHP iniettato sul cliente via Fileman API scansiona ricorsivamente:
- 47 file PHP con pattern malware → quarantenati 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 halt al bootstrap, vedi caso WSOD a parte).htaccessripristinato con versione clean
Ora 1:30 → 2:30 · DB users cleanup Query SQL diretta:
- 6 admin rogue identificati per pattern username
- Backup
wp_users+wp_usermeta+wp_posts(rows che referenziano quegli ID) - Reassign di 1.411 post da utente rogue → nuovo admin generato (username random + password 24 char + email del CRM)
- Delete utenti rogue + loro usermeta + cleanup orphan
- Verify: query
?author=1ora ritorna 404, sitemap users mostra solo nuovo admin
Ora 2:30 → 4:00 · Post content cleanup 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 stessi pattern (NON skippare — sono storico ma riattivabili)
Cleanup:
- Cut content al primo
<scripttag → keep prefix legit - Keep tail dopo ultimo
</script>se substantial - DELETE rev WordPress infetti (storico, non critici)
Risultato: 5 post pubblicati ripuliti (da 225KB → ~300 byte ciascuno), 18 revisions cancellate.
Ora 4:00 → 5:00 · Persistent fingerprint cleanup Lo step che gli scanner standard saltano: rimuovere gli "scarti del breach" che restano in wp_options:
admin_emailsettata a email attaccante (intercetta password reset)new_admin_emailcon vecchio admin pending changeauto_core_update_notifiedcon email vecchio adminWPLANGcambiato a'en'(frontend<html lang="en">su sito italiano)- Theme Builder con typo "Releted news" (sbaglio di non-madrelingua nel Divi layout)
- Post pubblicati con
post_content = 0 bytedopo cleanup malware
Ora 5:00 → 6:00 · Verify visivo + hardening Visual rendering check con browser headless:
- Body inspection: home > 1KB, contains theme markers
- Multi-endpoint:
/,/wp-login.php,/wp-json/ - Cloaking test: stesso md5 con UA Chrome vs Googlebot
- Hardening
.htaccess: bloccowp-admin/install.php,readme.html,license.txt,xmlrpc.php - Email cliente con report cosa è stato fatto + nuove credenziali admin
- Schedule auto-revoke creds dopo 7 giorni
Quello che il cliente NON ha dovuto fare
- Aprire ticket di supporto
- Comprare licenza Wordfence Premium
- Pagare un consulente esterno per il recovery
- Ripristinare 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 esplicitamente. Tutti gli altri sono sospetti. - Cerca file con doppia estensione in
/public_htmle/wp-contentcon:find . -name ".php."(deve essere 0 risultati) - Audit utenti admin in wp-admin → Utenti → Filter "Amministratore". Se vedi nomi che non riconosci o pattern come
sys_owp_random, sei già stato bucato. - Controlla
wp_optionsvia phpMyAdmin:admin_email,new_admin_email,auto_core_update_notified. Se contengono email che non sono tue, hai un problema serio.
Come WPSonar gestisce questo
Sui siti dei nostri clienti, una catena come quella descritta sopra viene neutralizzata in autonomia entro 6 ore dalla detection iniziale, senza richiedere alcun intervento del proprietario. Tutto è loggato nel nostro audit trail (append-only) e il cliente riceve un report di cosa è successo, cosa abbiamo fatto, e quali sono le nuove credenziali da cambiare.
Il sistema scansiona le 10 fonti pubbliche di threat intelligence (Patchstack, Wordfence Intelligence, Sucuri Blog, Reddit, WP Tavern, ecc.) ogni settimana per aggiornare i pattern di detection, in modo che attacchi simili al successivo cliente vengano riconosciuti subito.
Domande frequenti
Quanto tempo serve per recuperare un sito WordPress hackato?
Dipende dalla profondità del compromesso. Un attacco multilivello come quello descritto (file malware + database infetto + utenti rogue) richiede tipicamente 4-8 ore di lavoro tecnico. Con un sistema AI-driven che opera in autonomia il recovery completo è stato chiuso in 6 ore dalla detection, senza attesa di intervento umano.
Posso recuperare il sito senza perdere i contenuti?
Sì, se il cleanup è chirurgico invece di ripristinare un backup vecchio. Nel caso descritto i 1.411 post sono stati ripuliti dal JavaScript injected mantenendo 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 esplicitamente. Cerca file con doppia estensione (find . -name '.php.' deve restituire zero risultati). Verifica 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ò apparire 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