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_generator agisce 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.txt o da ver= 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-By con expose_php = Off in php.ini
  • readme.html torna 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:

Domande su WordPress? Chi pubblica questo sito ha sede in Giappone e risponde in giapponese. Contatti (in giapponese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