Blog 24/7

PHP object injection

TAB. 1Hasłopo angielsku
Po angielskuPHP object injection
Którą formą pisaćpo angielsku Polski odpowiednik istnieje, ale w praktyce nikt tak nie pisze. Zostaw angielski, polski trzymaj jako synonim.
Inne formywstrzyknięcie obiektu PHP · niebezpieczna deserializacja obiektów PHP
KategoriaPodatności i klasy błędów

PHP object injection to podatność w aplikacjach PHP, w której dane kontrolowane przez atakującego trafiają do funkcji unserialize(). OWASP opisuje ją jako lukę na poziomie aplikacji, która pozwala przeprowadzić różne ataki, między innymi wstrzyknięcie kodu, SQL injection, path traversal i odmowę usługi (DoS) [1]. W katalogu CWE nazwa PHP Object Injection figuruje jako alternatywne określenie słabości CWE-502, czyli deserializacji niezaufanych danych (insecure deserialization) [2].

Jak działa

Funkcja serialize() zamienia wartość PHP, także obiekt, w ciąg znaków, a unserialize() odtwarza z niego wartość. Zapis obiektu zawiera nazwę klasy i wartości pól. Kto kontroluje ten ciąg, ten decyduje, obiekt jakiej klasy powstanie i jakie będzie miał pola. Dokumentacja PHP ostrzega, że odtworzenie danych może skończyć się załadowaniem i wykonaniem kodu przez utworzenie obiektu i automatyczne ładowanie klas [3].

Sam obiekt nic nie robi. Szkodę wyrządzają metody magiczne, które PHP wywołuje automatycznie: __wakeup() zaraz po odtworzeniu obiektu, __destruct() przy jego niszczeniu, __toString() przy zamianie na tekst [4]. OWASP wymienia dwa warunki udanego ataku [1]:

  1. aplikacja ma klasę z metodą magiczną, taką jak __wakeup albo __destruct, którą można wykorzystać do ataku;
  2. wszystkie klasy użyte w ataku są zadeklarowane w chwili wywołania podatnego unserialize().

Jeśli jedna metoda magiczna wywołuje metodę innego obiektu zapisanego w polu, atakujący może połączyć kilka klas w łańcuch. Taki łańcuch nazywa się POP (property-oriented programming), a jego ogniwa to gadżety [1]. Przebieg ataku pokazuje schemat poniżej.

RYS. 1Od danych do skutku

Skutki

Skutek zależy od tego, jakie klasy są dostępne w aplikacji, a nie od samego błędu. Już samo odtworzenie obiektu narusza integralność: MITRE ostrzega, że atakujący może zmienić obiekty lub dane, które aplikacja uważała za chronione przed zmianą [2]. MITRE zaznacza, że konsekwencje wykonania zależą od kontekstu i typów odtwarzanych obiektów [2].

SkutekPrzykładowy gadżetŹródło
zdalne wykonanie kodu (RCE)klasa wywołująca funkcję z pola obiektu[1]
usunięcie dowolnego plikudestruktor czyszczący pamięć podręczną[4]
SQL injectionmetoda budująca zapytanie z pól obiektu[1]
atak odmowy usługi (DoS)pętla zależna od danych[2]

W zestawieniu CWE Top 25 za 2025 rok słabość CWE-502 zajęła 15. miejsce [8].

W WordPressie

WordPress sam intensywnie używa serializacji: w tabelach opcji i metadanych zapisuje tablice i obiekty w postaci zserializowanej. Funkcja maybe_unserialize() odtwarza dane tylko wtedy, gdy wyglądają na zserializowane, i wywołuje przy tym zwykłe unserialize() [5]. Nie ogranicza przy tym dopuszczalnych klas [5]. Dopóki dane w bazie pochodzą od samej aplikacji, jest to bezpieczne. Problem powstaje, gdy wtyczka przekazuje do unserialize() albo maybe_unserialize() ciasteczko, parametr żądania czy pole formularza.

Rdzeń WordPressa zawiera wiele klas, które mogą posłużyć jako gadżety. W październiku 2023 roku WPScan opisał łańcuch prowadzący do zdalnego wykonania kodu, zbudowany wyłącznie z klas rdzenia, w tym WP_Theme z metodą __toString, WP_Block_List i klas biblioteki Requests [6]. Łańcuch wymagał osobnej luki, która pozwoli wstrzyknąć zserializowany obiekt, na przykład przez wstrzyknięcie SQL do pól metadanych [6]. Kolejne ogniwa korzystały z interfejsu ArrayAccess i z mechanizmu haków biblioteki Requests, który pozwalał wywołać dowolną funkcję zwrotną [6]. WordPress 6.3.2 zablokował odtwarzanie kilku klas z tego łańcucha albo ograniczył wartości ich pól [6]. Przykład pokazuje, że nawet aktualny rdzeń nie chroni strony, jeśli jedna z wtyczek odtwarza obiekty z niezaufanych danych: gadżety już w kodzie są, brakuje tylko punktu wejścia.

