La sicurezza WordPress per agenzie che gestiscono decine o centinaia di siti è un problema completamente diverso dalla sicurezza di un singolo sito. Quando gestisci 50 installazioni WordPress, un singolo plugin vulnerabile diventa 50 porte aperte. In questa guida condividiamo le pratiche di hardening che applichiamo ogni giorno su AgencyPilot per proteggere i siti dei nostri clienti.
Perché la Sicurezza WordPress per Agenzie è Diversa
La differenza fondamentale tra gestire un sito WordPress e gestirne cento sta nella superficie di attacco. Ogni installazione ha il suo wp-config.php, il suo database, i suoi plugin, i suoi utenti admin. Un attacco automatizzato non colpisce un sito alla volta: scansiona interi range di IP alla ricerca di versioni vulnerabili specifiche.
Nella nostra esperienza, il 90% delle compromissioni che abbiamo rilevato negli ultimi tre anni segue lo stesso pattern:
- Un plugin con vulnerabilità nota (CVE pubblicata da settimane)
- Aggiornamento non applicato perché il cliente non ha autorizzato il downtime
- Exploit automatizzato che inietta codice nel
wp-load.phpo nei file del tema - Redirection malevola o script di crypto-mining inserito nel footer
Questo pattern si ripete perché le agenzie non hanno un processo sistematico. Aggiornano quando il cliente lo chiede, non quando la CVE viene pubblicata.
Audit di Sicurezza: Da Dove Iniziare
Prima di applicare qualsiasi hardening, serve sapere in che stato si trovano i siti. Un audit di sicurezza WordPress dovrebbe coprire almeno questi cinque punti:
| Area | Cosa controllare | Tool consigliati |
|---|---|---|
| Core WordPress | Versione core, file checksum | WP-CLI core verify-checksums |
| Plugin e Temi | Vulnerabilità note (CVE), versioni aggiornate | WPScan, Patchstack |
| Configurazione server | Permessi file, PHP version, TLS | Lynis, testssl.sh |
| Utenti e ruoli | Account admin non necessari, password deboli | WP-CLI user list |
| Database | Prefisso tabelle non standard, password DB | Inspezione manuale wp-config.php |
Per un audit rapido su tutti i siti, usiamo questo comando WP-CLI eseguito in batch:
# Verifica checksum core su tutti i siti
wp site list --field=url | xargs -I {} wp core verify-checksums --path={}
# Lista plugin con vulnerabilità note (richiede WPScan API token)
wpscan --url https://example.com --enumerate vp --api-token TOKEN
# Conta utenti admin per ogni sito
wp site list --field=url | xargs -I {} wp user list --role=administrator --format=count --path={}
Questi comandi danno un’istantanea dello stato di sicurezza in pochi minuti. Se gestisci molti siti, un sistema centralizzato come AgencyPilot automata questi controlli su tutti i siti dall’ stesso pannello.
Hardening WordPress: 10 Azioni Obbligatorie
Queste sono le 10 azioni di hardening che applichiamo su ogni installazione WordPress che gestiamo. Nessuna è opzionale.
1. Aggiornamenti Automatici del Core
WordPress può aggiornare il core automaticamente per le release di sicurezza. Abilitatelo sempre, anche sui siti dei clienti più conservativi. Una release di sicurezza di WordPress core non introduce breaking changes:
// wp-config.php
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
Per i plugin, usate wp cli cron event run wp_update_plugins su base settimanale almeno. Su AgencyPilot, gli aggiornamenti plugin vengono eseguiti automaticamente di notte con rollback in caso di errori fatali.
2. Firewall WAF a Livello Server
Un plugin di sicurezza WordPress opera dentro l’applicazione, il che significa che il traffico malevolo raggiunge comunque PHP. Un WAF a livello server blocca prima che arrivi a WordPress. Due opzioni concrete:
- Cloudflare WAF — gratis nel piano Pro, regole gestite per WordPress, blocca SQL injection e XSS prima che raggiungano il server
- ModSecurity + OWASP CRS — on-premise con Nginx o Apache, configurazione manuale ma zero dipendenze esterne
Configurazione ModSecurity minima su Nginx:
# /etc/nginx/modsec/modsecurity.conf
SecRuleEngine On
SecRequestBodyAccess On
SecRule REQUEST_URI "wp-login\.php" "id:1001,phase:1,pass,nolog,ctl:ruleEngine=DetectionOnly"
# Importa OWASP CRS
Include /etc/nginx/modsec/crs/*.conf
3. Limitare Login Attempts
Gli attacchi brute force su wp-login.php e /xmlrpc.php sono il vettore più comune. Due approcci:
Livello server (preferito, zero overhead PHP):
# /etc/nginx/conf.d/wordpress-security.conf
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=5r/m;
location = /wp-login.php {
limit_req zone=wplogin burst=5 nodelay;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
# ... resto della configurazione
}
location = /xmlrpc.php {
deny all;
# Disabilita XML-RPC completamente se non usato
}
Livello plugin (se non hai accesso al server): il plugin Limit Login Attempts Reloaded o Wordfence Login Security.
4. Disabilitare XML-RPC
XML-RPC è il vettore di attacco più sottovalutato. Permette brute force tramite system.multicall, che invia centinaia di credenziali in una singola richiesta HTTP. Se non usate l’app mobile WordPress o Jetpack, disabilitatelo:
# functions.php del tema
add_filter( 'xmlrpc_enabled', '__return_false' );
# Oppure a livello server: deny all su /xmlrpc.php
5. Rinominare wp-config.php e Spostare la Cartella wp-content
Queste due tecniche riducono la superficie di attacco dei bot automatizzati che cercano path prevedibili:
// wp-config.php
define( 'WP_CONTENT_DIR', dirname( __FILE__ ) . '/assets' );
define( 'WP_CONTENT_URL', 'https://' . $_SERVER['HTTP_HOST'] . '/assets' );
Attenzione: questo richiede aggiornamenti ai path di plugin e temi. Testate su staging prima di applicare in produzione.
6. Permessi File Corretti
Questa è la regola fondamentale: i file WordPress devono essere leggibili dal web server, ma wp-config.php non deve mai essere servito come statico. I permessi corretti:
# Directory: 755
find /var/www/wordpress -type d -exec chmod 755 {} \;
# File: 644
find /var/www/wordpress -type f -exec chmod 644 {} \;
# wp-config.php: 600 (solo il proprietario può leggere)
chmod 600 /var/www/wordpress/wp-config.php
Su Debian con Nginx + PHP-FPM, il proprietario deve essere www-data:www-data per le directory scrivibili e l’utente SSH per i file statici.
7. HTTPS e TLS ovunque
Nessun sito WordPress dovrebbe girare su HTTP nel 2026. La configurazione Nginx minima per TLS 1.2+:
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
Forzate HTTPS nel wp-config.php prima che WordPress carichi:
define( 'FORCE_SSL_ADMIN', true );
if ( strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) !== false ) {
$_SERVER['HTTPS'] = 'on';
}
8. Backup Off-site Automatizzati
Un backup sullo stesso server del sito non è un backup. Se il server viene compromesso, anche il backup lo è. La strategia che usiamo su AgencyPilot:
- Backup database —
mysqldumpogni notte, compresso e inviato a un bucket S3 compatibile - Backup file — rsync incrementale ogni 6 ore verso storage separato
- Retention — 30 giorni di backup giornalieri, 12 mensili
- Test di restore — ogni mese, restore su ambiente staging e verifica integrità
Per approfondire, leggi la nostra guida completa al backup WordPress per agenzie.
9. Monitoraggio File con Integrity Check
Quando un attacco ha successo, il primo segnale è quasi sempre un file modificato. Un integrity check regolare rileva modifiche non autorizzate:
#!/bin/bash
# integrity-check.sh — genera hash dei file core
WP_ROOT="/var/www/wordpress"
HASH_FILE="/var/backups/wp-hashes.txt"
# Prima esecuzione: genera baseline
if [ ! -f "$HASH_FILE" ]; then
find "$WP_ROOT/wp-admin" "$WP_ROOT/wp-includes" -type f -exec sha256sum {} \; > "$HASH_FILE"
echo "Baseline creata"
exit 0
fi
# Verifica
find "$WP_ROOT/wp-admin" "$WP_ROOT/wp-includes" -type f -exec sha256sum {} \; | diff - "$HASH_FILE" | grep "^[<>]"
Se l’output mostra file modificati che non corrispondono a un aggiornamento core, avvia un’investigazione immediata. AgencyPilot automatizza questo controllo su tutti i siti gestiti e invia alert su Discord quando rileva modifiche.
10. Principio del Minimo Privilegio per Utenti e Database
Ogni utente WordPress dovrebbe avere il ruolo minimo necessario. Un editor non ha bisogno di capability admin. A livello database, l’utente MySQL del sito non deve avere privilegi GRANT o SUPER:
-- Crea utente MySQL con privilegi minimi
CREATE USER 'wp_site'@'localhost' IDENTIFIED BY 'password-forte';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP
ON wordpress_db.* TO 'wp_site'@'localhost';
-- Niente GRANT OPTION, niente SUPER, niente FILE
FLUSH PRIVILEGES;
Sicurezza WordPress Multi-Sito: Gestione Centralizzata
Quando gestisci più di 10 siti WordPress, l’hardening manuale diventa insostenibile. Le agenzie hanno bisogno di un approccio centralizzato. Ecco come strutturiamo la sicurezza multi-sito su AgencyPilot:
Dashboard di Sicurezza Unificata
Invece di controllare ogni sito individualmente, una dashboard centralizzata mostra:
- Versione core di ogni sito (con alert se non aggiornata)
- Lista plugin vulnerabili su tutti i siti (integrazione Patchstack)
- Stato TLS e scadenza certificati
- Log di accesso sospetti aggregati
- Stato backup e ultimo test di restore
Automazione degli Aggiornamenti
Gli aggiornamenti sono il singolo intervento di sicurezza più efficace. Secondo i dati di Patchstack, oltre l’80% delle vulnerabilità WordPress risiede nei plugin, non nel core. Un processo di aggiornamento automatico sicuro deve includere:
- Snapshot — backup completo prima dell’aggiornamento
- Staging test — applicazione su clone e smoke test
- Rollback — ripristino automatico se il sito va in fatal error
- Notifica — report di what changed e stato post-aggiornamento
Monitoraggio Proattivo e Incident Response
La sicurezza non si ferma all’hardening. Serve monitoraggio continuo e un piano di risposta agli incidenti. Questi sono i segnali che monitoriamo costantemente:
Segnali di Compromissione
| Segnale | Come rilevarlo | Gravità |
|---|---|---|
| File core modificati | Checksum diff vs repository ufficiale | Alta |
| Account admin non riconosciuti | Confronto utenti vs baseline | Critica |
| Spike traffico da IP singolo | Access log analysis, fail2ban | Media |
| Redirect a domini sconosciuti | Header check automatizzato | Critica |
| File PHP in wp-content/uploads | Scan directory uploads | Critica |
Piano di Incident Response
Quando rilevi una compromissione, i primi 15 minuti contano. Il nostro protocollo:
- Isola — metti il sito in maintenance mode, blocca traffico esterno via firewall
- Snapshot — cattura stato attuale (file + database) per analisi forense
- Pulisci — ripristina da backup notturno, non tentare di pulire manualmente
- Aggiorna — applica tutti gli aggiornamenti core e plugin
- Cambia credenziali — tutte: database, admin WP, SSH, FTP
- Documenta — timeline dell’incident, causa root, azioni correttive
Il ripristino da backup pulito è sempre preferito alla pulizia manuale. Un attaccante può nascondere backdoor in decine di file, e trovarle tutte manualmente è quasi impossibile.
Strumenti di Sicurezza Consigliati per Agenzie
Non tutti i tool di sicurezza WordPress sono creati uguali. Per un’agenzia che gestisce multi-sito, il costo e la gestione di license individuali diventano proibitivi. Ecco il nostro stack consigliato:
| Tool | Funzione | Costo | Adatto a multi-sito |
|---|---|---|---|
| Cloudflare WAF | Firewall edge, DDoS protection | Gratis – $20/mese per sito | Sì, dashboard unificata |
| Wordfence CLI | Scanner malware, integrity check | Sì, versione CLI | |
| Patchstack | Vulnerability intelligence | $99/mese (agenzia) | Sì, API per automazione |
| WPScan | Scanner vulnerabilità | Gratis / $25/mese Pro | Manuale per sito |
| Lynis | Audit hardening server | Gratis | Sì, per-server |
Il tool più costoso non è necessariamente il migliore. Abbiamo confrontato AgencyPilot con ManageWP e MainWP e la differenza principale sta nell’automazione: un tool che richiede intervento manuale per ogni aggiornamento non scala quando gestisci 50+ siti.
FAQ: Sicurezza WordPress per Agenzie
Quanto spesso devo aggiornare i plugin WordPress?
Subito dopo il rilascio di una patch di sicurezza. Per gli aggiornamenti non di sicurezza, una volta alla settimana è sufficiente. Il rischio maggiore non è l’aggiornamento che rompe il sito, è il plugin vulnerabile che resta non aggiornato per settimane.
Wordfence o Sucuri: quale è meglio per agenzie?
Per multi-sito, Wordfence CLI è più pratico perché può essere automatizzato via script. Sucuri offre un servizio gestito di cleanup che è utile se non hai competenze interne, ma il costo per sito si moltiplica rapidamente. Per agenzie con competenze tecniche, Wordfence + Cloudflare WAF è la combinazione più economica e altrettanto efficace.
Come rilevo se un sito WordPress è stato hackerato?
I segnali principali sono: file PHP nella cartella uploads/, modifiche ai file core (rilevabili con wp core verify-checksums), account admin non riconosciuti, redirect non autorizzati, e spike di traffico da IP specifici nei log. Un integrity check automatizzato è il metodo più affidabile per rilevare compromissioni precocemente.
XML-RPC va disabilitato sempre?
No, ma va disabilitato se non lo usi. Se usi l’app mobile WordPress, Jetpack, o plugin che richiedono pingback, XML-RPC deve restare attivo. In quel caso, limita l’accesso tramite firewall ai soli IP autorizzati invece di disabilitarlo completamente.
Qual è la cosa più importante per la sicurezza WordPress multi-sito?
L’automazione degli aggiornamenti. Il 90% delle compromissioni sfrutta vulnerabilità note con patch già disponibili. Se aggiorni entro 48 ore dal rilascio della patch, riduci il rischio del 90%. Tutto il resto (WAF, backup, hardening) è importante, ma gli aggiornamenti tempestivi sono il singolo intervento più efficace.