1 14/04/2026 8 min

Bloccare il directory listing su WordPress: perché farlo subito

Se un server Apache mostra il contenuto di una directory quando manca un file indice, stai regalando all’esterno una mappa parziale del sito. Su WordPress questo può esporre cartelle di plugin, temi, upload e talvolta file di servizio che non dovrebbero essere elencati da chiunque. Non è una vulnerabilità “critica” da sola, ma è una superficie d’attacco inutile. In pratica: meno informazioni pubbliche, meno lavoro per chi prova a profilare l’installazione.

La correzione più rapida, quando il sito gira su Apache e usa .htaccess, è disabilitare l’autoindex a livello di directory. È un cambio piccolo, reversibile e con blast radius basso se lo fai nel punto giusto. Il punto giusto, in WordPress, è quasi sempre la root del sito o il livello superiore che include l’installazione.

Che cosa cambia davvero con Options -Indexes

La direttiva Options -Indexes dice ad Apache di non generare una pagina con l’elenco dei file quando una directory viene richiesta senza un indice valido. Se un visitatore apre /wp-content/plugins/ e non trova un index.php o un file equivalente, invece della lista dei contenuti otterrà un errore di tipo “403 Forbidden” oppure la risposta prevista dalla configurazione del server.

Il vantaggio operativo è semplice: non devi modificare WordPress, non devi installare plugin, non devi dipendere dal tema. Intervieni sul livello web server, che è quello corretto per questo tipo di controllo. Se più applicazioni condividono lo stesso host, però, devi stare attento al posizionamento: una regola troppo alta nella gerarchia può avere effetti su siti diversi. Qui la disciplina conta più della sintassi.

Prima verifica: il server supporta davvero .htaccess?

Prima di toccare file di configurazione, verifica che il sito sia servito da Apache con AllowOverride abilitato nella directory corretta. Se sei su Nginx puro, il file .htaccess non viene letto e la regola non avrà effetto. Se sei dietro un reverse proxy o un pannello hosting, può esserci Apache dietro ma con override disabilitati: in quel caso il cambio va fatto nella vhost o dal pannello, non nel file.

Controllo rapido da shell:

apachectl -S 2>/dev/null | sed -n '1,120p'

Se il comando non esiste o restituisce errore, sei probabilmente su un altro web server o in un ambiente containerizzato. In quel caso la chiusura del gap è: identificare il servizio reale con systemctl status oppure dal pannello hosting e applicare la regola nel punto supportato dal server.

Procedura pratica in WordPress con .htaccess

La soluzione minima consiste nell’inserire la direttiva nella root del sito, insieme alle regole standard di WordPress. Prima fai un backup del file, poi modifica con criterio. Non riscrivere tutto se non serve: aggiungi una sola riga e verifica.

1. Fai una copia del file prima di intervenire:

cp /var/www/html/.htaccess /var/www/html/.htaccess.bak.$(date +%F-%H%M)

2. Apri .htaccess e aggiungi la direttiva in alto, prima delle regole riscritte da WordPress:

<IfModule mod_autoindex.c>
    Options -Indexes
</IfModule>

3. Lascia intatte le regole già presenti per i permalink. Un file tipico resta ordinato così:

<IfModule mod_autoindex.c>
    Options -Indexes
</IfModule>

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

4. Se il sito è in una sottocartella, applica la stessa logica nel .htaccess di quella directory, non per forza nella root del dominio. Il criterio è semplice: la regola deve stare nel punto in cui Apache la legge davvero per quel path.

Verifica immediata: come capire se il listing è davvero chiuso

Dopo il cambio, prova una directory che prima poteva essere elencata. L’obiettivo è non vedere più il file listing. Se la directory non ha un indice, la risposta attesa è un 403 o comunque una pagina di accesso negato, non una lista di file.

Test sintetico da terminale:

curl -I https://example.com/wp-content/plugins/

Risultato atteso: niente risposta con contenuto HTML che elenca i file. Un HTTP/2 403 o HTTP/1.1 403 Forbidden è coerente con il blocco del listing. Se invece vedi un 200 OK con pagina che mostra nomi di file e cartelle, la regola non è stata applicata nel posto giusto o viene sovrascritta da un’altra configurazione.

Se vuoi una verifica più netta, usa una directory sicuramente priva di index:

curl -s https://example.com/wp-content/uploads/ | head

Se l’output mostra un elenco di file, la protezione non è attiva. Se invece ricevi una pagina di errore o contenuto non indicizzabile, il controllo sta funzionando.

