Karta hero PHP2Shell: od nieudanego żądania do zdalnego wykonania kodu, CVE-2026-109618 i CVE-2026-109619
Engineering & Research

OrcaCyber Research - PHP2Shell: Jak nieudane żądanie stało się zdalnym wykonaniem kodu

Autor

Rowan Sterling

Data publikacji

Najnowsze modele · 20Zobacz wszystkie modele →
Benchmarki: Artificial Analysis · aktualizowane codziennie
Powrót do wszystkich wpisów

Dowód koncepcji w tym badaniu został utworzony przy użyciu OrcaCyber Zero i OrcaCyber Ultra modeli. Pakiet badawczy dokumentuje analizę na poziomie kodu źródłowego, kontrolowaną reprodukcję z wykorzystaniem zaadaptowanego publicznego exploita, artefakt ujawnienia pamięci, awarie procesów oraz dowody wykonania poleceń. Dostarczone pliki nie rejestrują niezależnie, które kroki zostały wykonane przez każdy model; przypisanie modeli podaje zespół badawczy.

Krytyczny stan braku pamięci powinien bezpiecznie zakończyć żądanie. Tutaj mógł przerwać działanie PHP, gdy stan natywny był tylko częściowo zainicjowany, pozostawiając odwołania, które przetrwały do następnego żądania. W rezultacie doszło do naruszenia czasu życia pamięci między żądaniami, którego skutki w testowanym środowisku obejmowały od ujawnienia informacji po zdalne wykonanie kodu.

Najważniejsze dowody w skrócie

• Cel — PHP 8.4.26, Apache/mod_php, pojedynczy worker, izolowane laboratorium Docker.

• Logi awarii — Jedno zakończenie procesu roboczego z SIGABRT i trzy zakończenia z SIGSEGV w dostarczonym fragmencie.

• odpowiedź HTTP — 819 200 bajtów w wartości PHPSESSID po zdekodowaniu URL.

• Dowód wykonania — code>uid=33(www-data) gid=33(www-data) groups=33(www-data)/code>.

• Regresja — Raport opisuje cztery nieudane próby na załatanej wersji PHP 8.4.27; surowe przebiegi nie są dołączone.

Źródło: przesłane pliki REPORT.md, crash_evidence.log, leak_attempt.resp i rce_proof_8426.txt. Opisane poniżej załączniki odtwarzają te artefakty jako złożone panele dowodowe; nie są to fotografie ani natywne zrzuty ekranu terminala.

1. Podatność: błąd własności na granicy żądania

Te dwie powiązane kwestie dotyczą przerwanej inicjalizacji żądania i nieaktualnych globalnych wskaźników środowiska wykonawczego. W odpowiedniej architekturze PHP obsługa multipart/form-data i wywołania zwrotne postępu przesyłania w sesji mogą być uruchamiane przed zwykłym kodem aplikacji użytkownika. Wyjątkowe przejście przepływu sterowania, w tym code>zend_bailout()/code>, może pominąć oczekiwane czyszczenie i pozostawić stan wskazujący na pamięć, która później zostanie zwolniona lub ponownie wykorzystana.

Niezmiennik bezpieczeństwa: referencja globalna dla workera udostępniona żądaniu B nigdy nie może wskazywać pamięci, której własność i czas życia zakończyły się wraz z żądaniem A. Zgłoszony błąd narusza ten niezmiennik.

Zademonstrowany punkt końcowy był minimalną stroną PHP, która po prostu zwracała OK; narracja exploitu nie opierała się na punktach końcowych podatnych na wstrzyknięcie SQL, dołączanie plików ani deserializację na poziomie aplikacji.

2. Sekwencja techniczna

• A1 — przerwanie. Obsługa przesyłania wieloczęściowego i postępu wysyłania powoduje OOM podczas czyszczenia, pozostawiając nieaktualny stan sesji.

• B1 — wyciek. Kolejne żądanie powoduje, że serializacja pliku cookie sesji odczytuje dane poza prawidłowym identyfikatorem sesji.

• Odzyskiwanie adresów. Ujawnione wartości wskaźników są wykorzystywane do wnioskowania o odpowiednim układzie bibliotek i sterty w tej kompilacji.

