Situazione attuale: PHP2Shell. Due vulnerabilità critiche di PHP (CVSS 9,2) consentono codice dannoso senza autenticazione. Patch dal 21/10/2026.Che cosa fare ora →

open_basedir e isolamento per sito

Come impedire, con open_basedir, utenti di sistema propri e pool PHP-FPM separati, che un'intrusione in un sito colpisca tutti gli altri sul server.

Stato 6 min di letturaGuide

In breve: open_basedir limita le directory a cui PHP può accedere. Da solo è soltanto una barriera aggiuntiva. Un isolamento efficace per sito nasce solo dall'interazione di più elementi: utente di sistema proprio, pool PHP-FPM proprio, cartella temporanea propria e accessi al database propri. Così un'intrusione in un sito resta limitata a quel sito.

Perché dopo PHP2Shell l'isolamento decide l'entità del danno

Su molti server girano più siti affiancati: il sito aziendale, uno shop, una vecchia pagina di campagna e, nelle agenzie, spesso decine di progetti dei clienti. Spesso condividono un utente di sistema e un processo PHP. Se uno viene compromesso, tutti gli altri restano scoperti.

PHP2Shell rende tangibile questo rischio. Le vulnerabilità CVE-2026-109618 e CVE-2026-109619 consentono l'esecuzione di codice dannoso senza autenticazione, indipendentemente dal CMS. Secondo i media, già il 17/10/2026 c'era stato un primo tentativo di attacco, le patch sono seguite il 21/10. La correzione è l'aggiornamento. Se però un attacco nel periodo precedente colpisca uno o dieci siti lo decide l'isolamento.

Con la seconda vulnerabilità si aggiunge un'ulteriore considerazione: secondo il progetto PHP, lo stato interno di una richiesta può rimanere in un worker ed essere usato da una richiesta successiva nello stesso worker. Pool separati per ogni sito fanno sì che i siti non condividano comunque alcun worker.

Che cosa fa open_basedir

Con open_basedir definisce un elenco di directory. Le funzioni di file di PHP come fopen, include o file_get_contents rifiutano allora l'accesso a tutto ciò che è al di fuori di questo elenco. Uno script introdotto di nascosto non può così leggere senza difficoltà i file di configurazione del sito vicino.

I limiti sono importanti: il controllo avviene all'interno di PHP. I programmi avviati al di fuori di PHP non vi sono soggetti e gli errori dell'interprete possono aggirarlo. Per questo open_basedir va sempre insieme al blocco delle funzioni di sistema, come descritto nella guida Usare correttamente disable_functions, e soprattutto alla separazione a livello di sistema operativo.

Isolamento per sito in quattro livelli

Una separazione solida si basa su più livelli. Ciascuno intercetta ciò che il precedente non garantisce.

Livello Misura Effetto
Sistema operativo utente di sistema proprio per ogni sito I file di altri siti non sono leggibili
Processi PHP pool PHP-FPM proprio con socket proprio nessun worker condiviso, impostazioni proprie
Configurazione PHP open_basedir, cartelle tmp e di sessione proprie barriera aggiuntiva, nessun file temporaneo condiviso
Dati utente di database proprio con diritti solo sul proprio database nessun accesso ai dati di clienti altrui

Con un alto bisogno di protezione, ad esempio per shop con gestione dei pagamenti o portali con dati sanitari, si aggiungono container o server separati.

Configurare open_basedir nel pool PHP-FPM

L'esempio seguente mostra un pool per un sito con utente proprio seite1. Adatti percorsi e numero di versione al Suo sistema.

; /etc/php/8.3/fpm/pool.d/seite1.conf
[seite1]
user = seite1
group = seite1
listen = /run/php/seite1.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = ondemand
pm.max_children = 10

php_admin_value[open_basedir] = /var/www/seite1/:/var/www/seite1-tmp/
php_admin_value[upload_tmp_dir] = /var/www/seite1-tmp/
php_admin_value[sys_temp_dir] = /var/www/seite1-tmp/
php_admin_value[session.save_path] = /var/www/seite1-tmp/sessions
php_admin_value[error_log] = /var/log/php/seite1.error.log
php_admin_flag[session.upload_progress.enabled] = off

L'ultima riga applica subito la misura provvisoria di php.net contro PHP2Shell. Funziona solo dal pool, dal php.ini o dalla configurazione del server, non tramite ini_set() o .user.ini. Crei le cartelle con i permessi adatti:

