In quanto tempo le sonde automatiche iniziano a cercare PHP2Shell sul tuo sito
Gli avvisi di CVE-2026-109618 e CVE-2026-109619, le due vulnerabilità note come PHP2Shell, sono usciti il 21 ottobre 2026 alle 13:34 UTC. La prima richiesta che cercava quella falla sul mio sensore è arrivata alle 15:09, un'ora e trentacinque minuti dopo, e Amazon aveva documentato un tentativo già quattro giorni prima della divulgazione. Numeri così alimentano la convinzione che dopo ogni bollettino di sicurezza si abbiano quarantotto ore scarse per correre ai ripari.
Da dodici anni tengo un sensore HTTP su circa seicento domini di mia proprietà, parcheggiati e senza alcuna applicazione installata, e ci ho raccolto 45.430.202 richieste non sollecitate dal 2014. Dentro quell'archivio ho isolato 144 casi difendibili: vulnerabilità per cui so, con una controprova temporale, che qualcuno è venuto a cercarle e quando. PHP2Shell è uno di quei casi, ed è il terzo più veloce di tutti. Il quarto pezzo della serie spiega per esteso il metodo con cui li ho isolati; questo è il pezzo dei numeri che ne escono, e sono molto diversi da quello che suggerisce il caso di oggi.
Prima però devo mettere in chiaro cosa significa un caso, perché su questo si costruiscono tutte le interpretazioni che seguono e anche tutti gli abusi possibili.
Un caso dice: esiste un percorso HTTP che appartiene a una sola vulnerabilità nota, quel percorso è comparso nel mio archivio in una certa data, quella data è successiva al momento in cui il mondo ha saputo della vulnerabilità, e prima di quel momento sul percorso non passava traffico. Non dice niente su quante installazioni siano state compromesse, perché sui miei domini non c'è niente da compromettere. Misuro quando una vulnerabilità entra negli strumenti di scansione di massa, non quanti danni fa.
Quanto tempo passa davvero fra la pubblicazione di una CVE e la prima sonda?
Sui 144 casi del mio archivio, il ritardo mediano fra divulgazione e prima sonda è di 523 giorni, cioè un anno e cinque mesi. Solo due casi su 144 sono arrivati entro quarantotto ore, tre entro la settimana, quindici entro il mese.
Il ritardo minimo è un giorno, il massimo 7.159, cioè diciannove anni e mezzo. Ottantacinque casi su 144, il 59 per cento, hanno un ritardo superiore all'anno. La forma della distribuzione, presa dall'archivio del mio sensore, è più eloquente di qualunque media:
| Ritardo | Casi (casi) |
|---|---|
| 0-2 giorni | 2 |
| 3-7 giorni | 1 |
| 8-30 giorni | 12 |
| 31-90 giorni | 15 |
| 91-180 giorni | 14 |
| 181-365 giorni | 15 |
| 1-2 anni | 25 |
| oltre 2 anni | 60 |
Questo contrasta con la narrazione corrente in modo abbastanza netto. La frase "hai quarantotto ore per applicare la patch" descrive bene due casi su 144.
Prima di trarne conclusioni sbagliate, vanno dette due cose sul perché la coda è così lunga.
La prima è la natura del mio sensore. Vedo scansione opportunistica di massa, cioè chi prova tutto su tutti senza sapere cosa troverà. Quel tipo di attività segue i tempi degli strumenti: una vulnerabilità entra in un template, il template entra in uno strumento, lo strumento entra nelle mani di molti, e ogni passaggio costa settimane o mesi. Chi invece attacca mirato, perché sa già cosa c'è su un bersaglio specifico, si muove molto prima e non passa dai miei domini. I due fenomeni sono diversi e io ne vedo solo uno.
La seconda è che un ritardo lungo non è un errore di misura. Ho verificato che per tutti i casi con ritardo superiore all'anno il traffico sul percorso prima della divulgazione era esattamente zero. Sono arrivi genuinamente tardivi, non percorsi generici mascherati.
Due letture possibili, una sola corretta
La lettura sbagliata è: la mediana è 523 giorni, quindi si può aggiornare con calma.
Il motivo per cui è sbagliata sta nella forma della distribuzione. La distribuzione ha una testa piccola e molto rapida, poi una coda che si allunga per anni. La mediana descrive la massa, la testa descrive il rischio. Se la tua installazione sta nella testa, i 523 giorni di mediana non ti riguardano affatto, e nella testa ci stanno le cose più gravi, come si vede fra un attimo.
La fretta è una risorsa scarsa. Un'organizzazione che tratta ogni bollettino come un'emergenza da quarantotto ore consuma la sua capacità di reazione su cose che arriveranno fra due anni, e quando arriva quella che arriva in un giorno non ha più fiato.
Il problema sta nel saper distinguere. E si distingue, perché i casi veloci hanno caratteristiche riconoscibili.
Distinguere bene occupa la prima settimana quando entro in un'infrastruttura PHP che nessuno aggiorna da anni: inventario, priorità, prima le cose che arrivano in giorni e poi la coda. Se vuoi capire con chi avresti a che fare, nel mio profilo professionale trovi l'esperienza su sicurezza, hardening e modernizzazione di stack PHP in produzione.
I casi veloci, uno per uno
Questa è la tabella dei nove casi più rapidi, con tutto ciò che so di loro al momento in cui sono stati osservati.
| Vulnerabilità | Ritardo | Reti sorgente | Richieste | In KEV | EPSS |
|---|---|---|---|---|---|
| CVE-2024-4577 (PHP-CGI) | 1 giorno | 207 | 732 | dopo 3 giorni | 0,99987 |
| CVE-2026-8181 (*) | 2 giorni | 25 | 85 | no | 0,03012 |
| CVE-2026-85097 (*) | 5 giorni | 49 | 25 | no | 0,01292 |
| CVE-2026-85688 | 10 giorni | 207 | 1.254 | no | 0,02641 |
| CVE-2024-27956 | 11 giorni | 12 | 86 | no | 0,94057 |
| CVE-2021-3129 (Laravel Ignition) | 12 giorni | 161 | 1.108 | dopo oltre 2 anni | 0,99943 |
| CVE-2020-25213 | 14 giorni | 59 | 65 | dopo 14 mesi | 0,97328 |
| CVE-2024-28987 | 16 giorni | 13 | 18 | dopo 2 mesi | 0,93299 |
| CVE-2023-23752 (Joomla) | 21 giorni | 35 | 165 | dopo 11 mesi | 0,99827 |
I due casi marcati con l'asterisco meritano una precisazione che toglie loro parte del valore. Il percorso su cui li ho riconosciuti è il file readme.txt di un plugin, cioè il file che uno scanner scarica per leggere il numero di versione di quello che è installato. Una richiesta così dice che qualcuno sta inventariando quel plugin, non che stia provando a sfruttare quella vulnerabilità. Restano casi veri nel senso che il percorso è apparso dopo la divulgazione, ma la distanza fra "mi stanno enumerando" e "mi stanno attaccando" qui è tutta. Nel mio impianto questi casi sono marcati come enumerazione e non raggiungono la confidenza alta, e sono quattro su 144.
Il caso più veloce è quello che mi riguarda professionalmente di più, perché è PHP. La vulnerabilità di PHP-CGI del giugno 2024, quella dell'iniezione di argomenti, è stata pubblicata il 9 giugno e la prima sonda sui miei domini è arrivata il 10. Ventiquattro ore. Non da un singolo curioso: 207 reti distinte nella finestra di osservazione, per 732 richieste. Il catalogo delle vulnerabilità sfruttate attivamente l'ha recepita tre giorni dopo la pubblicazione, e il punteggio di probabilità di sfruttamento è 0,99987, cioè praticamente uno.
Guardando la colonna del punteggio EPSS si nota una cosa utile. Sei casi su nove hanno un punteggio superiore a 0,9, e cinque su nove sono finiti nel catalogo delle vulnerabilità sfruttate. In un gruppo di 144 casi dove quelli con punteggio alto sono 41 e quelli in catalogo 42, cioè meno di un terzo in entrambi i casi, trovarne sei e cinque su nove nella testa della distribuzione è un segnale. Non è una dimostrazione statistica, con nove osservazioni non si dimostra niente, ma è coerente con l'idea che quei due indicatori servano esattamente a questo.
Ci sono però tre casi veloci con punteggio basso, intorno a 0,01 e 0,03. Sono tutti e tre vulnerabilità di plugin per un noto gestore di contenuti, pubblicate quest'anno, e sono state sondate entro dieci giorni. Il punteggio non le aveva viste venire. Questo è il limite di qualunque indicatore predittivo: è una probabilità, e le probabilità basse si realizzano.
I casi larghi non sono i casi veloci
C'è un secondo modo di ordinare i 144 casi, per numero di reti che hanno mandato la richiesta, e produce una classifica completamente diversa da quella del ritardo.
| Vulnerabilità | Reti sorgente | Richieste | Ritardo |
|---|---|---|---|
| CVE-2020-26214 | 979 | 3.639 | 952 giorni |
| CVE-2023-5556 | 760 | 19.618 | 522 giorni |
| CVE-2026-4020 | 681 | 11.034 | 21 giorni |
| CVE-2014-9180 | 639 | 2.839 | 1.720 giorni |
| CVE-2024-37152 | 631 | 2.066 | 336 giorni |
| CVE-2018-1273 | 580 | 16.856 | 922 giorni |
Il caso più diffuso del mio archivio ha un ritardo di 952 giorni. Il secondo, con quasi ventimila richieste, 522 giorni. Un caso del 2014 è ancora cercato da 639 reti diverse.
Sono due fenomeni distinti e vale la pena nominarli separatamente. C'è la rapidità, cioè quanto presto una vulnerabilità viene provata, e c'è la persistenza, cioè quanto a lungo e quanto largamente resta negli strumenti. Non sono correlate. Una vulnerabilità può arrivare in un giorno e poi sparire, e un'altra può arrivare dopo tre anni e diventare parte dell'arredamento di internet per sempre.
La persistenza è la ragione per cui il software esposto va aggiornato anche quando la vulnerabilità è vecchia e non fa più notizia. Nel mio archivio le vulnerabilità del 2018 generano ancora oggi traffico: nove casi hanno origine in quell'anno, e alcuni sono fra i più larghi di tutti. Chi ha un'installazione non aggiornata del 2018 porta un rischio corrente, non un cimelio, perché quella richiesta arriva ancora adesso.
Per chi lavora su hosting condiviso la conseguenza è concreta e la vedo regolarmente nei progetti che prendo in mano. Un sito fermo da sei anni su un pannello di gestione non aggiornato non è "vecchio ma tranquillo perché nessuno lo conosce". Le richieste che lo cercano sono le stesse che arrivano sui miei domini parcheggiati, cioè quelle di chi non sa e non gli importa cosa ci sia dietro il nome. L'oscurità non protegge da un processo automatico che prova tutto su tutti.
Come leggere i due indicatori pubblici senza farsi male
Ho citato più volte due riferimenti e vale la pena spiegare cosa sono, perché vengono usati a rovescio con una certa frequenza.
Il primo è il punteggio di probabilità di sfruttamento, l'EPSS pubblicato da FIRST, che stima quanto è probabile che una vulnerabilità venga sfruttata nei trenta giorni successivi. È una probabilità, non un giudizio di gravità, e le due cose vengono confuse in continuazione. Un difetto devastante su un software installato in cinquanta posti al mondo può avere un punteggio basso, perché quasi nessuno si prenderà la briga di cercarlo. Un difetto banale su un plugin installato in un milione di siti può avere un punteggio altissimo. Serve a ordinare la coda, non a decidere quanto male fa una cosa.
Il secondo è il catalogo KEV della CISA, un elenco di difetti per cui esiste evidenza documentata di sfruttamento reale. Qui il dato cambia natura: diventa una constatazione a posteriori. Il che significa che è affidabile e tardivo per costruzione. Nei miei casi veloci il catalogo ha recepito in tre giorni il caso più eclatante, ma negli altri ha messo fra due mesi e oltre due anni. Chi lo usa come innesco dell'urgenza accetta quel ritardo senza saperlo. Lo si vede bene su PHP2Shell: tentativi documentati da più fonti già nelle prime ore, e nessuna delle due CVE nel catalogo a due giorni dalla pubblicazione.
Il modo sano di usarli insieme è asimmetrico. Punteggio alto significa "mettilo davanti nella coda", punteggio basso non significa "ignoralo": tre dei miei nove casi veloci avevano punteggio intorno a 0,01 e sono stati sondati entro dieci giorni. Presenza nel catalogo significa "non c'è più niente da discutere", assenza dal catalogo non significa niente del genere, perché l'assenza può essere solo il ritardo del processo di verifica.
Un terzo riferimento che non ho usato ma che vale la pena nominare è il punteggio di gravità tecnica, il CVSS. Non l'ho messo nelle tabelle perché nei miei dati non distingue niente: nella testa della distribuzione e nella coda ci sono vulnerabilità con punteggi alti in proporzioni simili. Misura quanto è brutto il difetto se qualcuno lo sfrutta, che è una domanda diversa da quella se qualcuno verrà a cercarlo.
La distribuzione per anno della vulnerabilità
I 144 casi si distribuiscono così per anno della CVE, con il 2013 e il 2016 a zero e gli anni dal 2004 al 2012 accorpati perché insieme fanno sei casi:
| Anno della CVE | Casi (casi) |
|---|---|
| 2004-2012 | 6 |
| 2013 | 0 |
| 2014 | 3 |
| 2015 | 4 |
| 2016 | 0 |
| 2017 | 5 |
| 2018 | 9 |
| 2019 | 8 |
| 2020 | 11 |
| 2021 | 7 |
| 2022 | 6 |
| 2023 | 12 |
| 2024 | 28 |
| 2025 | 18 |
| 2026 | 27 |
La concentrazione sugli anni recenti ha due spiegazioni che si sommano, e non si possono separare con questi dati. Da una parte le vulnerabilità recenti sono più numerose e il corpus di firme pubbliche è cresciuto molto. Dall'altra il mio archivio ha una copertura disomogenea.
Nota
Il recupero dai log del web server comincia nel febbraio 2018, e c'è un'interruzione di raccolta fra gennaio 2022 e gennaio 2023 che si vede chiaramente nella colonna del 2022.
Quindi la lettura "le vulnerabilità recenti vengono cercate di più" non è sostenibile con questi numeri. La lettura sostenibile è: ho più casi recenti, e una parte dell'effetto è mio.
Dichiarare questo tipo di limite non è pignoleria. Un grafico come quello sopra, pubblicato senza la nota sulla copertura, diventa una tendenza storica in mano al primo che la cita, e quella tendenza non esiste.
Cosa cambia nella priorità delle patch
Provo a tradurre questi numeri in qualcosa che si possa usare il lunedì mattina, con la cautela che tutto quello che segue vale per software esposto su internet e raggiungibile senza autenticazione, che è l'unica cosa che il mio sensore vede.
Il criterio del tempo da solo non funziona. "Aggiorna entro quarantotto ore tutto ciò che è critico" descrive male la realtà: su 144 casi, quarantotto ore sono state il tempo disponibile due volte. Tenere quel criterio per tutto significa non poterlo rispettare per niente.
I due indicatori pubblici meritano il peso che hanno. Nella testa della distribuzione il punteggio di probabilità di sfruttamento e la presenza nel catalogo delle vulnerabilità sfruttate sono sovrarappresentati rispetto alla loro frequenza nel gruppo intero. Se devi scegliere due filtri gratuiti da mettere in cima al processo, sono quelli.
Il catalogo delle sfruttate arriva spesso dopo. Nei miei casi veloci il catalogo ha recepito in tre giorni una volta, in due mesi un'altra, in undici mesi un'altra, in quattordici mesi un'altra, in oltre due anni un'altra. Usarlo come innesco unico significa accettare quel ritardo. Vale come conferma, non come allarme.
Lo stack conta più della gravità astratta. I casi veloci del mio archivio sono interprete PHP, framework PHP, plugin di gestori di contenuti, cioè esattamente il materiale che sta su un hosting condiviso italiano qualunque. Se hai quello stack, sei nel bersaglio della scansione rapida. Se hai un apparato di rete esposto, sei in un altro bersaglio che io non vedo e che segue tempi suoi.
La coda lunga impone una manutenzione, non una reazione. Il 59 per cento dei casi arriva dopo più di un anno. Contro quelli non serve velocità, serve che fra un anno il sistema sia ancora aggiornato. È un problema di processo ripetuto, non di risposta all'emergenza, e in genere è il problema che le organizzazioni risolvono peggio, perché non ha l'urgenza che fa scattare le decisioni. Per le dipendenze applicative un pezzo di quel processo si automatizza, come racconto nella guida all'aggiornamento automatico delle dipendenze PHP con Dependabot e Renovate; per l'interprete e il sistema operativo serve qualcuno che se ne occupi.
Misurarlo sui propri log, senza costruire un sensore
Niente di tutto questo richiede dodici anni di archivio. Chi ha un sito in produzione ha già i dati per rispondere alla domanda che conta davvero, cioè non "quando il mondo viene sondato" ma "quando vengo sondato io", e la risposta locale è più utile della mia.
Serve poco. I log del web server conservati per un periodo ragionevole, diciamo un anno, e la possibilità di cercarci dentro. Poi tre abitudini.
La prima è guardare i percorsi mai visti prima. Un conteggio giornaliero dei percorsi richiesti che non compaiono nello storico è una riga di script e produce l'allarme giusto: quando una vulnerabilità nuova entra negli strumenti di scansione, il suo percorso è per definizione un percorso nuovo per il tuo sito. È lo stesso principio del test temporale che descrivo nel pezzo sul metodo, applicato in diretta invece che a posteriori.
La seconda è separare il traffico di servizio. Sui miei domini i redirect canonici sono il 24 per cento delle richieste, 11.030.463 su 45 milioni, e contarli dentro i volumi falsa tutto. Sul tuo sito l'equivalente sono le richieste dei tuoi sistemi di monitoraggio, i controlli di disponibilità, i crawler legittimi e il tuo stesso traffico di lavoro. Finché stanno nel conteggio, qualunque anomalia resta sepolta.
La terza è tenere l'inventario di cosa hai esposto, con le versioni. Questa è la parte noiosa e quella che manca sempre. Il punteggio di probabilità di sfruttamento più alto del mondo su un componente che non hai installato è rumore, e un punteggio modesto su qualcosa che sta in produzione da sei anni è il tuo problema. Senza l'inventario, nessuna classifica esterna si può tradurre in una decisione.
Chi fa questi tre passi scopre una cosa che nel mio archivio si vede bene: la maggior parte del traffico non sollecitato non cerca vulnerabilità nuove, cerca cose vecchie, e le cerca in continuazione. L'emergenza occupa lo spazio mentale, la manutenzione decide gli esiti.
Le vulnerabilità che nessuno è venuto a cercare
Chiudo con il risultato più curioso, che è anche quello su cui ho dovuto frenare per onestà.
Delle 2.312 vulnerabilità che hanno una firma di rilevamento pubblica e un percorso distintivo, nel mio archivio non ne ho mai vista comparire 1.705. Di queste, 150 sono nel catalogo delle vulnerabilità sfruttate attivamente.
Letta male, questa riga diventa un titolo del tipo "150 vulnerabilità ufficialmente sfruttate che nessuno cerca davvero", e sarebbe una sciocchezza. Ho guardato l'elenco. In maggioranza sono vulnerabilità di apparati: videosorveglianza, dispositivi di rete, interfacce di gestione fuori banda, appliance aziendali. Nessuno le cerca su un dominio parcheggiato perché non è lì che stanno. L'assenza misura la distanza fra il mio sensore e il loro bersaglio.
Resta però un sottoinsieme che non si spiega così, e sono le vulnerabilità di software che su un dominio web ci starebbe benissimo. Fra queste ce n'è una del 2019 che riguarda una configurazione molto diffusa di PHP in produzione, ed è nel catalogo delle sfruttate: a quella mi aspettavo di vedere qualcuno bussare, e non ho mai visto nessuno. Non ho una spiegazione soddisfacente, e trovarne una è un lavoro che vale la pena fare prima di raccontarlo come un risultato.
È il motivo per cui la riga delle 1.705 non la pubblico come numero principale. Un numero che richiede quattro frasi di precisazione per non essere fuorviante resta un'osservazione in attesa di metodo.
Cosa resta fuori da tutto questo
I confini sono la parte che rende i numeri sopra utilizzabili, quindi li dico per esteso. Misuro pressione di scansione, non compromissioni. Vedo solo vulnerabilità che si cercano con un percorso HTTP distintivo: quelle che si sondano nel corpo di una richiesta o in un header mi restano invisibili per tutta la storia dell'archivio, perché corpo e header li conservo solo dall'ultimo mese. Vedo scansione opportunistica, non attacchi mirati. Il mio archivio ha un buco di un anno e una partenza del recupero storico nel 2018. E il denominatore, cioè quante vulnerabilità esistano davvero là fuori, non lo conosco: conosco quelle che hanno una firma pubblica, che sono 3.665.
PHP2Shell, con la sua ora e trentacinque minuti, sta all'estremo sinistro di questa distribuzione e non la rappresenta: è il terzo caso su 144 ad arrivare entro quarantotto ore. Chi è arrivato qui senza aver letto i due pezzi precedenti li trova nella cronaca della scoperta di PHP2Shell, con i controlli da fare sulle macchine, e nella spiegazione del difetto che la rende sfruttabile. Come ho costruito e difeso ciascuno di quei 144 casi sta nel pezzo sul metodo, con i filtri che servono e le due trappole in cui sono caduto; cosa è arrivato davvero sul mio sensore nelle ore successive agli avvisi sta nel racconto delle prime quarantotto ore.
Se il tuo problema è la coda lunga, cioè uno stack che nessuno aggiorna da anni e un inventario che non esiste, contattami. È il lavoro meno spettacolare che faccio ed è quello che decide più esiti, e non si limita a PHP: web server, database, sistema operativo, applicazione e le dipendenze che si porta dietro vanno messi in sicurezza insieme, perché la prossima falla non è detto che esca dall'interprete.