Una vulnerabilità critica di PHP viene pubblicata di solito insieme alle versioni correttive. Da quel momento la descrizione del problema, il codice della correzione e spesso un exploit sono alla portata di chiunque. Chi usa un ramo supportato aggiorna i pacchetti e chiude la questione. Chi ha in produzione un PHP fuori supporto ha davanti una giornata in cui ogni ora conta, e il rischio maggiore è perderne molte a decidere cosa fare.
In questo articolo descriviamo la sequenza che seguiamo nelle prime 24 ore dopo una CVE critica su PHP: triage, mitigazioni temporanee, correzione con un pacchetto aggiornato o con un backport, test con l’applicazione reale, rilascio con piano di rollback e verifiche finali. È la stessa sequenza dei nostri interventi d’urgenza, e può servire anche come traccia per un team interno.
La giornata in sintesi
Per un intervento d’urgenza su una singola CVE il nostro obiettivo è di 24 ore dall’analisi al rilascio. Le fasi si sovrappongono in parte: le mitigazioni proteggono il server mentre si prepara la correzione, e il test comincia appena il pacchetto è pronto. La linea del tempo qui sotto mostra una ripartizione tipica, che cambia secondo la vulnerabilità e il numero di server.
Ore 0–2: triage
Il triage risponde a una sola domanda: quali server sono davvero esposti a questa CVE? Si parte dall’avviso ufficiale, dalla scheda su NVD o cve.org e dalla correzione pubblicata nel repository di PHP. Da lì si ricavano le versioni affette, la parte di codice coinvolta e le condizioni necessarie per lo sfruttamento: una SAPI precisa, un’estensione, una direttiva di configurazione, un certo tipo di input.
Conviene consultare anche le fonti delle distribuzioni: il database delle CVE di Red Hat, il security tracker di Debian e quello di Ubuntu indicano per ogni pacchetto se è vulnerabile, se è già corretto e con quale versione. Gli advisory di sicurezza del progetto PHP, pubblicati sul repository php-src di GitHub, contengono spesso dettagli tecnici e il riferimento al commit della correzione. Mettere insieme queste informazioni richiede poco tempo ed evita due errori costosi: correre su server che non sono esposti e trascurare quelli che lo sono.
Poi si confrontano queste condizioni con i server reali. Non basta la versione della riga di comando: conta quella che esegue l’applicazione, con la sua SAPI e le sue estensioni. Questi comandi danno un primo quadro:
# Processi PHP-FPM in esecuzione, con utente e pool
ps -eo user,args | grep -E 'php-fpm: (master|pool)' | grep -v grep | sort | uniq -c
# Moduli compilati o caricati da PHP-FPM e dalla CLI
php-fpm -m 2>/dev/null || php -m
# Chi sta davanti a PHP: nginx con FastCGI o Apache con mod_php / proxy_fcgi
nginx -T 2>/dev/null | grep -n fastcgi_pass
apachectl -M 2>/dev/null | grep -Ei 'php|proxy_fcgi'
# Pacchetti installati e loro provenienza
rpm -qa 'php*' --qf '%{NAME}-%{VERSION}-%{RELEASE} %{VENDOR}\n' # famiglia Red Hat e SUSE
dpkg -l 'php*' | grep '^ii' # Debian e Ubuntu
Il risultato del triage è una lista di server divisa in tre gruppi, che determina la priorità di tutto il resto.
Ore 2–4: mitigazioni temporanee
Sui server esposti si applicano subito le misure che riducono il rischio senza toccare l’interprete. Quali siano dipende dalla vulnerabilità:
- disattivare l’estensione coinvolta, se l’applicazione non la usa: una falla nel parsing dei file phar o in un’estensione di immagini non si sfrutta se il modulo non è caricato;
- modificare la configurazione del server web, quando la CVE dipende dal modo in cui le richieste arrivano a PHP, come è successo con la CVE-2019-11043 di PHP-FPM e nginx;
- aggiungere una regola al firewall applicativo, se esiste una firma affidabile per l’attacco;
- restringere l’accesso alle aree amministrative o alle funzioni che ricevono l’input pericoloso, per indirizzo IP o dietro autenticazione.
Ogni mitigazione va provata sull’applicazione, perché disattivare un modulo usato da una funzione secondaria può rompere un flusso che nessuno ricorda. E va annotata, perché dopo il rilascio della correzione alcune vanno rimosse. Abbiamo raccolto le opzioni più utili nell’articolo su come mitigare una vulnerabilità di PHP prima della patch.
Ore 4–14: la correzione
Se il pacchetto installato è ancora mantenuto, dalla distribuzione o da un repository, la correzione è un aggiornamento: si verifica che la nuova versione sia uscita e che il changelog citi la CVE. Se il ramo è fuori supporto, la correzione va portata sul codice in uso con un backport della patch.
Il backport parte dal commit ufficiale, verifica che il codice vulnerabile esista nel ramo installato e adatta la modifica alle sue strutture interne. Il pacchetto si ricostruisce partendo da quello che il server usa già, che sia di Remi, delle Software Collections, di AppStream, della distribuzione o di deb.sury.org: così percorsi, configurazioni ed estensioni restano identici e il rollback è un’operazione semplice. La versione di PHP non cambia; cambiano il numero di release e il changelog, che documenta la CVE corretta.
Ore 14–20: i test con l’applicazione reale
Un pacchetto corretto che rompe il sito non è una soluzione. Il test avviene in un ambiente di prova con la stessa distribuzione, la stessa configurazione di PHP e una copia dell’applicazione reale, in due passaggi:
- i test automatici di PHP relativi all’area corretta, compreso quello che riproduce la vulnerabilità quando il progetto lo pubblica insieme alla correzione;
- la prova dei percorsi critici dell’applicazione: accesso, ricerca, carrello e pagamento per un e-commerce, le funzioni principali e le integrazioni per un gestionale, controllando che nei log di PHP non compaiano errori o avvisi nuovi.
Se un test fallisce, si torna alla correzione prima di toccare la produzione. Le mitigazioni applicate nelle prime ore servono proprio a questo: danno il margine per rifare un passaggio senza esporre il server.
Ore 20–24: rilascio, rollback e verifiche
Il rilascio avviene con Ansible, in modo ripetibile su tutti i server coinvolti. Si comincia da un solo server, si verificano l’applicazione e i log, poi si procede con gli altri. Il piano di rollback è pronto prima di iniziare: il pacchetto precedente resta disponibile e il comando per reinstallarlo è già scritto.
# Prova a secco sul primo server, poi rilascio sul primo e su tutti
ansible-playbook php-patch.yml --limit web01 --check --diff
ansible-playbook php-patch.yml --limit web01
ansible-playbook php-patch.yml
# Verifica sul server: release del pacchetto e CVE nel changelog
rpm -q php-fpm && rpm -q --changelog php-fpm | head -n 5
# Rollback, se serve: torna al pacchetto precedente
dnf history undo last # RHEL 8 e successive, Rocky, Alma
apt install php7.4-fpm=VERSIONE_PRECEDENTE # Debian e Ubuntu
Dopo il rilascio si controllano tre cose: che il processo PHP-FPM sia stato riavviato e usi il nuovo binario, che l’applicazione risponda come prima e che le mitigazioni temporanee non più necessarie vengano rimosse o lasciate in modo consapevole. Infine si scrive il resoconto: CVE, server coinvolti, analisi dell’esposizione, mitigazioni, pacchetto rilasciato, esito dei test. È il documento che serve in un audit e alla prossima vulnerabilità.
Per tutta la giornata conta anche la comunicazione. Chi gestisce l’applicazione deve sapere quando è previsto il rilascio, quali verifiche fare subito dopo e chi chiamare se qualcosa non va. Chi ha la responsabilità della sicurezza deve ricevere l’esito del triage e la lista dei server esposti, per decidere se servono misure aggiuntive. Un messaggio breve a ogni passaggio di fase evita telefonate concitate e decisioni prese senza le informazioni giuste.
Se trovi segni di compromissione
Durante il triage capita di trovare nei log richieste compatibili con l’attacco, file PHP che nessuno ha caricato o processi sconosciuti. In quel caso l’intervento cambia natura: diventa la gestione di un incidente. Prima di correggere si conservano log e copie dei file sospetti, si valuta l’isolamento del server e si coinvolgono le persone responsabili della sicurezza e, quando previsto, chi deve valutare gli obblighi di notifica. Un aggiornamento applicato su un server già compromesso chiude la falla e lascia dentro chi è già entrato.
Cosa preparare prima che serva
Le prime 24 ore vanno molto meglio se alcune cose esistono già. La lista è breve:
- un inventario aggiornato dei server PHP, con versione, SAPI, estensioni e provenienza dei pacchetti;
- un ambiente di prova che riproduca la produzione, con una copia recente dell’applicazione;
- l’automazione del rilascio, con Ansible o con lo strumento che usi, e una procedura di rollback provata almeno una volta;
- un elenco dei percorsi critici da verificare dopo ogni modifica;
- un contatto raggiungibile a qualsiasi ora, interno o esterno.
Le 24 ore chiudono l’urgenza. Il problema di fondo resta, perché un PHP fuori supporto riceverà altre CVE. Per questo ogni intervento d’urgenza dovrebbe chiudersi con una data per la migrazione a un ramo supportato. Se la vulnerabilità è già pubblicata e i tuoi server sono scoperti, la nostra reperibilità H24 risponde al +39 340 985 4556.
Possiamo dunque riassumere
Le prime 24 ore dopo una CVE critica su un PHP fuori supporto seguono una sequenza precisa. Il triage stabilisce quali server sono davvero esposti, confrontando le condizioni della vulnerabilità con versione, SAPI, estensioni e configurazione reali. Le mitigazioni temporanee riducono il rischio mentre si prepara la correzione, che è un aggiornamento se il pacchetto è ancora mantenuto e un backport ricostruito dal pacchetto in uso se il ramo è abbandonato. Il pacchetto si prova con l’applicazione reale in un ambiente di prova, si rilascia con Ansible partendo da un solo server e con il rollback già pronto, si verifica e si documenta. Se emergono segni di compromissione, la priorità diventa la gestione dell’incidente. E alla fine della giornata serve una data per la migrazione.