• A2/B2 — uszkodzenie. Kolejna sekwencja dwóch żądań kształtuje i przekierowuje nieaktualne dane używane podczas zamykania.

• Wynik. Dostosowany publiczny exploit zgłasza wykonanie polecenia jako www-data.

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

Dowody rzeczowe: co faktycznie pokazują dostarczone pliki

Dowód A — zakończenie procesu roboczego na podstawie logu Apache

• code>[core:notice] [pid 1:tid 1] AH00051: proces potomny o pid 54 zakończył się sygnałem Abort (6), możliwy zrzut rdzenia w /etc/apache2/code>

• code>[core:notice] [pid 1:tid 1] AH00051: proces potomny o pid 55 zakończył się sygnałem Segmentation fault (11), możliwy zrzut pamięci w /etc/apache2/code>

• code>[core:notice] [pid 1:tid 1] AH00051: pid 58 procesu potomnego zakończył się sygnałem Segmentation fault (11), możliwy coredump w /etc/apache2/code>

• code>[core:notice] [pid 1:tid 1] AH00051: proces potomny pid 61 zakończony sygnałem Segmentation fault (11), możliwy coredump w /etc/apache2/code>

Zestawiony fragment z crash_evidence.log (23 października 2026 r.). Wielokrotne zakończenia procesów roboczych wskazują na błąd bezpieczeństwa pamięci; same awarie nie dowodzą wystąpienia RCE.

• code>HTTP/1.1 200 OK/code>, z pominięciem danych binarnych.

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

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

• code>Set-Cookie: PHPSESSID=[pominięto dane binarne]/code>

• Długość zakodowanego pliku cookie: 2 330 754 bajty.

• Zdekodowana wartość URL: 819 200 bajtów.

Pomiar obliczony bezpośrednio z leak_attempt.resp. Wartość binarna została celowo pominięta, aby uniknąć odtworzenia jakiejkolwiek zawartości ujawnionego procesu.

Załącznik C — dowód wykonania

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

Dokładna zawartość pliku rce_proof_8426.txt, w dostarczonej postaci. Potwierdza ona zgłoszony wynik wykonania, ale nie jest pełnym zapisem poleceń/sesji.

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

Dowód D — poprawka cyklu życia sesji

• 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>* ponownie koduje sesję podczas uruchamiania żądania, przed RINIT, gdy nie ma użytkownika/code>

• code>/* Działa przed RINIT: nie wolno wywoływać kodu użytkownika, zobacz php_session_unserialize_init() *//code>

• code>/* Ten kod wykonuje się przed RINIT, więc musimy wyczyścić je wcześnie *//code>

• code>php_rinit_session_globals();/code>

Wybrane wiersze różnic źródłowych z pliku session.c.diff. Ta zmiana jawnie resetuje stan globalny sesji wcześniej niż zwykły RINIT.

3. Dlaczego dowody mają znaczenie

Ujawnienie pamięci stanowi pomost między awarią procesu a łańcuchem wykorzystania luki. Wartość sesji o nietypowym rozmiarze z osadzonymi danymi binarnymi jest spójna z tym, że środowisko wykonawcze interpretuje nieprawidłową pamięć jako ciąg Zend. Raport badawczy opisuje ponadto wyodrębnianie adresów kodu i sterty z ujawnionego okna. Pakiet dowodów zawiera surową odpowiedź, ale nie zawiera samodzielnego skryptu potwierdzającego każdy odzyskany adres.

Artefakt RCE pokazuje kontekst bezpieczeństwa www-data. Nie dowodzi uzyskania dostępu root, kompromitacji środowiska produkcyjnego ani pełnej przenośności do dowolnych wdrożeń PHP. Konfiguracja laboratoryjna z pojedynczym workerem jest istotna, ponieważ kolejność żądań i przypisanie do workera wpływają na ten mechanizm.

4. Poprawka w bazowym cyklu życia, a nie tylko objaw.

