In PHP, le istruzioni include e require (e le varianti _once) caricano un file ed eseguono il codice che contiene. Si usano ovunque, per esempio per caricare un template del tema. Il pericolo nasce quando il percorso del file dipende da un dato inviato dal visitatore senza un controllo sufficiente. Il catalogo del MITRE classifica questa debolezza come CWE-98, con due nomi d’uso: RFI per l’inclusione remota, LFI per quella locale.
Come funziona l’attacco
Un codice come questo lascia al visitatore la scelta del file da caricare:
// Da non fare
include( __DIR__ . '/templates/' . $_GET['vista'] . '.php' );
- LFI (Local File Inclusion): con sequenze
../l’attaccante risale l’albero delle cartelle e fa caricare un file già presente sul server. Nel migliore dei casi legge un file che non dovrebbe vedere; se riesce a far includere un file di cui controlla il contenuto (un log, un file caricato), ottiene un’esecuzione remota di codice. - RFI (Remote File Inclusion): l’attaccante fornisce un URL verso il proprio server e PHP include direttamente il suo codice. È la forma più diretta, ma richiede un’opzione raramente attiva.

Il ruolo della configurazione di PHP
La documentazione di PHP è chiara su due direttive:
allow_url_includeautorizza gli URL inincludeerequire. Vale0per impostazione predefinita, si modifica solo nella configurazione di sistema (php.ini) ed è deprecata da PHP 7.4.0. Richiede inoltre cheallow_url_fopensia attiva.allow_url_fopenpermette di aprire URL come se fossero file; è attiva per impostazione predefinita, perché molti script ne hanno bisogno.
Disattivare la RFI non risolve tutto: i wrapper di PHP, come php://filter, permettono su una configurazione predefinita di trasformare alcune LFI in esecuzione di codice, e phar:// è servito a lungo per attivare una deserializzazione insicura. Il nostro articolo sui wrapper php://filter e phar descrive queste tecniche.
Come proteggersi
La difesa migliore, raccomandata dal MITRE, è non costruire mai un percorso a partire da un dato ricevuto, ma associare valori fissi a file noti:
$viste = array( 'elenco' => 'elenco.php', 'griglia' => 'griglia.php' );
$vista = isset( $viste[ $_GET['vista'] ?? '' ] ) ? $viste[ $_GET['vista'] ] : 'elenco.php';
include __DIR__ . '/templates/' . $vista;
- Tieni i file inclusi fuori dalla radice web quando possibile.
- Limita ciò che PHP può leggere con
open_basedir: un’inclusione deviata non potrà uscire dalle cartelle autorizzate. Il rafforzamento di PHP su un hosting spiega questa impostazione e i suoi effetti. - Un web application firewall blocca gli schemi tipici (
../,php://), ma solo come complemento.
Per WordPress
Il core di WordPress non costruisce le sue inclusioni a partire dai parametri dei visitatori: il rischio viene da plugin e temi che caricano un template, una lingua o un modulo in base a un parametro dell’URL o di AJAX. Il bersaglio preferito di una LFI è wp-config.php, che contiene le credenziali del database e le chiavi di sicurezza; un file sensibile dimenticato nella radice, come un .env o un backup, è un’altra preda facile, come mostra il nostro articolo sui file sensibili esposti. Verifica infine che il tuo hosting lasci allow_url_include disattivata.