# Mettere in sicurezza Nginx con PHP-FPM

> Sicurezza Nginx e PHP-FPM dopo PHP2Shell: verificare pool e versioni, riavviare tutti i worker, impostare i valori transitori con php_admin_value e rafforzare Nginx.

Fonte: https://phpsos.de/it/server/nginx-php-fpm/  
Stato: 25/10/2026  
Fornitore: PHP SOS, Assistenza di emergenza PHP e sicurezza dei server. Assistenza immediata su WhatsApp: https://wa.me/491736494914?text=Buongiorno%20PHP%20SOS%2C%20abbiamo%20bisogno%20di%20aiuto%20con%20il%20nostro%20server%20PHP.%20Azienda%3A%20%E2%80%A6%20Sito%20web%3A%20%E2%80%A6

**In breve:** con Nginx e PHP-FPM la vulnerabilità di PHP2Shell si trova in PHP-FPM, non in Nginx. Aggiorni tutte le versioni di PHP-FPM, riavvii per intero ogni servizio FPM e lo dimostri con gli orari di avvio dei processi. Per la sicurezza di Nginx e PHP-FPM nel lungo periodo contano pool separati, valori non sovrascrivibili e una configurazione di Nginx che non esegua i file caricati.

## Come collaborano Nginx e PHP-FPM

Nginx serve da sé i file statici e inoltra le richieste agli script PHP a PHP-FPM tramite FastCGI. PHP-FPM è composto da un processo master e da più processi worker, raggruppati in pool. Un worker elabora una dopo l'altra molte richieste.

È proprio questo a essere rilevante per PHP2Shell. Con CVE-2026-109619, lo stato interno di una richiesta può persistere dopo il rilascio della memoria ed essere usato da una richiesta successiva nello stesso worker. Con CVE-2026-109618, una condizione di out-of-memory può interrompere PHP nel mezzo dell'inizializzazione di una richiesta. Entrambe le vulnerabilità sono valutate CVSS v4.0 9.2 e sono corrette in PHP 8.5.12, 8.4.27, 8.3.36 e 8.2.35.

## Verificare l'inventario: versioni, pool, processi

Molti server hanno in parallelo più versioni di PHP-FPM. I comandi seguenti leggono soltanto; i nomi di pacchetti e servizi sono esempi per Debian/Ubuntu e la famiglia RHEL.

```bash
# Quali servizi FPM sono in esecuzione?
systemctl list-units --type=service | grep -i fpm

# Quale versione c'è dietro? (esempio Debian/Ubuntu)
php-fpm8.3 -v
# Famiglia RHEL
php-fpm -v

# A quali socket o porte inoltra Nginx?
nginx -T 2>/dev/null | grep -E 'fastcgi_pass'

# Pool e relativi utenti
grep -RhE '^\[|^user|^listen' /etc/php/*/fpm/pool.d/ 2>/dev/null
```

Confronti ogni voce `fastcgi_pass` con un pool in esecuzione. Così vede quale versione di PHP serve quale sito. Per i pacchetti delle distribuzioni è il changelog con i numeri CVE a provare la patch, non il solo numero di versione.

Un riscontro frequente in questi inventari sono i server su cui nel corso degli anni sono state installate più versioni di PHP, delle quali una sola è effettivamente in uso. Gli altri servizi FPM continuano comunque a girare, spesso con pool standard in ascolto su un socket o una porta locale. Dall'esterno di solito non sono raggiungibili direttamente, ma restano un rischio inutile e allungano ogni aggiornamento d'emergenza. Disattivi e rimuova le versioni che nessun sito utilizza, dopo aver verificato l'assegnazione tramite le voci `fastcgi_pass`.

Vale la pena guardare anche all'utente dei pool. Se tutti i pool girano come `www-data` o `nginx`, la separazione tra i siti esiste solo sulla carta. Chi prende il controllo di un sito può allora leggere i file di tutti gli altri, ad esempio file di configurazione con password del database. Utenti di sistema separati per ogni pool e permessi dei file adeguati creano qui un vero confine. Non è un rimedio per PHP2Shell, ma limita in modo sensibile il possibile danno di un attacco riuscito.

## Installare la patch e rinnovare tutti i worker

Dopo l'aggiornamento dei pacchetti riavvii ogni servizio PHP-FPM. Un reload sostituisce sì i worker, ma solo un riavvio completo rinnova anche il processo master ed è la via sicura dopo gli aggiornamenti di sicurezza.

```bash
# Esempio Debian/Ubuntu, per ogni versione installata
systemctl restart php8.3-fpm
# Famiglia RHEL
systemctl restart php-fpm

# Controllo: orario di avvio di master e worker
ps -eo pid,lstart,cmd | grep -E 'php-fpm' | grep -v grep
```

Ogni processo deve essere stato avviato dopo l'aggiornamento. La procedura è descritta in dettaglio alla pagina [Riavviare PHP-FPM e tutti i worker](https://phpsos.de/it/php2shell/php-fpm-neustart/).