Dostarczony diff źródłowy dla commita poprawki PHP 01a40e89fbfc („Avoid state corruption via bailout”) pokazuje wczesną inicjalizację globalnych struktur sesji, zmiany w obsłudze OOM alokatora oraz szerszą logikę resetowania/czyszczenia. Zmiany te mają na celu zapobieżenie temu, by stan natywny przetrwał przerwane żądanie w nieprawidłowym stanie. Sama naprawa ścieżki kodowania plików cookie nie przywróciłaby tej gwarancji własności pamięci.

Raport z badań stwierdza, że cztery próby przeprowadzone przeciwko PHP 8.4.27 nie doprowadziły do uzyskania nieprawidłowego pliku cookie, awarii ani dowodu RCE. Rzeczywiste transkrypty wersji z poprawkami nie znajdują się w tym pakiecie, dlatego porównanie to przedstawiono jako obserwację badacza, a nie jako niezależnie weryfikowalny materiał dowodowy.

5. Działania defensywne

• Natychmiast. Zaktualizuj obsługiwaną linię PHP, której to dotyczy, do wydania z poprawkami bezpieczeństwa i skorzystaj z komunikatów dostawcy, aby potwierdzić dokładny stan pakietu.

• Ograniczenie ekspozycji. Rozważ ograniczenie danych wejściowych typu multipart i wyłączenie code>session.upload_progress/code>, jeśli nie są używane; nie zastępują one poprawki.

• Wykrywanie. Przejrzyj awarie podczas inicjalizacji żądania, nieoczekiwane błędy 500 i zbyt duże code>Set-Cookie/code> nagłówki odpowiedzi.

• Zapewnienie. Przetestuj ponownie przy użyciu pul workerów reprezentatywnych dla produkcji i potwierdź, że stary stan sesji nie może utrzymywać się między żądaniami.

6. Metodologia badań OrcaCyber

Cennym zadaniem badawczym nie jest wyłącznie wskazywanie pojedynczych niebezpiecznych operacji; polega ono na prześledzeniu pełnego naruszenia niezmiennika w obrębie parsowania żądań, działania alokatora, trwałych natywnych zmiennych globalnych, serializacji i zamykania. OrcaCyber Zero i OrcaCyber Ultra zostały użyte do utworzenia PoC w tym badaniu, zgodnie z atrybucją dokonaną przez zespół badawczy. Publiczny zestaw artefaktów wspiera techniczną reprodukcję, ale nie dostarcza śladów wykonania dla poszczególnych modeli ani nie dowodzi autonomicznego wykrywania podatności.

Drabina dowodów: hipoteza źródłowa → osiągalny wyzwalacz → awaria w czasie wykonania → ujawnienie informacji → dowód wykonania → regresja w wersji poprawionej. Taka sekwencja daje silniejszą pewność niż opis podatności lub wynik oparty wyłącznie na awarii. Zachęca też do jasnego raportowania niepewności, gdy brakuje plików źródłowych lub surowych dzienników wykonania.

7. Zakres i ograniczenia

Ta publikacja opisuje autoryzowane, izolowane laboratorium Docker. Eksploit opiera się na wcześniej opublikowanych badaniach PHP2Shell, a lokalna adaptacja została udokumentowana w dostarczonym raporcie. Pakiet zawiera skrypty, diffy, bajty odpowiedzi, logi i dane wyjściowe dowodu, ale pomija pełny checkout upstreamowego eksploita, natywne zrzuty ekranu oraz kompletne surowe zapisy testów regresji poprawek. Nie twierdzi się, że doszło do kompromitacji rzeczywistej ofiary lub klienta.

Źródła i artefakty

Źródło podstawowe: dostarczono 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; różnice w kodzie źródłowym PHP). Kontekst publiczny: biuletyny bezpieczeństwa PHP GHSA-w8hw-w9fx-j79w oraz GHSA-6wmf-4rv5-p3rp; ogłoszenia o wydaniach bezpieczeństwa PHP. Publiczne przypisanie exploita: 9bie/php2shell-bypass-aslr-exp. Repozytorium badawcze: orcacyber-php2shell-research.

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

Wniosek: jedno żądanie nie powiodło się; wskaźnik przetrwał; kolejne żądanie mu zaufało. Najtrudniejsze w zrozumieniu tej podatności jest ustalenie tego związku na podstawie obserwowalnych dowodów.

Porównane w tym artykule1

Wykryto na podstawie tego artykułu