Gestisci 50 siti WordPress per i tuoi clienti e ti svegli alle 3 di notte perché uno è stato bucato? Succede. Ci siamo passati. E dopo 15 anni a gestire siti per la Pubblica Amministrazione italiana, agenzie e PMI, abbiamo capito una cosa: la sicurezza WordPress non è un plugin. È un processo.
In questa guida ti mostriamo esattamente come proteggiamo i siti dei nostri clienti con AgencyPilot, quali errori abbiamo commesso (e tu puoi evitare), e come automatizzare il 90% del lavoro di hardening senza perdere il controllo.
TL;DR: Hardening del core + monitoraggio continuo delle vulnerabilità + patching automatico con rollback + incident response documentato. Non servono 15 plugin. Serve un sistema.
Perché le Agenzie WordPress Sono il Bersaglio Perfetto
Un’agenzia che gestisce 50 siti è 50 volte più appetibile di un freelance con 3 progetti. Ogni sito ha le sue credenziali, i suoi plugin, i suoi aggiornamenti saltati. Basta una falla in un plugin dimenticato su un sito secondario e l’attaccante ha un punto d’ingresso.
Secondo il report Wordfence Threat Intelligence 2025, il 97% delle vulnerabilità WordPress sfruttate attivamente riguarda plugin e temi, non il core. Nella nostra esperienza con AgencyPilot, confermiamo: su oltre 200 siti monitorati, zero breach sono arrivate dal core WordPress aggiornato. Tutte dai plugin.
Il problema? Quando gestisci decine di siti, non puoi controllare manualmente ogni aggiornamento. Non puoi aprire 50 dashboard wp-admin ogni mattina. Ti serve automazione. Ma automazione intelligente, con guardrail.
Hardening del Core: Le Basi che Tutti Saltano
Prima di parlare di plugin di sicurezza e WAF, sistemiamo le fondamenta. Queste sono le configurazioni che applichiamo su ogni sito gestito tramite la nostra piattaforma di gestione multi-sito.
File wp-config.php: la prima linea di difesa
// Disabilita l'editor di file nel pannello admin
define('DISALLOW_FILE_EDIT', true);
// Forza SSL per l'area admin
define('FORCE_SSL_ADMIN', true);
// Limita le revisioni dei post (riduce il DB bloat)
define('WP_POST_REVISIONS', 5);
// Disabilita il debug in produzione
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);
// Blocca installazione plugin/temi da admin
define('DISALLOW_FILE_MODS', true);
// Cambia il prefisso tabelle (durante setup, non dopo)
$table_prefix = 'wp_x7k_';
DISALLOW_FILE_MODS è la costante più sottovalutata. Blocca qualsiasi modifica al filesystem da wp-admin. Se un attaccante ottiene accesso admin, non può caricare una backdoor tramite il pannello plugin. Punto.
Permessi file e directory
# Imposta permessi corretti ricorsivamente
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
# wp-config.php: solo lettura per il webserver
chmod 440 /var/www/html/wp-config.php
# .htaccess: protetto
chmod 444 /var/www/html/.htaccess
Semplice? Sì. Ma nella nostra esperienza, il 60% dei siti che prendiamo in gestione ha permessi 777 su qualche directory. Ogni volta.
Headers di sicurezza via Nginx
# Security headers - configurazione Nginx
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https:; connect-src 'self' https:;" always;
Lo stack che usiamo è Nginx + PHP-FPM + Debian. Se usi Apache, la logica è la stessa, cambiano le direttive. Ma onestamente? Passa a Nginx. La differenza di performance WordPress con Nginx è misurabile.
Monitoraggio Vulnerabilità: Sapere Prima che Succeda
L’hardening ti protegge dal 70%. Il monitoraggio ti copre il resto. Ecco cosa monitoriamo su ogni sito in AgencyPilot.
Scansione plugin vulnerabili
Usiamo il database Wordfence Threat Intelligence e il Patchstack vulnerability database come fonti primarie. Ogni 6 ore, AgencyPilot controlla la versione di ogni plugin installato sui siti gestiti e la confronta con le CVE note.
Quando trova un match, succedono tre cose:
- Alert immediato su Slack/Discord con severity score CVSS
- Se esiste un aggiornamento che risolve la CVE, proposta di patching automatico
- Se non esiste patch, disattivazione temporanea del plugin con notifica al cliente
Drastic? Forse. Ma un plugin vulnerabile attivo è peggio di un plugin disattivato. Sempre.
Monitoraggio integrità file
File integrity monitoring (FIM) confronta gli hash SHA-256 dei file core di WordPress con quelli ufficiali. Se qualcosa cambia senza un aggiornamento pianificato, è un red flag.
# Verifica integrità core WordPress via WP-CLI
wp core verify-checksums --path=/var/www/html
# Output atteso: Success: WordPress installation verifies against checksums.
# Se esce qualcos'altro, hai un problema.
Questo comando lo eseguiamo quotidianamente su tutti i siti gestiti. WP-CLI è il coltellino svizzero dell’amministrazione WordPress su scala. Se non lo usi ancora, stai perdendo tempo.
Patching Automatico con Rollback: Aggiornare Senza Paura
Aggiornare i plugin è la cosa più importante e la più spaventosa per un’agenzia. Perché un aggiornamento che rompe il sito di un cliente è peggio di una vulnerabilità teorica. Almeno, così la pensano in tanti.
Sbagliato. Ma capisco il ragionamento.
Ecco come abbiamo risolto il dilemma in AgencyPilot, e come puoi farlo anche tu con un sistema di automazione WordPress.
Il workflow di patching sicuro
- Backup pre-aggiornamento — snapshot completo (file + database) prima di toccare qualsiasi cosa
- Aggiornamento in staging — se il sito ha un ambiente di staging, aggiorna lì prima
- Health check post-aggiornamento — verifica che il sito risponda correttamente (HTTP 200, nessun errore PHP fatale, homepage carica)
- Rollback automatico — se l’health check fallisce, ripristina il backup in meno di 60 secondi
- Report — log completo di cosa è stato aggiornato, su quale sito, con quale esito
#!/bin/bash
# Script semplificato di patching con rollback
SITE_PATH="/var/www/html"
BACKUP_DIR="/backups/$(date +%Y%m%d_%H%M%S)"
# 1. Backup
mkdir -p "$BACKUP_DIR"
wp db export "$BACKUP_DIR/db.sql" --path="$SITE_PATH"
rsync -a "$SITE_PATH/wp-content/" "$BACKUP_DIR/wp-content/"
# 2. Aggiorna plugin
wp plugin update --all --path="$SITE_PATH" 2>&1 | tee "$BACKUP_DIR/update.log"
# 3. Health check
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://example.com)
if [ "$HTTP_CODE" != "200" ]; then
echo "ERRORE: Sito non risponde ($HTTP_CODE). Rollback in corso..."
wp db import "$BACKUP_DIR/db.sql" --path="$SITE_PATH"
rsync -a "$BACKUP_DIR/wp-content/" "$SITE_PATH/wp-content/"
echo "Rollback completato."
exit 1
fi
echo "Aggiornamento completato con successo."
Questo è uno script base. In produzione con AgencyPilot aggiungiamo controlli più granulari: verifica delle Core Web Vitals post-update, check sui log PHP, test dei form di contatto. Ma il concetto è questo: aggiorna, verifica, rollback se serve.
Gestione Credenziali e Accessi su Scala
50 siti significa potenzialmente 200+ coppie username/password se contiamo admin, SFTP, database, hosting panel. Un incubo di gestione credenziali.
Le regole che applichiamo
Primo: niente username “admin”. Mai. Su nessun sito. Se prendiamo in gestione un sito con utente admin, lo cambiamo il giorno zero.
Secondo: Application Passwords di WordPress (introdotte nel core con WP 5.6) per tutti gli accessi programmatici. Niente credenziali admin nei cron job o negli script di automazione. Ogni integrazione ha la sua Application Password con scope limitato.
# Crea un Application Password via WP-CLI
wp user application-password create admin "AgencyPilot Monitoring" --path=/var/www/html
# Output: password monouso da usare per le API REST
# Questo accesso può essere revocato senza toccare la password principale
Terzo: autenticazione a due fattori (2FA) obbligatoria su tutti gli account admin. Non opzionale. Non “consigliata”. Obbligatoria. Il plugin Two Factor è la soluzione più pulita: usa TOTP standard, nessun vendor lock-in.
Quarto: rotazione credenziali ogni 90 giorni. Con AgencyPilot questo è automatizzato. Senza, devi metterlo in calendario e farlo. Ogni trimestre.
WAF e Rate Limiting: Bloccare il Rumore
Un Web Application Firewall (WAF) a livello di server è la differenza tra gestire 50 siti e passare le giornate a pulire log di attacchi brute force.
Rate limiting su wp-login.php e xmlrpc.php
# Nginx rate limiting per wp-login.php
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=3r/m;
server {
# Limita tentativi di login a 3 al minuto per IP
location = /wp-login.php {
limit_req zone=wplogin burst=3 nodelay;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Blocca completamente xmlrpc.php (se non serve)
location = /xmlrpc.php {
deny all;
return 403;
}
# Proteggi wp-config.php dall'accesso diretto
location = /wp-config.php {
deny all;
}
# Blocca accesso a file sensibili
location ~* /(wp-config\.php|\.htaccess|\.env|readme\.html|license\.txt) {
deny all;
}
}
xmlrpc.php è responsabile di una quantità assurda di traffico malevolo. A meno che tu non stia usando l’app mobile di WordPress o Jetpack (e non dovresti usare Jetpack su siti in produzione, ma quello è un altro discorso), bloccalo. Punto.
Cloudflare come primo livello
Per i siti dei clienti usiamo Cloudflare free tier come CDN e primo livello di protezione. Non per le funzionalità avanzate WAF (quelle costano), ma per:
- DDoS mitigation di base (automatica)
- Bot management (riduce il 40-60% del traffico malevolo)
- SSL terminato al edge (riduce carico sul server)
- Caching delle risorse statiche
Gratis. Per 50 siti. Non c’è motivo per non usarlo.
Incident Response: Quando il Sito È Già Bucato
Succede. Con 50 siti, prima o poi succede. La differenza tra un’agenzia seria e una improvvisata è cosa fai nei primi 30 minuti.
La nostra procedura di incident response
- Isolamento (minuti 0-5) — Metti il sito in manutenzione. Blocca l’accesso admin. Non spegnere il server (perdi i log in memoria).
- Analisi (minuti 5-15) — Controlla access.log e error.log. Cerca richieste POST anomale verso wp-admin, wp-content/uploads, o endpoint REST inusuali. Identifica il vettore d’attacco.
- Contenimento (minuti 15-25) — Cambia tutte le credenziali: database, admin, SFTP, application passwords. Revoca i token di sessione WordPress con
wp_get_session_tokens(). - Pulizia (minuti 25-60) — Confronta i file con una copia pulita. Cerca backdoor nei file PHP (pattern comuni:
eval(base64_decode(,assert(,$_POST['cmd']). Controlla i cron job di WordPress per task malevoli. - Ripristino — Se la pulizia manuale non è sufficiente, ripristina da backup verificato precedente all’attacco.
- Post-mortem — Documenta tutto. Cosa è successo, come è successo, come prevenirlo. Condividi con il team.
# Cerca backdoor comuni nel filesystem WordPress
find /var/www/html -name "*.php" -exec grep -l "eval(base64_decode" {} \;
find /var/www/html -name "*.php" -exec grep -l "\$_POST\['cmd'\]" {} \;
find /var/www/html -name "*.php" -exec grep -l "assert(\$_" {} \;
# Controlla file modificati nelle ultime 48 ore
find /var/www/html -name "*.php" -mtime -2 -ls
# Controlla cron job WordPress per task sospetti
wp cron event list --path=/var/www/html
Questo non è teoria. L’abbiamo usato. L’ultimo incidente che abbiamo gestito con questa procedura, la causa era un plugin di form builder con una vulnerabilità di file upload non autenticato. Il plugin era aggiornato, ma la patch era uscita 4 ore prima e non era stata applicata. Quattro ore.
Checklist di Sicurezza WordPress per Agenzie
Ecco la checklist che applichiamo su ogni sito gestito. Copiala, adattala, usala.
| Area | Azione | Frequenza |
|---|---|---|
| Core | Aggiornamento WordPress all’ultima versione | Entro 24h dal rilascio |
| Plugin | Aggiornamento plugin con workflow patching sicuro | Settimanale |
| Plugin | Rimozione plugin inattivi | Mensile |
| Temi | Rimozione temi non utilizzati (tieni solo l’attivo + un default) | Mensile |
| Credenziali | Rotazione password admin e Application Passwords | Trimestrale |
| 2FA | Verifica che tutti gli admin abbiano 2FA attivo | Mensile |
| Backup | Verifica integrità backup e test di ripristino | Mensile |
| SSL | Verifica scadenza certificati SSL | Settimanale (automatizzabile) |
| Log | Revisione log di accesso per anomalie | Settimanale |
| FIM | Scansione integrità file core | Giornaliera (automatica) |
| CVE | Controllo vulnerabilità note su plugin installati | Ogni 6 ore (automatica) |
| Headers | Verifica security headers attivi | Dopo ogni deploy |
Con AgencyPilot, 9 di queste 12 azioni sono automatizzate. Le altre 3 (rimozione plugin/temi, revisione log, test ripristino) richiedono giudizio umano. E va bene così. L’automazione gestisce il ripetitivo. Tu gestisci le decisioni.
Errori Comuni che Vediamo nelle Agenzie
Dopo 15 anni e centinaia di siti presi in gestione, questi sono gli errori che vediamo ripetersi:
“Uso un plugin di sicurezza, quindi sono protetto.” No. Un plugin di sicurezza è uno strato. Senza hardening a livello server, permessi file corretti e monitoraggio, è come mettere un allarme su una casa con la porta aperta.
“Non aggiorno perché potrebbe rompere qualcosa.” Non aggiornare è la scelta più rischiosa che puoi fare. Un plugin con una CVE nota non patchata è un invito aperto. Usa il workflow di patching con rollback e il problema scompare.
“Il mio hosting si occupa della sicurezza.” L’hosting gestisce l’infrastruttura. La sicurezza applicativa è responsabilità tua. Nessun hosting shared al mondo ti protegge da un plugin vulnerabile installato nel tuo WordPress.
“Abbiamo il backup, quindi siamo al sicuro.” Un backup è inutile se non lo testi. Hai mai provato a ripristinare? Sai quanto ci metti? Se la risposta è no, il backup non ti protegge. È solo un file che occupa spazio.
FAQ sulla Sicurezza WordPress per Agenzie
Qual è il miglior plugin di sicurezza per WordPress nel 2026?
Non esiste “il migliore” in assoluto. Wordfence è solido per il firewall applicativo e la scansione malware. Patchstack è superiore per il monitoraggio vulnerabilità plugin. Ma nessun plugin sostituisce l’hardening a livello server (Nginx rate limiting, permessi file, headers di sicurezza). Usa un plugin come complemento, non come soluzione unica.
Quanto costa un attacco WordPress a un’agenzia?
Dipende dalla gravità. Un defacement semplice costa 2-4 ore di lavoro per la pulizia e il danno reputazionale con il cliente. Un data breach con dati personali (GDPR) può costare sanzioni fino al 4% del fatturato annuo. Il costo medio di downtime per un sito aziendale? Tra 200€ e 2.000€ all’ora in mancato fatturato, a seconda del business. La prevenzione costa una frazione.
Devo disabilitare XML-RPC su WordPress?
Sì, a meno che non usi l’app mobile WordPress, Jetpack, o integrazioni che lo richiedono specificamente. XML-RPC è il vettore più comune per attacchi brute force e DDoS amplification su WordPress. Bloccalo a livello Nginx (non con un plugin, che lo processa comunque prima di bloccarlo).
Come gestisco la sicurezza WordPress su 50+ siti senza un team dedicato?
Automazione. Patching automatico con rollback, monitoraggio vulnerabilità con alert, scansione integrità file schedulata, e una dashboard centralizzata. È esattamente quello che fa AgencyPilot. Ma anche senza il nostro tool, puoi costruire un sistema simile con WP-CLI, cron job Linux, e uno script di monitoraggio. Richiede setup iniziale, poi gira da solo.
Ogni quanto devo aggiornare WordPress e i plugin?
WordPress core: entro 24 ore dal rilascio (le minor release sono quasi sempre patch di sicurezza). Plugin: settimanalmente per aggiornamenti normali, immediatamente se c’è una CVE nota. Temi: stessa logica dei plugin. Non lasciare mai un aggiornamento di sicurezza in attesa più di 48 ore.