In breve: con PHP disable_functions blocca le funzioni con cui PHP esegue comandi di sistema, ad esempio exec, shell_exec o proc_open. Questo rende più difficile agli aggressori il passo successivo dopo un'intrusione. L'impostazione funziona solo dal php.ini o dal pool FPM, deve essere adatta all'applicazione e non sostituisce un aggiornamento.
Perché disable_functions è sensato proprio adesso
Con PHP2Shell si tratta dell'esecuzione di codice dannoso da remoto senza autenticazione. Le due vulnerabilità CVE-2026-109618 e CVE-2026-109619 si trovano nell'interprete PHP stesso e sono corrette in PHP 8.5.12, 8.4.27, 8.3.36 e 8.2.35. L'aggiornamento è l'unico modo per chiuderle.
L'hardening interviene un livello più avanti. Chi riesce una volta a eseguire codice su un server di solito vuole andare oltre: avviare comandi di sistema, scaricare strumenti, installare una backdoor permanente. Molti di questi passi passano attraverso poche funzioni PHP. Se sono bloccate, la strada diventa più faticosa e più visibile.
disable_functions non è quindi un sostituto delle patch, ma un tassello per il caso in cui, nonostante ogni cautela, qualcosa riesca a passare. Vale per le vulnerabilità future come per PHP2Shell.
Che cosa fa PHP disable_functions e che cosa no
L'impostazione rimuove le funzioni indicate dall'ambiente di esecuzione. Se uno script richiama una funzione bloccata, PHP termina con un errore. Il blocco vale per ogni codice che gira in quel processo PHP, quindi anche per il codice introdotto di nascosto.
Conviene conoscerne i limiti:
- L'impostazione non è uno spazio protetto a tenuta stagna. Estensioni PHP, errori dell'interprete o programmi esterni a PHP possono aggirarla.
- Non impedisce a un aggressore di leggere o scrivere file a cui l'utente PHP ha accesso. Di questo si occupano permessi dei file e isolamento.
- Funziona solo dal php.ini o come
php_admin_value. Conini_set(),.user.inio.htaccessnon si può impostare.
disable_functions rende di più insieme a un php.ini pulito, a utenti separati per ogni sito e a permessi dei file restrittivi. Le basi sono nella guida Configurare php.ini in modo sicuro.
Quali funzioni dovrebbe bloccare
Per i siti tipici senza necessità di comandi di sistema si è dimostrato valido l'elenco seguente. Comprende funzioni per avviare processi e per controllare processi in esecuzione.
| Gruppo | Funzioni | Tipico uso legittimo |
|---|---|---|
| Eseguire comandi | exec, shell_exec, system, passthru |
Elaborazione di immagini, backup tramite script |
| Aprire processi | proc_open, popen |
Composer, strumenti PDF, invio di posta |
| Controllare processi | proc_nice, proc_terminate, proc_get_status |
Code, job in background |
| Gestione dei processi | pcntl_exec, pcntl_fork |
di solito solo da riga di comando |
| Segnali e permessi | posix_kill, posix_setuid |
raramente in esercizio web |
Come configurazione appare così:
; php.ini della modalità di esecuzione web, ad es. /etc/php/8.3/fpm/php.ini
disable_functions = exec,shell_exec,system,passthru,proc_open,popen,proc_nice,proc_terminate,proc_get_status,pcntl_exec,pcntl_fork,posix_kill,posix_setuid
Se l'elenco non vale per tutti i siti sul server, lo imposti per ogni pool FPM. Dopo il ricaricamento verifichi quale elenco valga effettivamente in quel pool:
; /etc/php/8.3/fpm/pool.d/meine-seite.conf (estratto)
php_admin_value[disable_functions] = exec,shell_exec,system,passthru,proc_open,popen
Verificare prima l'applicazione: così evita interruzioni
Chi imposta l'elenco senza verificarlo rischia che ridimensionamento delle immagini, fatture PDF o invio della posta smettano improvvisamente di funzionare. Cerchi quindi prima nel codice le funzioni interessate:
# Dove e quanto spesso vengono usate le funzioni nel codice?
grep -rnoE "\b(exec|shell_exec|system|passthru|proc_open|popen|pcntl_exec)\s*\(" /var/www/meine-seite --include="*.php" \
| cut -d: -f1 | sort | uniq -c | sort -rn | head -30
I riscontri non significano automaticamente che la funzione serva in esercizio. Molte librerie controllano prima se una funzione è disponibile e altrimenti ripiegano su un'alternativa. È decisivo un test in un ambiente di staging con tutti i processi importanti: ordine, fattura, invio dei moduli, upload di immagini, attività pianificate.
Se un'applicazione richiede necessariamente una di queste funzioni, controlli i requisiti di sistema del produttore sulla sua pagina ufficiale. Spesso il compito si può spostare su un pool separato o su uno script da riga di comando non raggiungibile dal web.
Attivare l'impostazione e controllarne l'effetto
Dopo la modifica PHP deve rileggere la configurazione. Verifichi poi il valore nella modalità di esecuzione del Suo sito, non sulla riga di comando:
sudo systemctl reload php8.3-fpm
php-fpm8.3 -i | grep "^disable_functions"
# Controllare nel log degli errori le chiamate a funzioni bloccate
sudo grep -i "has been disabled" /var/log/php/*.log | tail -20
I messaggi nel log degli errori sono preziosi anche in seguito. Se compaiono all'improvviso chiamate a funzioni bloccate che la Sua applicazione non usa, può indicare codice introdotto di nascosto. Come proseguire in tal caso è descritto nella guida Riconoscere e rimuovere le webshell.
Errori tipici nell'uso di disable_functions
In pratica l'hardening fallisce di rado per ragioni tecniche, ma per piccolezze. Questi errori sono particolarmente diffusi:
- File sbagliato modificato: l'elenco è solo nel php.ini della riga di comando, il sito gira tramite PHP-FPM e resta senza protezione.
- Nessun riavvio: il file è corretto, ma i processi in esecuzione lavorano ancora con la vecchia configurazione.
- Blocco troppo ampio: funzioni come
ini_setomailvengono bloccate insieme alle altre e processi importanti si interrompono senza che nessuno se ne accorga. Gli errori emergono spesso solo dopo giorni, ad esempio quando mancano le conferme d'ordine. - Impostato una volta, mai verificato: dopo un trasloco, un cambio di versione di PHP o una reinstallazione tramite il pannello di hosting l'elenco è scomparso.
- Falso senso di sicurezza: il blocco viene inteso come sostituto degli aggiornamenti. Non chiude però alcuna vulnerabilità nell'interprete.
Inserisca quindi il controllo del valore attivo nella Sua routine dopo ogni aggiornamento di PHP. Basta una rapida occhiata, costa pochissimo tempo e impedisce che un hardening vada perso in silenzio.
Con più siti su un server: crei per ogni sito un pool separato con un proprio elenco. In aggiunta, open_basedir limita le directory a cui PHP può accedere.
Come aiuta concretamente PHP SOS?
- Verifichiamo codice e processi della Sua applicazione rispetto all'uso di funzioni critiche.
- Definiamo per ogni sito un elenco di blocco adatto e lo testiamo prima della messa online.
- Combiniamo il blocco con pool, permessi dei file e registrazione in un concetto di hardening coerente.
- Documentiamo le impostazioni e monitoriamo il log degli errori alla ricerca di chiamate sospette.
Come si svolge il tutto come pacchetto complessivo è descritto nel servizio Hardening del server per server web PHP.
Domande frequenti
Posso impostare disable_functions con ini_set() o .htaccess?
No. L'impostazione funziona solo dal php.ini oppure come php_admin_value nel pool FPM o nella configurazione di Apache. Non si può impostare durante l'esecuzione e l'applicazione non può nemmeno sbloccare di nuovo le funzioni bloccate.
disable_functions protegge da PHP2Shell?
No. PHP2Shell riguarda l'interprete PHP stesso, la vulnerabilità si chiude solo con l'aggiornamento. Le funzioni bloccate possono però restringere il margine di manovra di un aggressore dopo uno sfruttamento riuscito.
Perché php -i mostra un elenco diverso da quello del mio sito?
La riga di comando legge spesso un proprio php.ini. Per il sito conta la configurazione di PHP-FPM, mod_php o LiteSpeed. Verifichi quindi il valore nella modalità di esecuzione con cui gira il Suo sito.
Quali applicazioni hanno bisogno di proc_open o exec?
Dipende dall'applicazione. Casi tipici sono l'elaborazione di immagini tramite programmi esterni, la creazione di PDF, l'invio di posta tramite sendmail o strumenti come Composer. Lo verifichi nel codice e nei requisiti di sistema del produttore.