Scheda hero di PHP2Shell: da una richiesta fallita all'esecuzione di codice remoto, CVE-2026-109618 e CVE-2026-109619
Engineering & Research

Ricerca OrcaCyber - PHP2Shell: come una richiesta fallita è diventata esecuzione di codice remoto

Autore

Rowan Sterling

Data di pubblicazione

Ultimi modelli · 20Vedi tutti i modelli →
Benchmark: Artificial Analysis · aggiornato ogni giorno
Torna a tutti gli articoli

Il proof of concept di questa indagine è stato creato con i modelli OrcaCyber Zero e OrcaCyber Ultra. Il pacchetto di ricerca documenta l'analisi a livello di codice sorgente, una riproduzione controllata tramite un exploit pubblico adattato, un artefatto di divulgazione di memoria, crash dei processi e prove di esecuzione di comandi. I file forniti non registrano in modo indipendente quali passaggi siano stati eseguiti da ciascun modello; l'attribuzione dei modelli è fornita dal team di ricerca.

Una condizione fatale di esaurimento della memoria dovrebbe terminare una richiesta in modo sicuro. Qui poteva interrompere PHP mentre lo stato nativo era solo parzialmente inizializzato, lasciando riferimenti che persistevano nella richiesta successiva. Il risultato era una violazione della durata della memoria tra richieste, con conseguenze che andavano dalla divulgazione all'esecuzione di codice remoto nell'ambiente testato.

Principali prove a colpo d'occhio

• Obiettivo — PHP 8.4.26, Apache/mod_php, singolo worker, laboratorio Docker isolato.

• Log di crash — Un SIGABRT e tre terminazioni di worker dovute a SIGSEGV nell'estratto fornito.

• Risposta HTTP — 819.200 byte nel valore PHPSESSID decodificato dall'URL.

• Prova di esecuzione — code>uid=33(www-data) gid=33(www-data) groups=33(www-data)/code>.

• Regressione — Il report descrive quattro tentativi non riusciti su PHP 8.4.27 con patch; le esecuzioni grezze non sono incluse.

Fonte: REPORT.md, crash_evidence.log, leak_attempt.resp e rce_proof_8426.txt caricati. I reperti descritti di seguito riproducono tali artefatti come pannelli probatori composti tipograficamente; non sono fotografie né screenshot nativi del terminale.

1. La vulnerabilità: errore di ownership al confine della richiesta

I due problemi correlati riguardano l'inizializzazione interrotta delle richieste e i puntatori globali di runtime obsoleti. Nell'architettura PHP in questione, la gestione di multipart/form-data e i callback di avanzamento del caricamento delle sessioni possono essere eseguiti prima del normale codice dell'applicazione utente. Una transizione eccezionale del flusso di controllo, inclusa code>zend_bailout()/code>, può saltare la pulizia prevista e lasciare lo stato che punta a memoria che viene successivamente rilasciata o riutilizzata.

Invariante di sicurezza: un riferimento globale al worker esposto alla richiesta B non deve mai puntare a memoria la cui proprietà e il cui ciclo di vita sono terminati con la richiesta A. Il malfunzionamento segnalato viola tale invariante.

L'endpoint dimostrato era una pagina PHP minimale che restituiva semplicemente OK; la narrazione dell'exploit non dipendeva da endpoint applicativi di SQL injection, inclusione di file o deserializzazione.

2. Sequenza tecnica

• A1 — interruzione. La gestione di multipart e dell'avanzamento del caricamento causa OOM durante la pulizia, lasciando uno stato di sessione obsoleto.

• B1 — fuga. Una richiesta successiva provoca una lettura oltre un ID di sessione valido durante la serializzazione del cookie di sessione.

• Recupero degli indirizzi. I valori di puntatore divulgati vengono utilizzati per dedurre il layout pertinente della libreria e dell'heap in quella build.

• A2/B2 — corruzione. Un'ulteriore sequenza di due richieste modella e reindirizza i dati obsoleti usati allo spegnimento.

• Esito. L'exploit pubblico adattato riporta l'esecuzione di comandi come www-data.

