Sicurezza web

File inclusion (LFI e RFI)

Definizione

La file inclusion (inclusione di file) è una vulnerabilità PHP in cui un attaccante controlla il percorso passato a include o require. Con la LFI (Local File Inclusion) fa caricare un file già presente sul server; con la RFI (Remote File Inclusion), un file ospitato altrove. Porta alla lettura di segreti o all’esecuzione di codice.

File inclusion (LFI e RFI), Sicurezza web

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.
Confronto in tre colonne: LFI (inclusione di un file del server, lettura o esecuzione di wp-config.php tramite percorsi ../, wrapper php://filter e phar://, funziona con la configurazione predefinita), RFI (inclusione di un URL http o ftp che contiene il codice dell’attaccante, richiede allow_url_include attivo, opzione disattivata per impostazione predefinita e deprecata in PHP 7.4) e difese (elenco fisso di file autorizzati, mai un percorso preso dalla richiesta, open_basedir e allow_url_include disattivato, aggiornamenti)
La RFI dipende da un’opzione disattivata per impostazione predefinita; la LFI invece funziona su una configurazione standard.

Il ruolo della configurazione di PHP

La documentazione di PHP è chiara su due direttive:

  • allow_url_include autorizza gli URL in include e require. Vale 0 per impostazione predefinita, si modifica solo nella configurazione di sistema (php.ini) ed è deprecata da PHP 7.4.0. Richiede inoltre che allow_url_fopen sia attiva.
  • allow_url_fopen permette 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.

Video: «Web Exploitation con DVWA - 05 File Inclusion (LFI + RFI) (ITA)» (Esadecimale)

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.

Fonti

  1. MITRE CWE-98: PHP Remote File Inclusion (link esterno, si apre in una nuova scheda)
  2. PHP Manual: Filesystem and Streams Configuration Options (link esterno, si apre in una nuova scheda)
  3. PHP Manual: Backward Incompatible Changes in PHP 8.0 (Phar) (link esterno, si apre in una nuova scheda)

Tutte le definizioni

Sicurezza WordPress, senza rumore

Un’email quando conta: nuovi attacchi osservati, aggiornamenti del plugin e guide pratiche. Niente spam, disiscrizione con un clic.

Inizia gratis, passa a Pro quando sei pronto

La versione gratuita nasconde già WordPress e sposta la pagina di login. Pro aggiunge alias, autenticazione a due fattori e monitoraggio.