2026年11月12日
2026年11月12日
Nascondere la versione di WordPress: generator, ver= e readme.html
Questo articolo è un'edizione localizzata dell'originale giapponese. Leggi l'originale in giapponese
Nella configurazione iniziale WordPress scrive il proprio numero di versione nell'HTML delle pagine e nei feed. Un attaccante può usarlo come indizio per verificare se si tratta di una versione con vulnerabilità note. In questo articolo vediamo dove viene mostrata la versione e come nasconderla. Il contenuto è aggiornato a ottobre 2026.
La prima cosa da sapere è che nascondere la versione è solo una misura di supporto. Esistono modi per dedurre la versione, per esempio dal contenuto dei file CSS e JavaScript, quindi nasconderla non garantisce che non venga individuata. La misura più efficace è tenere aggiornati core, plugin e temi di WordPress.
Dove viene mostrata la versione
| Posizione | Cosa viene mostrato | Rimedio |
|---|---|---|
<head> dell'HTML |
Un tag come <meta name="generator" content="WordPress 6.9.4"> |
Filtro the_generator |
| Feed RSS e Atom | Una riga come <generator>https://wordpress.org/?v=6.9.4</generator> |
Sempre il filtro the_generator |
| URL di CSS e JavaScript | Un ?ver= come style.min.css?ver=6.9.4 |
Filtri style_loader_src e script_loader_src |
| Header HTTP | X-Powered-By: PHP/8.3.x (è la versione di PHP, non di WordPress) |
expose_php in php.ini |
readme.html |
Il fatto che si usi WordPress (l'attuale readme.html non riporta il numero di versione) | Negare l'accesso |
Le informazioni sul sito restituite da /wp-json/ della REST API (nome, descrizione, URL, fuso orario, namespace e così via) non includono la versione di WordPress. Per nascondere la versione non serve ridurre l'output della REST API.
Passo 1: controlla cosa viene mostrato adesso
Sostituisci l'URL con quello del tuo sito ed esegui i comandi dal tuo computer o dal server. Se usi plugin di cache o una CDN, dopo la modifica svuota la cache prima di controllare.
# Tag generator dell'HTML
curl -s https://example.com/ | grep -i 'name="generator"'
# Generator del feed
curl -s https://example.com/feed/ | grep -i '<generator>'
# Elenco dei valori di ver= presenti in CSS e JS
curl -s https://example.com/ | grep -oE 'ver=[0-9][0-9.]*' | sort | uniq -c
# X-Powered-By negli header HTTP
curl -sI https://example.com/ | grep -i 'x-powered-by'
# readme.html è leggibile? (con 200 è leggibile)
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html
Se nell'elenco di ver= compare lo stesso valore della versione di WordPress mostrata in «Bacheca» → «Aggiornamenti» (Dashboard → Updates) nell'amministrazione, da quei CSS e JS si può risalire alla versione di WordPress. Quando il core o il tema di WordPress caricano CSS e JS senza indicare una versione, nel ver= finisce la versione di WordPress.
Passo 2: decidi dove mettere il codice
Il codice di questo articolo va messo in uno di questi due posti.
- mu-plugin (consigliato): se metti un file PHP nella cartella
wp-content/mu-plugins/(creala se non c'è), viene caricato senza bisogno di attivarlo. L'effetto resta anche se cambi tema - functions.php del tema figlio: se lo scrivi nel functions.php del tema padre, scompare con l'aggiornamento del tema
Se scegli il mu-plugin, salva il codice del passo successivo in un unico file con un nome come wp-content/mu-plugins/hide-wp-version.php.
Passo 3: nascondi la versione nel tag generator e in ver=
<?php
/**
* Plugin Name: Hide WordPress Version
* Description: Nasconde la versione di WordPress mostrata nel tag generator e in ver= di CSS e JS.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Svuota <meta name="generator"> dell'HTML e <generator> del feed.
add_filter( 'the_generator', '__return_empty_string' );
/**
* Sostituisce con un altro valore il ver= di CSS e JS solo quando coincide con la versione di WordPress.
* Poiché ver= viene sostituito e non eliminato, la cache del browser si aggiorna anche dopo un aggiornamento di WordPress.
*/
function wpdr_replace_wp_version_query( $src ) {
if ( ! is_string( $src ) || '' === $src ) {
return $src;
}
$query = wp_parse_url( $src, PHP_URL_QUERY );
if ( empty( $query ) ) {
return $src;
}
parse_str( $query, $args );
$wp_version = get_bloginfo( 'version' );
if ( isset( $args['ver'] ) && $args['ver'] === $wp_version ) {
$src = add_query_arg( 'ver', substr( wp_hash( $wp_version ), 0, 10 ), $src );
}
return $src;
}
add_filter( 'style_loader_src', 'wpdr_replace_wp_version_query', 20 );
add_filter( 'script_loader_src', 'wpdr_replace_wp_version_query', 20 );
I punti chiave sono questi.
- Il filtro
the_generatoragisce sia sul tag generator dell'HTML sia sul generator dei feed.remove_action( 'wp_head', 'wp_generator' );elimina solo il tag dell'HTML, quindi non agisce sui feed - Se elimini tutti i
?ver=, quando aggiorni un plugin o un tema il browser può continuare a usare i vecchi CSS e JS. Il codice qui sopra sostituisce il valore con un'altra stringa, creata a partire dalla versione, solo quando coincide con la versione di WordPress. Aggiornando WordPress il valore cambia, quindi la cache viene aggiornata - I
ver=con un numero di versione proprio di plugin e temi non vengono modificati
Dopo averlo salvato, verifica con i comandi del Passo 1 che il generator non compaia più e che nell'elenco di ver= non resti la versione di WordPress. Se usi plugin di cache, svuota la cache prima di controllare.
Passo 4: elimina l’header X-Powered-By
X-Powered-By è un header aggiunto da PHP, non da WordPress, e rivela la versione di PHP. Per eliminarlo imposta expose_php su Off nel file di configurazione di PHP (php.ini). Questa impostazione si può cambiare solo in php.ini.
expose_php = Off
Ecco un esempio per un VPS Ubuntu con PHP-FPM (adatta 8.3 alla versione di PHP che usi).
# Controlla l'impostazione attuale
grep -n '^expose_php' /etc/php/8.3/fpm/php.ini
# Dopo la modifica, riavvia PHP-FPM
sudo systemctl restart php8.3-fpm
Il php.ini dei pacchetti Ubuntu ha expose_php = Off già nella configurazione iniziale. Se l'header compare, controlla che non venga usato un altro php.ini. Sugli hosting condivisi, a seconda dei casi, si può cambiare dalle impostazioni PHP del pannello di controllo oppure non si può.
Se non puoi modificare php.ini, puoi rimuovere l'header anche con il codice di WordPress. Tuttavia send_headers è un hook che scatta quando WordPress genera le pagine del front-end, quindi non agisce sull'amministrazione né sulla pagina di login.
add_action( 'send_headers', function () {
header_remove( 'X-Powered-By' );
} );
Passo 5: nega l’accesso a readme.html e license.txt
readme.html e license.txt sono file del core di WordPress. L'attuale readme.html non riporta il numero di versione, ma rivela che si usa WordPress.
Anche se li elimini, tornano con l'aggiornamento del core di WordPress. Negare l'accesso dal server web richiede meno lavoro che eliminarli.
Con Apache (.htaccess)
Aggiungi il codice nel file .htaccess nella cartella di WordPress. Tra # BEGIN WordPress e # END WordPress WordPress riscrive il contenuto, quindi scrivi fuori da quel blocco. È la sintassi di Apache 2.4 (Order e Deny from all sono la vecchia sintassi di Apache 2.2).
<FilesMatch "^(readme\.html|license\.txt)$">
Require all denied
</FilesMatch>
Con Nginx
Aggiungilo al blocco server del sito, controlla la configurazione e ricaricala.
location ~* ^/(readme\.html|license\.txt)$ {
deny all;
}
sudo nginx -t && sudo systemctl reload nginx
Dopo l'aggiunta esegui curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html e verifica che risponda 403.
Cosa non si evita nascondendo la versione
- Il contenuto dei file CSS e JS di WordPress cambia un po' a ogni versione, quindi scaricando i file e confrontandoli si può dedurre la versione
- Da
readme.txto daver=di plugin e temi a volte si può risalire alla versione del plugin. Gli attacchi mirano più spesso alle vulnerabilità dei plugin che a quelle del core - Per chi può accedere all'amministrazione la versione resta visibile come sempre
Per questo, oltre a nascondere la versione, aggiorna core, plugin e temi, elimina i plugin che non usi e disattiva la modifica dei file dall'amministrazione.
Riepilogo
- La versione compare soprattutto nel generator dell'HTML e dei feed e nei
?ver=di CSS e JS. Nel/wp-json/della REST API la versione di WordPress non è inclusa - Con
add_filter( 'the_generator', '__return_empty_string' );si elimina il generator sia dell'HTML sia dei feed - Non eliminare
?ver=: sostituisci solo i valori uguali alla versione di WordPress, così non blocchi l'aggiornamento della cache - Elimina
X-Powered-Byconexpose_php = Offin php.ini readme.htmltorna con gli aggiornamenti anche se lo elimini, quindi nega l'accesso dal server web- Nascondere la versione è solo una misura di supporto: la cosa più importante è continuare ad aggiornare
Articoli correlati:
- Come configurare gli header di sicurezza di WordPress: .htaccess, Nginx e functions.php
- Come limitare l'accesso alla REST API di WordPress
- Disattivare l'editor dei file di temi e plugin di WordPress: DISALLOW_FILE_EDIT
Domande su WordPress? Chi pubblica questo sito ha sede in Giappone e risponde in giapponese. Contatti (in giapponese)