Five-step diagram of the PHP2Shell chain from OOM interruption to command execution as www-data, reconstructed from the research bundle

Reperti probatori: cosa mostrano effettivamente i file forniti

Reperto A — terminazione del worker dal log di Apache

• code>[core:notice] [pid 1:tid 1] AH00051: il pid figlio 54 è terminato con segnale Abort (6), possibile coredump in /etc/apache2/code>

• code>[core:notice] [pid 1:tid 1] AH00051: pid figlio 55 terminato con segnale Segmentation fault (11), possibile coredump in /etc/apache2/code>

• code>[core:notice] [pid 1:tid 1] AH00051: il processo figlio pid 58 è terminato con segnale Segmentation fault (11), possibile coredump in /etc/apache2/code>

• code>[core:notice] [pid 1:tid 1] AH00051: il processo figlio con pid 61 è terminato con segnale Segmentation fault (11), possibile coredump in /etc/apache2/code>

Estratto impaginato da crash_evidence.log (23 ottobre 2026). Numerose terminazioni dei worker avvalorano un errore di sicurezza della memoria; i crash da soli non dimostrano l'RCE.

• code>HTTP/1.1 200 OK/code>, con i dati binari omessi.

• code>Server: Apache/2.4.69 (Debian)/code>

• code>X-Powered-By: PHP/8.4.26/code>

• code>Set-Cookie: PHPSESSID=[dati binari omessi]/code>

• Lunghezza del cookie codificato: 2.330.754 byte.

• Valore decodificato dall'URL: 819.200 byte.

La misurazione è calcolata direttamente da leak_attempt.resp. Il valore binario è intenzionalmente omesso per evitare di riprodurre eventuali contenuti di processo trapelati.

Allegato C — prova di esecuzione

code>uid=33(www-data) gid=33(www-data) groups=33(www-data)/code>

Contenuto esatto di rce_proof_8426.txt, come fornito. Supporta l'esito di esecuzione riportato, ma non è una trascrizione completa dei comandi o della sessione.

Evidence summary card: four worker exits, an 819,200-byte URL-decoded session cookie, and uid=33 execution context

Allegato D — correzione del ciclo di vita della sessione

• code>static inline void php_rinit_session_globals(void)/code>

• code>@@ -121,6 +120,7 @@ static inline void php_rinit_session_globals(void)/code>

• code>* ricodifica la sessione all'avvio della richiesta, prima di RINIT, quando nessun utente/code>

• code>/* Viene eseguito prima di RINIT: nessun codice utente può essere invocato, vedi php_session_unserialize_init() *//code>

• code>/* Questo viene eseguito prima di RINIT, quindi dobbiamo ripulirli in anticipo *//code>

• code>php_rinit_session_globals();/code>

Righe selezionate del diff del codice sorgente da session.c.diff. Questa modifica reimposta esplicitamente lo stato globale della sessione in anticipo rispetto al normale RINIT.

3. Perché le prove sono importanti

La divulgazione di memoria fornisce il ponte tra un crash di processo e una catena di exploit. Un valore di sessione di dimensioni anomale con dati binari incorporati è coerente con il runtime che interpreta memoria non valida come stringa Zend. Il rapporto di ricerca descrive inoltre l'estrazione di indirizzi di codice e heap dalla finestra divulgata. Il pacchetto di prove contiene la risposta grezza ma non uno script autonomo che provi ogni indirizzo recuperato.

L'artefatto RCE mostra il contesto di sicurezza di www-data. Non dimostra l'accesso root, la compromissione di un ambiente di produzione né la completa portabilità verso distribuzioni PHP arbitrarie. La configurazione di laboratorio con un singolo worker è importante perché la sequenza delle richieste e l'affinità del worker influenzano il meccanismo.

4. Una correzione al ciclo di vita sottostante, non solo al sintomo