sudo useradd --system --home /var/www/seite1 --shell /usr/sbin/nologin seite1
sudo mkdir -p /var/www/seite1-tmp/sessions
sudo chown -R seite1:seite1 /var/www/seite1-tmp
sudo chmod 700 /var/www/seite1-tmp

Come dovrebbero essere i permessi nella vera e propria directory web è descritto nella guida Permessi dei file sul server web.

Collegare il server web e verificare il risultato

In Nginx ogni sito rimanda al proprio socket. Così nessuna richiesta finisce nel pool di un altro sito.

server {
    server_name seite1.example;
    root /var/www/seite1/public;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/seite1.sock;
    }
}

Ulteriori indicazioni su questa combinazione si trovano in Mettere in sicurezza Nginx con PHP-FPM. Dopo il riavvio verifichi che i pool girino davvero separati:

sudo systemctl restart php8.3-fpm
# Ogni pool dovrebbe girare con il proprio utente
ps -eo user,pid,cmd | grep "[p]hp-fpm: pool"

Provi poi tutte le funzioni del sito: upload, elaborazione delle immagini, cache, attività pianificate. I messaggi di errore con riferimento a open_basedir restriction nel log degli errori mostrano quale percorso manca ancora. Aggiunga solo percorsi di cui l'applicazione ha davvero bisogno, e mai l'intero file system.

Consiglio

Le agenzie con molti siti di clienti dovrebbero mantenere la configurazione del pool come modello. Così ogni nuovo sito riceve la separazione automaticamente, invece di doverla aggiungere in seguito. Approfondimenti per questo caso si trovano in Partner per la sicurezza delle agenzie.

Ostacoli tipici durante il passaggio

Il passaggio a pool separati è pianificabile, ma presenta alcune trappole ricorrenti. La più frequente riguarda le librerie condivise: se, ad esempio, un framework o una cartella di caratteri si trova al di fuori della directory del sito, questo percorso deve essere inserito in sola lettura in open_basedir. Meglio portare tali dipendenze nel progetto stesso.

La seconda trappola sono le sessioni. Se cambia il luogo di archiviazione, tutti i visitatori vengono disconnessi una volta e i carrelli in corso vanno persi. Pianifichi quindi il passaggio in una fascia oraria tranquilla e lo annunci internamente.

In terzo luogo, le attività pianificate girano spesso dalla riga di comando e quindi con un utente diverso da quello del sito. Controlli cronjob e code e li faccia girare con il nuovo utente del sito, altrimenti si creano file con il proprietario sbagliato che PHP non potrà più modificare.

Infine, ogni pool dovrebbe avere limiti propri per processi e memoria. Un sito che va sotto carico o viene attaccato non può così mettere in ginocchio gli altri.

Come aiuta concretamente PHP SOS?

  • Rileviamo quali siti oggi condividono utenti, processi e database.
  • Creiamo per ogni sito utenti, pool, cartelle temporanee e accessi al database propri, senza modificare le applicazioni.
  • Testiamo ogni sito dopo il passaggio e risolviamo in modo mirato i percorsi mancanti.
  • Documentiamo la separazione come modello per i progetti futuri.

Come si inserisce in un concetto complessivo è descritto nel servizio Hardening del server per server web PHP.

Domande frequenti

open_basedir basta per separare i siti l'uno dall'altro?

No. open_basedir è una barriera aggiuntiva all'interno di PHP, non una separazione rigida. L'isolamento diventa affidabile solo con utenti di sistema e pool propri per ogni sito, con container o server separati se il bisogno di protezione è più alto.

Perché dopo aver impostato open_basedir gli upload non funzionano più?

Di solito nell'elenco manca la cartella dei file temporanei. Crei per ogni sito una propria cartella tmp, la inserisca in open_basedir e imposti upload_tmp_dir e sys_temp_dir su questa cartella.

Un'applicazione può revocare da sola open_basedir?

Un'applicazione può solo restringere ulteriormente l'impostazione durante l'esecuzione, non allentarla. Imposti comunque open_basedir tramite php_admin_value nel pool, in modo che il valore sia fissato in modo inequivocabile.

L'isolamento è possibile anche con lo shared hosting?

Dipende dall'hoster. Molte offerte separano i clienti tramite utenti e processi PHP propri. Chieda come è realizzata la separazione, in particolare se più dei Suoi siti si trovano in uno stesso pacchetto.

Fonti

Contatto immediato

Ogni ora conta. Ci scriva adesso.

Descriva brevemente sistema, versione di PHP e quanto osservato. Ci faremo sentire, chiariremo la situazione e lavoreremo da remoto fino alla chiusura e alla documentazione dell'incidente.

Aiuto immediato