Vai al contenuto
Server e .htaccess

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’è 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.

FAQ

Domande

Come impedisco l'esecuzione dei file PHP nella cartella uploads di WordPress?

Crea un file .htaccess dentro wp-content/uploads con un blocco FilesMatch che intercetta i file .php e la direttiva Require all denied. Dato che uploads è scrivibile da chiunque per progettazione, negare l'esecuzione fa sì che un file .php malevolo che riesca a entrare resti sul disco come file inerte invece di diventare esecuzione di codice remoto.

Devo bloccare l'accesso diretto a wp-config.php?

Sì, e non costa nulla. Aggiungi un blocco Files per wp-config.php con Require all denied. Finché PHP è in esecuzione una richiesta diretta restituisce solo una pagina bianca, ma se PHP si blocca, viene configurato male durante una migrazione o il suo handler viene disattivato, Apache serve il file in chiaro e riversa le credenziali del tuo database.

Perché il mio sito ha mostrato un errore 500 Internal Server Error subito dopo aver modificato .htaccess?

Quasi sempre si tratta di sintassi Apache mescolata. Require all denied è Apache 2.4, mentre Order Deny,Allow con Deny from all è la 2.2, e combinare i due dialetti nello stesso file rompe il sito nel momento in cui salvi. Controlla la tua versione con apachectl -v, oppure rimuovi l'ultimo blocco che hai aggiunto e ricarica.

Il file .htaccess funziona su nginx?

No. .htaccess ha effetto solo su Apache, e su LiteSpeed, che lo legge anch'esso. Su nginx viene ignorato completamente, quindi resta lì mentre tu credi di essere protetto. Esegui curl -I sul tuo sito e controlla prima l'header Server:, poi usa dei blocchi server o location.

Bloccare xmlrpc.php ferma gli attacchi brute force a WordPress?

No. Il vettore di brute force di gran lunga più comune sono normali richieste POST a wp-login.php, e bloccare xmlrpc.php non ci fa nulla. Il brute force si batte con il rate limiting, password robuste e la 2FA. Disattivare XML-RPC ha comunque senso se non usi Jetpack, l'app mobile o i pingback, dato che il pingback può essere abusato per amplificare attacchi DDoS.