Quando .htaccess non basta: vhost, pannello e Apache globale

Ci sono ambienti in cui il file per-directory non è la scelta migliore. Se gestisci la macchina e hai accesso alla vhost, mettere Options -Indexes nella configurazione del virtual host è più pulito e spesso più prevedibile. In un pannello hosting, la stessa opzione può essere esposta come toggle di sicurezza o come campo “Additional directives”. L’idea non cambia: il controllo va applicato nel livello più stabile disponibile.

Se usi Apache con una configurazione centralizzata, la direttiva può stare in un blocco di directory del tipo:

<Directory /var/www/html>
    AllowOverride All
    Options -Indexes
</Directory>

Qui il punto critico è AllowOverride All: se è impostato su None, il tuo .htaccess non verrà letto. In quel caso la soluzione non è insistere sul file, ma correggere la policy del server. Questo è un classico gap operativo: la regola è giusta, ma il layer che la dovrebbe applicare non la consente.

Occhio alle eccezioni: non confondere listing con accesso ai media

Bloccare il listing non impedisce il download di file che conosci già. Se un file in /wp-content/uploads/ è pubblico e il suo URL è noto, potrà essere scaricato a meno di altre regole. Il listing serve a evitare la navigazione casuale della directory, non a trasformare il contenuto in privato.

Questo dettaglio conta soprattutto quando qualcuno confonde “directory non listabile” con “directory sicura”. Non sono la stessa cosa. Se devi proteggere documenti riservati, la strategia corretta è spostarli fuori dal web root, servirli tramite script autenticato o usare un sistema di storage con controllo accessi reale. Options -Indexes è solo un primo livello di igiene.

Errori tipici che fanno credere di aver risolto quando non è così

Il primo errore è modificare il file sbagliato. WordPress può avere più .htaccess se è in sottocartella o se il pannello genera regole per domini aggiuntivi. Il secondo è mettere la direttiva dopo una riscrittura che non viene mai raggiunta, o dentro un blocco che non è letto per quella directory. Il terzo è testare l’URL della home e non una directory reale senza indice.

Un altro errore frequente è ignorare la cache. Se hai un proxy, un CDN o una cache applicativa davanti ad Apache, il comportamento osservato può essere falsato per qualche minuto. In quel caso svuota la cache o usa un parametro di bypass secondo le regole del tuo stack. La verifica corretta è sempre sul layer che sta rispondendo davvero, non su quello che immagini stia rispondendo.

Approccio più robusto: combinare hardening web e igiene dei permessi

Se vuoi fare un lavoro sensato e non solo cosmetico, affianca al blocco del listing una revisione di base dei permessi e dell’esposizione dei file. Le directory dovrebbero avere permessi coerenti con l’utente del web server, i file sensibili non dovrebbero stare nel document root e i file di configurazione non dovrebbero essere accessibili via HTTP. Il blocco del listing riduce la visibilità; l’igiene dei permessi riduce il danno se qualcuno indovina un path.

Per un audit minimo, controlla almeno questi punti:

  1. La root del sito: verifica che il file .htaccess esista davvero e sia letto dal server.
  2. Le directory sensibili: prova un URL diretto a cartelle come wp-content/plugins/ e wp-content/uploads/.
  3. I log web: cerca risposte 403 coerenti e controlla che non ci siano errori di sintassi nel file di configurazione.

Se trovi errori come AH00526: Syntax error nei log di Apache, la modifica va corretta subito e ripristinata dal backup. Il rollback è semplice: rimetti il file precedente o togli la direttiva appena aggiunta. Non serve fare altro per tornare allo stato iniziale.

Snippet pronto da usare e criterio di rollback

Se vuoi una versione essenziale da incollare senza complicarti la vita, questa è la base minima consigliabile:

<IfModule mod_autoindex.c>
    Options -Indexes
</IfModule>

Rollback: rimuovi quelle tre righe oppure ripristina il backup del file .htaccess. Se il sito dopo il cambio mostra un 500, il primo sospetto è una direttiva non supportata dal modulo presente o una sintassi corrotta: in quel caso il rollback immediato è la scelta corretta, non la caccia al colpevole a caldo.

Assunzione: il sito WordPress è servito da Apache con supporto a .htaccess; se il web server è Nginx, LiteSpeed o un proxy gestito dal pannello, la stessa protezione va applicata nel punto equivalente del relativo stack.