Two-factor authentication WordPress: perché la password non basta più

Il brute force non è più il vettore principale — le credenziali rubate sì. La password, anche forte, è un singolo fattore che può essere compromesso. Il 2FA è l'unica difesa che ferma l'accesso anche quando la password è trapelata. Come implementarlo senza frustrare gli utenti legittimi.
Il modo in cui i siti WordPress vengono compromessi è cambiato. Dieci anni fa era quasi tutto brute force — bot che provavano migliaia di password su wp-login.php. Oggi il brute force è ancora attivo, ma il vettore principale è diverso: credenziali rubate. Password che finiscono in database trapelati da altri siti, phishing mirato, infostealer che rubano le credenziali salvate nel browser. La password, anche forte, è un singolo fattore — e un singolo fattore può sempre essere compromesso.
Il two-factor authentication (2FA) aggiunge un secondo fattore: qualcosa che sai (password) più qualcosa che hai (il telefono, una chiave hardware). Anche se la password viene rubata, l'attaccante non può accedere senza il secondo fattore. È l'unica difesa che rimane efficace quando il primo fattore è compromesso — ed è per questo che è diventato uno standard de facto per l'accesso amministrativo.
I tre tipi di 2FA (e quale scegliere)
Il 2FA non è tutto uguale. Ci sono tre metodi principali, con livelli di sicurezza e usabilità diversi. Il primo è il 2FA via SMS: il sito invia un codice via SMS. È il più facile da implementare ma il meno sicuro — il SIM swapping permette a un attaccante di prendere controllo del numero di telefono e ricevere i codici. Google e Microsoft hanno deprecato il 2FA via SMS per i loro account, e per buone ragioni.
Il secondo è il 2FA via app authenticator (Google Authenticator, Authy, Microsoft Authenticator): l'app genera un codice a sei cifre che cambia ogni 30 secondi. Non dipende dal operatore telefonico, non è vulnerabile al SIM swapping, ed è gratuito. È il metodo che raccomandiamo per la maggior parte dei siti WordPress.
Il terzo è la chiave hardware (YubiKey, Titan): un dispositivo fisico che devi toccare per autenticarti. È il più sicuro — immune al phishing perché la chiave verifica il dominio del sito — ma ha un costo (30-50€ per chiave) e richiede che l'utente la abbia fisicamente con sé. Per account amministrativi di siti ad alto valore, è la scelta migliore.
Implementazione: il pattern che usiamo
Per implementare il 2FA su WordPress, il modo più affidabile è un plugin dedicato. Ma se vuoi implementarlo in codice custom (es. per un'integrazione specifica), ecco il pattern con un'app authenticator e la libreria PHP per TOTP:
<?php
// Implementazione 2FA TOTP custom (semplificata)
// Richiede la libreria PHP otphp (composer require spomky-labs/otphp)
use OTPHP\TOTP;
// 1. Genera un secret per l'utente (una volta sola, al setup)
function wp_planet_generate_2fa_secret( $user_id ) {
$totp = TOTP::generate();
$secret = $totp->getSecret();
update_user_meta( $user_id, 'wp_planet_2fa_secret', $secret );
update_user_meta( $user_id, 'wp_planet_2fa_enabled', true );
// Genera l'URI per il QR code
$totp->setLabel( get_userdata( $user_id )->user_email );
$totp->setIssuer( get_bloginfo( 'name' ) );
return $totp->getProvisioningUri();
}
// 2. Verifica il codice inserito dall'utente al login
function wp_planet_verify_2fa_code( $user_id, $code ) {
$secret = get_user_meta( $user_id, 'wp_planet_2fa_secret', true );
if ( ! $secret ) return false;
$totp = TOTP::createFromSecret( $secret );
return $totp->verify( $code );
}
// 3. Hook nel processo di login: richiedi 2FA dopo la password
add_filter( 'authenticate', function( $user, $username, $password ) {
if ( is_wp_error( $user ) || ! $user instanceof WP_User ) {
return $user;
}
$enabled = get_user_meta( $user->ID, 'wp_planet_2fa_enabled', true );
if ( ! $enabled ) return $user;
// Se il 2FA non è stato ancora inviato, ferma l'autenticazione
// e mostra il form del codice 2FA
$two_factor_code = $_POST['two_factor_code'] ?? '';
if ( empty( $two_factor_code ) ) {
// Mostra il form 2FA (gestito dal template)
return new WP_Error(
'two_factor_required',
'Inserisci il codice 2FA dalla tua app authenticator.'
);
}
if ( ! wp_planet_verify_2fa_code( $user->ID, $two_factor_code ) ) {
return new WP_Error(
'invalid_two_factor',
'Codice 2FA non valido. Riprova.'
);
}
return $user;
}, 30, 3 );Codici di backup: il piano B che ti salva
Il rischio del 2FA è perdere l'accesso al secondo fattore: il telefono si rompe, l'app viene disinstallata, la chiave hardware si perde. Senza un piano di recupero, l'utente è bloccato fuori dal suo account — e per un amministratore WordPress, questo significa bloccato fuori dal sito. La soluzione sono i codici di backup: 10 codici monouso generati al setup del 2FA, da stampare e conservare in luogo sicuro.
<?php
// Generazione di codici di backup monouso
function wp_planet_generate_backup_codes( $user_id ) {
$codes = array();
for ( $i = 0; $i < 10; $i++ ) {
// Codice di 8 caratteri alfanumerici
$codes[] = strtoupper( wp_generate_password( 8, false ) );
}
// Salva i codici come hash (mai in chiaro)
$hashed = array_map( 'wp_hash_password', $codes );
update_user_meta( $user_id, 'wp_planet_2fa_backup_codes', $hashed );
return $codes; // Mostra all'utente una volta sola
}
// Verifica un codice di backup (e lo consuma)
function wp_planet_verify_backup_code( $user_id, $code ) {
$hashed = get_user_meta( $user_id, 'wp_planet_2fa_backup_codes', true );
if ( ! is_array( $hashed ) ) return false;
foreach ( $hashed as $i => $hash ) {
if ( wp_check_password( $code, $hash ) ) {
// Consuma il codice (rimuovilo dalla lista)
unset( $hashed[ $i ] );
update_user_meta( $user_id, 'wp_planet_2fa_backup_codes', array_values( $hashed ) );
return true;
}
}
return false;
}Chi deve avere il 2FA (e chi no)
Il 2FA su WordPress dovrebbe essere obbligatorio per tutti gli utenti con ruolo amministrativo o che possono pubblicare/modificare contenuti. Per i ruoli inferiori (subscriber, customer in WooCommerce), il 2FA è opzionale — il rischio di compromissione è minore e l'attrito per l'utente non è giustificato. La regola: se l'account può modificare il sito o accedere a dati sensibili, il 2FA è obbligatorio.
Il 2FA non è un lusso — è la differenza tra un sito che resiste alle credenziali rubate e uno che cede al primo database trapelato. La password, per quanto forte, è un singolo punto di failure. Il 2FA lo raddoppia, e per un sito aziendale, quel raddoppio è la differenza tra una giornata normale e una settimana di emergenza.
Verifica la sicurezza del tuo WordPress prima che diventi un'emergenza.
Un audit di sicurezza individua le falle, i plugin vulnerabili e le configurazioni deboli prima che qualcuno le sfrutti.
Articoli correlati

Plugin di sicurezza WordPress: quali servono davvero, quali sono sovrapposti e perché tre plugin fanno meno danni di uno
Leggi
Log di sicurezza WordPress: cosa monitorare, come e perché un audit trail vale più di tre plugin di sicurezza
Leggi
