wp-login.php Riceve Centinaia di Attacchi al Giorno. Ecco 5 Modi per Fermarlo.
Apri i log di accesso del tuo server. Cerca “wp-login.php”. Conta le righe. Se il tuo sito è online da più di una settimana, vedrai centinaia (o migliaia) di tentativi di login da IP sparsi per il mondo.
Non è un attacco mirato a te. Sono bot che scannerizzano internet 24/7 cercando siti WordPress con credenziali deboli. L’equivalente digitale di qualcuno che prova tutte le maniglie delle porte in un quartiere.
Questi 5 metodi funzionano. Li usiamo su ogni installazione WordPress che gestiamo. Sono cumulabili: non devi sceglierne uno, usali tutti.
Metodo 1: 2FA Obbligatorio (Il Più Importante)
Anche se un attaccante indovina username e password, senza il secondo fattore non entra. Fine.
Plugin raccomandato: WP 2FA (di WP White Security). Supporta TOTP (Google Authenticator, Authy), email, e backup codes.
Configurazione chiave: rendi il 2FA obbligatorio per tutti i ruoli admin e editor. Non opzionale. Se è opzionale, nessuno lo attiva.
// Forza 2FA per admin e editor (se il plugin non ha l'opzione)
add_action('admin_init', function() {
if (!is_user_logged_in()) return;
$user = wp_get_current_user();
$requires_2fa = array_intersect(['administrator', 'editor'], $user->roles);
if ($requires_2fa && !get_user_meta($user->ID, '2fa_configured', true)) {
// Redirect alla pagina setup 2FA
if (strpos($_SERVER['REQUEST_URI'], '2fa-setup') === false) {
wp_redirect(admin_url('profile.php?2fa-setup=required'));
exit;
}
}
});
Metodo 2: Rate Limiting a Livello Server
Prima ancora che la richiesta arrivi a PHP, il web server la blocca se arriva troppo spesso.
# Nginx: limita wp-login.php a 3 richieste ogni 10 secondi per IP
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=3r/s;
server {
location = /wp-login.php {
limit_req zone=wplogin burst=5 nodelay;
# Passa a PHP normalmente
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Questo è più efficiente di qualsiasi plugin: il bot viene bloccato a livello Nginx, PHP non si avvia nemmeno. Zero carico server per le richieste bloccate.
Metodo 3: Fail2ban per WordPress
Fail2ban analizza i log del server e banna gli IP dopo un numero configurable di tentativi falliti. A differenza del rate limiting Nginx (che limita la frequenza), fail2ban banna completamente l’IP per un periodo.
# /etc/fail2ban/filter.d/wordpress-login.conf
[Definition]
failregex = ^<HOST> .* "POST /wp-login\.php .* 200
ignoreregex =
# /etc/fail2ban/jail.local
[wordpress-login]
enabled = true
filter = wordpress-login
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 3600
action = iptables-multiport[name=wordpress, port="http,https"]
5 tentativi in 5 minuti (findtime=300) = ban per 1 ora (bantime=3600). Per attacchi persistenti, puoi usare bantime.increment = true per ban progressivi (1h, 2h, 4h, 8h…).
Metodo 4: URL Login Personalizzato
Cambiare l’URL di login da /wp-login.php a qualcosa di custom (/accesso-riservato). Non è sicurezza reale (security through obscurity), ma riduce il rumore del 95%.
Plugin: WPS Hide Login. Setup in 2 minuti: installa, vai in Impostazioni → Generali → scorri in fondo, cambia l’URL.
Attenzione: comunica il nuovo URL a tutti gli utenti del sito PRIMA di attivarlo. E annota l’URL da qualche parte. Se lo dimentichi, puoi recuperarlo disabilitando il plugin via FTP (rinomina la cartella del plugin).
Metodo 5: Blocco Accesso per IP (o VPN)
La misura più drastica: solo IP specifici possono accedere a wp-login.php e wp-admin.
# Nginx
location = /wp-login.php {
allow 203.0.113.50; # IP ufficio
allow 198.51.100.0/24; # Range VPN
deny all;
}
location /wp-admin/ {
allow 203.0.113.50;
allow 198.51.100.0/24;
deny all;
# IMPORTANTE: lascia admin-ajax.php aperto (usato dal frontend)
location = /wp-admin/admin-ajax.php { allow all; }
}
Prerequisito: IP statico o VPN. Se lavori da casa con IP dinamico, questo metodo non fa per te (a meno che non usi una VPN con IP fisso).
Per la PA, dove gli accessi avvengono sempre dalla rete dell’ente, è la soluzione ideale.
La Combinazione Raccomandata
| Scenario | Combinazione |
|---|---|
| Blog/sito vetrina | 2FA + Rate Limiting Nginx + WPS Hide Login |
| E-commerce | 2FA + Rate Limiting + Fail2ban + Wordfence |
| PA / Alta sicurezza | 2FA + Blocco IP + Fail2ban + Rate Limiting |
| Agenzia (30 siti) | 2FA obbligatorio + Rate Limiting Nginx + WPS Hide Login su tutti |
Come Verificare che Funziona
# Conta i tentativi di login nelle ultime 24 ore
grep "wp-login.php" /var/log/nginx/access.log | grep "POST" | wc -l
# Conta i ban di fail2ban
sudo fail2ban-client status wordpress-login
# Test il rate limiting (dal tuo IP, con attenzione)
for i in {1..10}; do curl -s -o /dev/null -w "%{http_code}\n" -X POST https://tuosito.com/wp-login.php; done
# Dovresti vedere 200, 200, 200, poi 429 (rate limited)
FAQ
Se cambio l’URL login, i plugin che usano wp-login.php smettono di funzionare?
La maggior parte no. WPS Hide Login fa un redirect trasparente. Plugin come WooCommerce, BuddyPress, e i form di registrazione funzionano normalmente. L’unica eccezione: plugin che hardcodano /wp-login.php nel codice (raro, ma succede). Testa dopo l’attivazione.
Il rate limiting blocca anche i login legittimi?
Solo se inserisci password sbagliata 3+ volte in 10 secondi, il che è praticamente impossibile per un umano. Il burst di 5 nel rate limiting Nginx permette una raffica iniziale (es: refresh della pagina) senza bloccare.
Fail2ban funziona su hosting condiviso?
No. Fail2ban richiede accesso root al server e la possibilità di manipolare iptables. Su hosting condiviso, affidati al rate limiting del plugin di sicurezza (Wordfence) e al 2FA. Se il tuo hosting ha un WAF (Cloudflare, Sucuri), quello fa un lavoro simile.