> **Importante:**
> Una patch non rimuove il malware introdotto prima. Conservi i log di accesso e di errore di Nginx a partire dal 20/10/2026 e verifichi la presenza di tracce nei siti.

## Impostare i valori transitori nel pool

Finché una versione non è aggiornata, php.net raccomanda misure transitorie. Non offrono una protezione completa. In PHP-FPM imposti i valori con `php_admin_value` o `php_admin_flag` nel pool: in questo modo le applicazioni non possono sovrascriverli con `ini_set()`.

```ini
; Esempio: /etc/php/8.3/fpm/pool.d/website.conf
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 24M
```

Senza funzione di upload, php.net indica `post_max_size = 8M`. Su PHP 8.5 si aggiunge `fatal_error_backtraces=0`. Per l'indicazione su `memory_limit=-1` serve un limite di memoria a livello di cgroup, ad esempio tramite `MemoryMax` in un'integrazione systemd per il servizio FPM. In Nginx adegui `client_max_body_size` al nuovo `post_max_size`, in modo che gli utenti ricevano messaggi di errore comprensibili. Poi riavvii FPM.

## Migliorare nel tempo la sicurezza di Nginx e PHP-FPM

Oltre al caso acuto aiutano alcune regole di base che limitano il danno in caso di future vulnerabilità:

- **Un pool per ogni sito** con utente di sistema proprio, socket proprio e confine `open_basedir` proprio. Maggiori informazioni alla pagina [open_basedir e isolamento per sito](https://phpsos.de/it/ratgeber/open-basedir/).
- **Permessi del socket** impostati in modo che possa accedervi solo Nginx; non aprire all'esterno porte FPM.
- **Eseguire solo script esistenti:** nella location PHP impostare `try_files $uri =404;`, in modo che Nginx non passi a PHP percorsi inesistenti.
- **Non eseguire gli upload:** vietare l'esecuzione di PHP nelle directory di upload. Trova indicazioni alla pagina [Implementare in sicurezza gli upload di file](https://phpsos.de/it/ratgeber/datei-upload-sicher/).
- **Proteggere le pagine di stato:** rendere `pm.status_path` e `ping.path` raggiungibili solo dall'interno.

```nginx
# Esempio: nessuna esecuzione di PHP nella directory di upload
location ~* ^/uploads/.*\.php$ {
    deny all;
}
```

Verifichi ogni modifica con `nginx -t` prima di ricaricare Nginx. Annoti inoltre quali pool, versioni e regole particolari esistono sul server. Questa breve documentazione fa risparmiare tempo prezioso alla prossima vulnerabilità critica, perché nessuno deve prima cercare quale sito dipenda da quale pool.

## Come aiuta concretamente PHP SOS?

- Assegniamo ogni sito al proprio pool e alla propria versione di PHP e verifichiamo l'effettivo stato dei pacchetti.
- Aggiorniamo, riavviamo tutti i servizi FPM e documentiamo gli orari di avvio dei processi come prova.
- Fino alla patch impostiamo i valori transitori per ogni pool e limitiamo la memoria tramite cgroup.
- Nell'ambito dell'[hardening dei server](https://phpsos.de/it/leistungen/server-haertung/) separiamo in modo pulito pool, permessi e directory di upload.
- In caso di sospetta intrusione ci occupiamo dell'[incident response](https://phpsos.de/it/leistungen/incident-response/).


## Domande frequenti

**Dopo un aggiornamento basta systemctl reload per PHP-FPM?**  
Un reload rinnova i worker, ma il processo master può mantenere il vecchio codice. Dopo un aggiornamento di sicurezza la via sicura è un riavvio completo del servizio. Poi controlli l'orario di avvio di master e worker.

**Nginx deve essere riavviato dopo un aggiornamento di PHP?**  
Nginx di per sé non contiene PHP e non deve riavviarsi per la patch di PHP. Devono riavviarsi tutti i servizi PHP-FPM. Se nel frattempo modifica la configurazione di Nginx, la verifichi con nginx -t prima del ricaricamento.

**Perché un pool separato per ogni sito?**  
Ogni pool gira con un utente proprio e con limiti propri. Se un sito viene compromesso, l'aggressore non arriva senza difficoltà ai file degli altri. Inoltre i valori transitori si possono impostare in modo mirato per ogni pool.

**pm.max_requests è una protezione contro PHP2Shell?**  
No, non sostituisce una patch. Il valore limita quante richieste elabora un worker prima di essere sostituito. Questo può accorciare la durata degli stati nel processo, ma non è un rimedio indicato da php.net.

## Fonti

- [php.net: bollettini di sicurezza](https://www.php.net/)
- [PHP 8 ChangeLog](https://www.php.net/ChangeLog-8.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
- [BSI](https://www.bsi.bund.de/)
