Regole di sicurezza .htaccess per WordPress che servono davvero
Gran parte di ciò che viene venduto come sicurezza .htaccess per WordPress è solo riempitivo. Le regole che cambiano davvero la tua superficie d'attacco sono poche: ecco quali sono quali
Pubblicato
Gran parte di ciò che viene venduto come “sicurezza .htaccess per WordPress” è solo riempitivo. Le regole che cambiano davvero la tua superficie d’attacco sono poche: bloccare l’esecuzione di PHP dentro wp-content/uploads, negare l’accesso diretto a wp-config.php e disattivare l’indicizzazione delle directory. Quelle più diffuse — bloccare xmlrpc.php “per fermare il brute force”, nascondere la versione di WordPress, incollare una lista di 200 righe di user-agent di bot malevoli — vanno dal marginale al puro teatrino. Qui sotto trovi quali sono quali, e perché.
Una cosa da chiarire subito: .htaccess funziona solo su Apache (e su LiteSpeed, che lo legge anch’esso). Su nginx viene ignorato completamente — il file resta lì mentre tu credi di essere protetto. Se il tuo host usa nginx, niente di tutto questo si applica e ti servono invece dei blocchi server/location. Verifica con curl -I https://tuosito.com e guarda l’header Server: prima di passare un’ora a modificare un file che il server non legge mai.
La regola che conta davvero: niente PHP in /uploads
Questa è quella che vale la pena fare. wp-content/uploads è scrivibile da chiunque per progettazione — ogni caricamento di media, ogni plugin che salva un file, scrive lì. Se un attaccante riesce a mettere un file .php in quella directory (tramite un gestore di upload vulnerabile, un campo immagine che non valida il tipo MIME, un plugin compromesso), la differenza tra un fastidio e una compromissione completa con esecuzione di codice remoto sta nel fatto che il server esegua o meno quel file quando viene richiesto. Nega l’esecuzione e il payload caricato resta un file inerte che giace sul disco.
Inserisci questo in wp-content/uploads/.htaccess (crea il file se non esiste):
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
Questa è la sintassi di Apache 2.4. Nella più vecchia 2.2, l’equivalente è Order Deny,Allow / Deny from all. Mischiare i due dialetti nello stesso file è la causa più comune di un improvviso 500 Internal Server Error dopo il “hardening” — se l’intero sito muore nel momento in cui salvi, quasi sempre è per questo. Controlla la tua versione con apachectl -v.
Proteggi wp-config.php
wp-config.php contiene le credenziali del database e i salt di autenticazione. Finché PHP è in esecuzione, una richiesta diretta al file restituisce una pagina bianca — PHP esegue il file invece di stamparlo. Il rischio è il caso di guasto: se PHP dovesse mai andare in crash, venire configurato male durante una migrazione, o il gestore venisse disattivato, Apache serve il file come testo semplice e scarica la password del tuo DB a chiunque la chieda. Negare l’accesso è un’assicurazione a basso costo contro cinque brutti minuti:
<Files wp-config.php>
Require all denied
</Files>
Disattiva l’indicizzazione delle directory
Se qualcuno visita una cartella senza index.php e Apache ha Options +Indexes attivo, ne elenca il contenuto — ogni file di backup, ogni dump SQL abbandonato che ti eri dimenticato. Disattivala su tutto il sito:
Options -Indexes
Gravità bassa, ma reale, e non costa nulla.
Questa è la lista essenziale e onesta. Puoi assemblare queste regole — con la sintassi corretta 2.4-vs-2.2 così da non mandare in 500 il tuo sito — con il generatore di .htaccess per WordPress invece di copiare e incollare da un post di forum scritto per la versione sbagliata di Apache.
Cosa NON fare
Bloccare xmlrpc.php “per protezione dal brute force”. Questa è la grande convinzione che tutti ripetono ed è sbagliata così come viene formulata. Sì, il metodo system.multicall di XML-RPC storicamente permetteva a un attaccante di raggruppare molti tentativi di login in una singola richiesta — un’amplificazione reale. Ma il vettore di brute force di gran lunga più comune sono le semplici richieste POST verso wp-login.php, e bloccare xmlrpc.php non fa nulla contro quello. Il brute force si sconfigge con il rate limiting, password robuste e la 2FA — non chiudendo un singolo endpoint. C’è sì un motivo legittimo per disattivare XML-RPC: la sua funzione di pingback può essere abusata per la riflessione DDoS, quindi se non usi Jetpack, l’app mobile o i pingback, chiuderlo riduce la tua superficie d’attacco. Solo, non raccontarti che sia la tua difesa dal brute force, perché non lo è.
Nascondere la versione di WordPress / rimuovere il tag generator. Togliere readme.html e il tag <meta name="generator"> dà la sensazione di stare facendo hardening. Un attaccante identifica la tua versione dalle query string degli asset in coda, dal markup del block editor e da una dozzina di altri indizi in pochi secondi. Non stai nascondendo nulla; ti stai solo dando l’impressione di essere impegnato.
Enormi blocklist di user-agent e referrer di bot malevoli. Gli user-agent sono un singolo header HTTP falsificabile. Queste liste sono già obsolete il giorno in cui le incolli, non bloccano nessuno che sia competente, e Apache valuta ogni regex a ogni richiesta — stai pagando una vera tassa sulle prestazioni per zero sicurezza. Lasciale perdere.
Bloccare wp-login.php per IP. Ottimo finché il tuo ISP non ti cambia l’indirizzo e ti sei chiuso fuori dalla tua stessa area amministrativa. Praticabile solo con un IP genuinamente statico.
Redirect contro l’enumerazione degli autori (?author=1). La riscrittura in .htaccess che tutti incollano per questo è incompleta da sola — l’endpoint REST /wp-json/wp/v2/users continua a elencare gli username. Bloccare un percorso mentre l’altro resta aperto è teatrino.
Ancora bloccato?
Se una regola manda in 500 il sito, è un problema di sintassi — rimuovi l’ultimo blocco che hai aggiunto e ricarica; così lo isoli subito. Se una regola sembra non fare nulla, verifica di essere davvero su Apache e che AllowOverride sia abilitato per quella directory (molti host gestiti lo limitano). Costruisci il file a partire da un template affidabile con il generatore di .htaccess, tieni le tre regole che contano e lascia perdere il resto.