Se il tuo WordPress reindirizza i visitatori verso siti sconosciuti (spesso solo su mobile o al primo click), è quasi sempre segno di una compromissione. Qui trovi una procedura operativa, passo per passo, per bloccare il danno, ripulire file e database e rimettere in sicurezza il sito.
Ti anticipo la sequenza, poi la vediamo nel dettaglio:
- Metti in sicurezza: backup immediato, disattiva cache e CDN, attiva la 2FA, cambia le password.
- Trova l’origine: controlla
.htaccess,wp-config.php, la cartella uploads, mu-plugins, plugin/tema e il database (wp_options,wp_posts). - Pulisci: rimuovi il codice offuscato (
base64_decode,gzinflate,eval) e ripristina core e plugin da fonti ufficiali. - Ruota le chiavi (SALTS), reset password, blocca l’esecuzione PHP in
/uploads, aggiorna tutto. - Verifica: svuota la cache, controlla Search Console (sezione Sicurezza), monitora per 48-72 ore.
Una premessa: questa è una guida per chi sa dove mettere le mani. Se non te la senti, meglio farla fare a qualcuno, perché su un sito compromesso un passo falso può peggiorare le cose.
1) Metti in sicurezza (prima di toccare i file)
- Backup completo di file + database: serve una copia “forense” dello stato attuale, prima di modificare qualsiasi cosa.
- Disattiva la cache (plugin e CDN), altrimenti rischi di continuare a servire versioni infette dalla cache.
- Attiva la 2FA e cambia le password di tutto: WordPress (tutti gli admin), hosting, FTP/SSH, database, CDN.
- Controlla il DNS: verifica che i record A/AAAA/CNAME non siano stati modificati.
2) Riconosci il tipo di redirect
- Succede solo su mobile/Android o al primo caricamento? È tipico degli script che usano
localStorageo cookie per fare un “redirect una tantum” per visitatore. - Si attiva su URL specifiche o al click? Di solito è codice iniettato nel footer o in un widget.
3) I punti caldi da controllare
- .htaccess (Apache): regole
Rewritesospette che puntano a domini esterni. - wp-config.php: include strani (soprattutto a inizio o fine file) o costanti aggiunte.
- /wp-content/uploads/: presenza di file
.php(sospetti per definizione), specie nelle sottocartelle anno/mese. - /wp-content/mu-plugins/: file auto-caricati con codice offuscato.
- Plugin e tema: file modificati di recente o con date anomale.
- Database:
wp_options(opzioni serializzate con JS offuscato),wp_posts(iframe o script),siteurl/homealterati.
4) Comandi utili per trovare l’infezione (SSH)
|
1 2 3 4 5 6 7 8 9 10 11 |
# Cerca funzioni tipiche di offuscamento/backdoor grep -R --line-number -E "base64_decode|gzinflate|str_rot13|eval\(|assert\(|preg_replace\(.*/e" wp-content # Trova file PHP dentro uploads (sospetti) find wp-content/uploads -type f -iname "*.php" -ls # File modificati negli ultimi 3 giorni find . -type f -mtime -3 -ls | grep -E "wp-content|wp-includes|wp-admin" # Inclusioni sospette in wp-config.php grep -n "include\|require" wp-config.php |
5) Ripristino di core, tema e plugin
La regola d’oro qui è: non riparare a mano i file infetti, sovrascrivili da fonte pulita. È più veloce e non rischi di lasciarti dietro un pezzo di backdoor.
Reinstalla il core da sorgente ufficiale:
|
1 |
wp core download --force |
Poi ripristina plugin e tema reinstallandoli:
|
1 2 3 4 5 |
# Plugin wp plugin reinstall --all --force # Tema attivo (sostituisci con il tuo slug) wp theme install twentytwentyfive --force |
6) Pulisci .htaccess e Nginx
Riporta l’.htaccess allo standard WordPress (dopo aver rimosso eventuali regole malevole):
|
1 2 3 4 5 6 7 8 |
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> |
Su Nginx: controlla che non ci siano rewrite verso domini esterni e che gli snippet siano quelli standard del tema o dell’hosting.
7) Pulisci il database
Controlla wp_options: siteurl e home devono puntare al tuo dominio, e vanno ispezionate le opzioni widget_* e quelle personalizzate che contengono script.
Query di ricerca (adatta il prefisso delle tabelle al tuo):
|
1 2 3 4 5 6 7 |
SELECT option_name, LEFT(option_value, 200) FROM wp_options WHERE option_value REGEXP '(base64|<script|iframe|eval\()'; SELECT ID, post_type, LEFT(post_content, 200) FROM wp_posts WHERE post_content REGEXP '(base64|<script|iframe|eval\()'; |
8) Ruota le chiavi e blocca PHP in uploads
Rigenera le SALTS dal generatore ufficiale di WordPress e aggiungi un paio di protezioni nel wp-config.php:
|
1 2 3 |
// wp-config.php — rigenera le SALTS dal generatore ufficiale define('DISALLOW_FILE_EDIT', true); define('FORCE_SSL_ADMIN', true); |
Blocca l’esecuzione di PHP in /uploads (in una cartella di sole immagini, PHP non deve girare):
Apache (.htaccess dentro uploads):
|
1 |
<FilesMatch "\.php$">Deny from all</FilesMatch> |
Nginx:
|
1 |
location ~* ^/wp-content/uploads/.*\.php$ { return 403; } |
9) Verifiche dopo la pulizia
- Svuota la cache (plugin + CDN) e riabilita le ottimizzazioni un po’ alla volta.
- Chrome DevTools → Network: verifica che non ci siano chiamate a domini sconosciuti né inline script sospetti.
- Google Search Console → Sicurezza: controlla e, se c’erano avvisi, richiedi una revisione.
- Monitora per 48-72 ore, anche da mobile e da reti diverse.
Dove si nasconde il redirect? (mappa rapida)
| Posizione tipica | Segnale | Come si sistema |
|---|---|---|
| .htaccess | RewriteRule verso domini esterni |
Ripristina lo snippet standard di WordPress |
| wp-config.php | include a file nascosti | Rimuovi l’include, reinstalla il core, ruota le SALTS |
| /uploads/ | file .php tra le immagini |
Elimina e blocca l’esecuzione PHP in uploads |
| mu-plugins / plugin | codice offuscato, date anomale | Reinstalla da fonte ufficiale |
| DB (wp_options / wp_posts) | script o iframe in opzioni o contenuti | Pulizia mirata o ripristino da backup precedente |
Prevenzione (dopo aver ripulito)
- Aggiornamenti regolari di core, tema e plugin, con uno staging dove testare prima.
- Principio del minimo privilegio e 2FA per gli account con permessi elevati.
- Backup off-site con un test di ripristino ogni tanto (un backup che non sai ripristinare non è un backup).
- WAF (applicativo o a livello edge) e rate-limit su login e XML-RPC.
- Regole di cache sicure per WooCommerce e controllo dei webhook.
Log di errore WordPress: leggere e risolvere i bug comuni (guida pratica)
Guida completa ai comandi WP-CLI: elenco aggiornato e spiegazione in italiano