Jak się bronić

Najprostsza zasada brzmi: nie przekazywać do unserialize() danych od użytkownika. Dokumentacja PHP zaznacza, że dotyczy to także przypadku, gdy ustawiono opcję allowed_classes [3]. Jako format wymiany danych z użytkownikiem zaleca JSON, czyli json_decode() i json_encode() [3]. To samo zalecają OWASP [1] i Michał Bentkowski w artykule Sekuraka [4].

// dane od klienta: tylko JSON, bez obiektów PHP
$dane = json_decode( wp_unslash( $_POST['ustawienia'] ?? '' ), true );

// dane z własnego źródła: bez tworzenia obiektów
$lista = unserialize( $zapis, array( 'allowed_classes' => false ) );

Opcja allowed_classes ustawiona na false sprawia, że zamiast obiektu dowolnej klasy powstaje obiekt __PHP_Incomplete_Class [3]. Gdy zserializowane dane muszą przejść przez klienta, dokumentacja PHP zaleca sprawdzenie ich podpisem hash_hmac() [3]. MITRE również wymienia podpisywanie danych kodem HMAC i listy dozwolonych klas, zaznaczając, że sama lista nie wystarcza [2]. Wśród środków dodatkowych MITRE podaje zapory aplikacyjne [2], czyli WAF.

Po stronie właściciela strony najważniejsze są szybka łatka (patch) wtyczki i aktualizacja rdzenia WordPressa, bo poprawki rdzenia utrudniają budowanie łańcuchów z jego klas.

Historia i przykłady

W czerwcu 2014 roku Michał Bentkowski opisał tę klasę podatności na przykładzie Joomli i luki CVE-2013-1453 [4]. Łańcuch zaczynał się w destruktorze klasy wtyczki debugowania i kończył w metodzie czyszczącej pamięć podręczną, co pozwalało usuwać dowolne katalogi [4]. Punktem wejścia była wtyczka, która przyjmowała w parametrze GET zserializowany obiekt zakodowany w Base64 i przekazywała go do unserialize() bez sprawdzenia [4].

6 grudnia 2023 roku WordPress wydał wersję 6.4.2 z poprawką luki opisanej jako zdalne wykonanie kodu, której nie da się wykorzystać bezpośrednio w rdzeniu [7]. Zespół bezpieczeństwa ocenił, że w połączeniu z niektórymi wtyczkami, zwłaszcza w instalacjach Multisite, może mieć wysoką wagę [7].

TAB. 2

Przypisy

8
  1. [1] PHP Object Injection · OWASP
  2. [2] CWE-502: Deserialization of Untrusted Data · MITRE
  3. [3] unserialize — PHP Manual · The PHP Group
  4. [4] PHP Object Injection – mało znana, krytyczna klasa podatności · Sekurak
  5. [5] maybe_unserialize() — Code Reference · WordPress.org
  6. [6] Finding A RCE Gadget Chain In WordPress Core · WPScan
  7. [7] WordPress 6.4.2 Maintenance & Security Release · WordPress.org
  8. [8] 2025 CWE Top 25 Most Dangerous Software Weaknesses · MITRE
TAB. 3

Hasła w tym artykule

12
TAB. 4

Linkują tutaj

4

Wszystkie kategorie → · Hasło w słowniku →

Blog 24/7
05.11CISA i FBI wzywają do zabezpieczenia sterowników chłodzenia po atakach w Europietherecord.media05.11Midnight Blizzard atakowała iPhone'y i Androidy przez zainfekowane strony w Europie i USAsecurityweek.com05.11APT29 kradła dane z iPhone'ów i Androidów przez przejęte i podrobione stronytherecord.media05.11Grupa APT29 przejęła skrypt Plerdy i atakowała niezałatane iPhone'y i Androidythehackernews.com05.11Microsoft wykrył 7,3 mld wiadomości phishingowych w III kwartale 2026microsoft.com05.11DigiCert ujawnia wyciek danych klientów i skanów dokumentów tożsamościbleepingcomputer.com05.11CWPdoor podmienia serwer cwpsrv w Control Web Panel i otwiera tylne wejście do Linuksableepingcomputer.com05.11Brytyjskie NCSC ostrzega, że narzędzia AI zwiększyły liczbę wykrywanych luk zero-daythehackernews.com05.11Skaner RootEvidence sprawdza starą lukę w Cisco IOS i dodaje nagłówki Opt-Outisc.sans.edu05.11Włamanie do portalu grantowego Norad, zagrożone dane 20 614 użytkownikówhelpnetsecurity.com