Il diff del codice sorgente fornito per il commit della patch PHP 01a40e89fbfc ("Avoid state corruption via bailout") mostra un'inizializzazione anticipata delle globali di sessione, modifiche alla gestione OOM dell'allocatore e una logica di reset/pulizia più ampia. Queste modifiche mirano a impedire che lo stato nativo sopravviva a una richiesta interrotta in uno stato non valido. Correggere solo il percorso di codifica dei cookie non ripristinerebbe, di per sé, questa garanzia di proprietà della memoria.

Il rapporto di ricerca afferma che i tentativi contro PHP 8.4.27 non hanno prodotto il cookie anomalo, il crash o la prova di RCE in quattro prove. Le trascrizioni effettive della versione con patch non sono presenti in questo pacchetto, quindi tale confronto è riportato come un'osservazione del ricercatore anziché come un reperto ispezionabile in modo indipendente.

5. Azioni difensive

• Immediato. Aggiorna la linea PHP supportata interessata alla release con correzioni di sicurezza e usa gli avvisi del fornitore per confermare lo stato esatto del pacchetto.

• Riduzione dell'esposizione. Valuta di limitare gli input multipart e disabilitare code>session.upload_progress/code> se non utilizzato; questi non sostituiscono la patch.

• Rilevamento. Esamina i crash durante l'inizializzazione delle richieste, gli errori 500 imprevisti e le intestazioni di risposta code>Set-Cookie/code> di dimensioni eccessive.

• Garanzia. Ripeti il test con pool di worker rappresentativi dell'ambiente di produzione e verifica che lo stato di sessione precedente non possa persistere tra le richieste.

6. Metodologia di ricerca OrcaCyber

Il prezioso compito di ricerca non consiste solo nell'individuare singole operazioni non sicure; consiste nel tracciare una violazione completa di un invariante attraverso l'analisi delle richieste, il comportamento dell'allocatore, le variabili globali native persistenti, la serializzazione e la chiusura. OrcaCyber Zero e OrcaCyber Ultra sono stati usati per creare il PoC in questa indagine, come attribuito dal team di ricerca. L'insieme di artefatti pubblici supporta la riproduzione tecnica, ma non fornisce tracce di esecuzione modello per modello né dimostra la scoperta autonoma di vulnerabilità.

Scala delle prove: ipotesi sulla sorgente → trigger raggiungibile → errore a runtime → divulgazione di informazioni → prova di esecuzione → regressione sulla versione corretta. Questa sequenza genera una fiducia maggiore rispetto a una descrizione della vulnerabilità o a un risultato basato solo su un crash. Incoraggia anche a segnalare chiaramente l'incertezza quando mancano i file sorgente o i log di esecuzione grezzi.

7. Ambito e limitazioni

Questa pubblicazione descrive un laboratorio Docker isolato e autorizzato. L'exploit si basa su una ricerca PHP2Shell pubblicata in precedenza, con adattamento locale documentato nel report fornito. Il pacchetto include script, diff, byte di risposta, log e output di prova, ma omette il checkout completo dell'exploit upstream, gli screenshot nativi e le trascrizioni grezze complete delle regressioni delle patch. Non viene rivendicato alcun compromesso reale di vittime o clienti.

Fonti e artefatti

Primario: fornito php2shell-report-bundle.tar.gz (REPORT.md; report-CVE-2026-109618.md; report-CVE-2026-109619.md; crash_evidence.log; leak_attempt.resp; rce_proof_8426.txt; diff del codice sorgente PHP). Contesto pubblico: avvisi di sicurezza PHP GHSA-w8hw-w9fx-j79w e GHSA-6wmf-4rv5-p3rp; annunci di rilascio di sicurezza PHP. Attribuzione pubblica dell'exploit: 9bie/php2shell-bypass-aslr-exp. Repository di ricerca: orcacyber-php2shell-research.

The public orcacyber-php2shell-research GitHub repository README on the OrcaCyber PHP2Shell defender research artifacts and its defensive scripts

In sintesi: una richiesta è fallita; un puntatore è sopravvissuto; la richiesta successiva si è fidata di esso. La parte difficile nel comprendere questa vulnerabilità è stabilire quella connessione con prove osservabili.

Confrontati in questo articolo1

Rilevato da questo articolo