Spis treści 7 sekcji
- 22 września 2026 WordPress wydał wersję 7.1.2 z jedną poprawką: krytyczną lukę CVE-2026-87902 (CVSS 9.2). Atakujący bez konta może zmusić WordPressa do wczytania wybranego pliku PHP z serwera.
- Podatne są wszystkie wersje od 4.7.0 do 7.1.1, czyli prawie dziewięć lat wydań. Łatki dostało 25 gałęzi, od 7.1.2 w dół do 4.7.37.
- Pełne przejęcie serwera wymaga spełnienia kilku warunków, między innymi włączonego w PHP
register_argc_argv. Pierwsze próby ataku Patchstack zauważył niecałe 5 godzin po publikacji łatki. - To druga krytyczna luka w rdzeniu WordPressa w ciągu dwóch miesięcy, po wp2shell z lipca. Tamta dotyczyła mniejszej liczby wersji, ale działała na domyślnej instalacji.
- Automatyczna aktualizacja w tle obejmuje 7.1.2, ale nie zadziała na witrynach wdrażanych z repozytorium git. Wersję trzeba sprawdzić na każdej witrynie.
22 września 2026 WordPress wydał wersję 7.1.2, która naprawia jedną lukę, ale od razu z oceną krytyczną. Zespół bezpieczeństwa zaleca natychmiastową aktualizację wszystkich witryn. Pięć dni wcześniej, 17 września, wyszła wersja 7.1.1 z jedenastoma innymi poprawkami bezpieczeństwa, więc kto zaktualizował w zeszłym tygodniu, i tak musi zrobić to jeszcze raz.
W lipcu pisałem o wp2shell, luce, która pozwalała przejąć WordPressa bez logowania. Nowa luka jest z tej samej kategorii: dotyczy samego rdzenia WordPressa i nie wymaga konta. Różni się zasięgiem i warunkami, co omawiam niżej, bo od tego zależy, jak pilnie trzeba działać na konkretnej witrynie.
Co naprawia WordPress 7.1.2
Błąd siedzi w mechanizmie, który wybiera szablon strony. Według notatki do wydania atakujący bez uwierzytelnienia może w określonych warunkach sprawić, że WordPress dołączy wskazany przez niego plik PHP spoza katalogów aktywnego motywu. To klasyczne przejście po katalogach (path traversal) zakończone dołączeniem lokalnego pliku. Poprawka zmienia jeden plik rdzenia: wp-includes/template.php. Lukę zgłosił Robert Ressl.
Samo wczytanie pliku nie oznacza jeszcze przejęcia serwera. Żeby to się udało, na serwerze musi leżeć plik PHP, który po wczytaniu zrobi coś przydatnego dla atakującego. Według analizy Patchstack droga do wykonania kodu prowadzi przez trzy warunki naraz:
- PHP obsługujący stronę ma włączone
register_argc_argv, - aktywny motyw ma w głównym katalogu folder o nazwie zaczynającej się od
page-, - na serwerze jest plik, który po dołączeniu wykonuje polecenia. Patchstack wskazuje tu
pearcmd.phpz pakietu PEAR.
WordPress wycenił lukę na 9.2 w skali CVSS, jak podaje The Hacker News. Na 22 września nie było publicznego kodu ataku ani wpisu w katalogu aktywnie wykorzystywanych luk CISA KEV. Mimo to Patchstack zablokował pierwsze próby już o 17:44 UTC tego samego dnia, niecałe pięć godzin po publikacji łatki. Atakujący odczytują zmiany w łatce i sprawdzają, które witryny jeszcze ich nie mają. Na razie to rekonesans, który wczytuje nieszkodliwe pliki rdzenia, żeby potwierdzić podatność.
Porównanie z luką wp2shell z lipca
| wp2shell (lipiec) | CVE-2026-87902 (wrzesień) | |
|---|---|---|
| Numer CVE | CVE-2026-63030 | CVE-2026-87902 |
| Ocena CVSS | 7.5 | 9.2 |
| Miejsce błędu | REST API, endpoint batch | wybór szablonu strony |
| Wymaga konta | nie | nie |
| Podatne wersje | 6.9.0-6.9.4 i 7.0.0-7.0.1 | 4.7.0-7.1.1 |
| Warunki przejęcia | brak trwałego object cache, czyli domyślna instalacja | register_argc_argv, folder page- w motywie, użyteczny plik PHP |
| Łatka | 7.0.2 i 6.9.5, 17 lipca | 7.1.2 i 24 starsze gałęzie, 22 września |
Obie luki są porównywalne w tym, co najważniejsze: dotyczą rdzenia i nie wymagają logowania. Różnią się dwiema rzeczami. Wrześniowa obejmuje wielokrotnie więcej instalacji, bo sięga wersji z grudnia 2016 roku. Za to pełne przejęcie serwera jest trudniejsze niż przy wp2shell, bo wymaga konkretnej konfiguracji PHP i motywu.
Które wersje są podatne i gdzie jest łatka
Oficjalnie WordPress wspiera tylko najnowszą wersję, ale przy tej luce wydał poprawki dla wszystkich gałęzi od 4.7. Jeśli Twoja witryna stoi na starszej gałęzi, nie musisz od razu skakać do 7.1. Wystarczy wersja poprawkowa z tej samej linii:
| Gałąź | Bezpieczna wersja | Gałąź | Bezpieczna wersja |
|---|---|---|---|
| 7.1 | 7.1.2 | 5.8 | 5.8.17 |
| 7.0 | 7.0.6 | 5.7 | 5.7.19 |
| 6.9 | 6.9.9 | 5.6 | 5.6.21 |
| 6.8 | 6.8.10 | 5.5 | 5.5.22 |
| 6.7 | 6.7.9 | 5.4 | 5.4.23 |
| 6.6 | 6.6.9 | 5.3 | 5.3.25 |
| 6.5 | 6.5.12 | 5.2 | 5.2.28 |
| 6.4 | 6.4.12 | 5.1 | 5.1.26 |
| 6.3 | 6.3.12 | 5.0 | 5.0.29 |
| 6.2 | 6.2.13 | 4.9 | 4.9.33 |
| 6.1 | 6.1.14 | 4.8 | 4.8.32 |
| 6.0 | 6.0.16 | 4.7 | 4.7.37 |
| 5.9 | 5.9.18 |
Czy WordPress zaktualizuje się sam
W większości przypadków tak. W ogłoszeniu wydania WordPress pisze, że witryny obsługujące automatyczne aktualizacje w tle zaczną proces same. Według dokumentacji aktualizacje poboczne, takie jak 7.1.1 do 7.1.2, są automatyczne domyślnie od WordPressa 3.7. Od wersji 5.6 nowe instalacje aktualizują się automatycznie także do wydań głównych.
Przy wp2shell WordPress.org dodatkowo wymuszał aktualizację podatnych instalacji. Tym razem ogłoszenie o niczym takim nie wspomina, więc zostaje zwykły mechanizm, który na serwerach zarządzanych samodzielnie potrafi po cichu nie zadziałać. Typowe przyczyny, takie jak uprawnienia do plików, stała DISALLOW_FILE_MODS, metoda zapisu przez FTP, pełny dysk czy zablokowany ruch wychodzący, opisałem w artykule o wp2shell. Wszystkie nadal obowiązują.
Tym razem dochodzi częsty przypadek: wdrożenie z repozytorium. WordPress wyłącza automatyczne aktualizacje, gdy wykryje w instalacji katalog systemu kontroli wersji, na przykład .git, .svn albo .hg. Jeśli wdrażasz WordPressa przez git albo pipeline CI/CD, rdzeń nie zaktualizuje się sam. Musisz podbić wersję w repozytorium i wdrożyć ją jak każdą inną zmianę. Automatyczne aktualizacje wyłączają też stałe AUTOMATIC_UPDATER_DISABLED oraz WP_AUTO_UPDATE_CORE ustawiona na false w wp-config.php.
Stan faktyczny najszybciej sprawdzisz przez WP-CLI na serwerze:
# aktualna wersja rdzenia
wp core version
# aktualizacja do najnowszej wersji poprawkowej w tej samej gałęzi
wp core update --minor
# porównanie plików rdzenia z sumami kontrolnymi WordPress.org
wp core verify-checksums
Przy wielu serwerach nie musisz logować się na każdy. To samo polecenie uruchomisz zdalnie narzędziem, którym już zarządzasz maszynami, na przykład Ansible albo AWS Systems Manager.
Co zrobić, jeśli nie możesz zaktualizować od razu
Aktualizacja zmienia jeden plik rdzenia, więc ryzyko, że coś się zepsuje, jest małe. Jeśli jednak witryna czeka na okno serwisowe albo na testy u klienta, możesz doraźnie zmniejszyć ryzyko na dwa sposoby. Oba to zabezpieczenie na kilka dni, do czasu aktualizacji.
Reguła w zaporze WAF
Patchstack wskazuje, że skutecznie działa odrzucanie sekwencji przejścia po katalogach w parametrze pagename. Atak używa podwójnie zakodowanych kropek, dlatego reguła najpierw dwa razy dekoduje wartość, a potem szuka w niej dwóch kropek z rzędu. Żaden prawidłowy adres strony w WordPressie ich nie zawiera. Taką regułę ustawisz w każdym WAF-ie, który pozwala zdekodować parametr przed porównaniem. Poniżej przykład dla AWS WAF, który sprawdziłem pod kątem składni w API: jest poprawny i zajmuje 56 jednostek pojemności (WCU).
{
"Name": "blokuj-pagename-traversal",
"Priority": 0,
"Statement": {
"OrStatement": {
"Statements": [
{
"RegexMatchStatement": {
"FieldToMatch": { "SingleQueryArgument": { "Name": "pagename" } },
"RegexString": "\\.\\.",
"TextTransformations": [
{ "Priority": 0, "Type": "URL_DECODE" },
{ "Priority": 1, "Type": "URL_DECODE" }
]
}
},
{
"RegexMatchStatement": {
"FieldToMatch": { "Body": { "OversizeHandling": "CONTINUE" } },
"RegexString": "(^|&)pagename=[^&]*\\.\\.",
"TextTransformations": [
{ "Priority": 0, "Type": "URL_DECODE" },
{ "Priority": 1, "Type": "URL_DECODE" }
]
}
}
]
}
},
"Action": { "Block": {} },
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "blokujPagenameTraversal"
}
}
Drugi warunek sprawdza treść żądań POST, bo Patchstack widział próby obiema metodami. Zanim ustawisz akcję na blokowanie, puść regułę dzień w trybie Count i zobacz w próbkach żądań, co łapie. W AWS taką regułę podepniesz pod CloudFront albo Application Load Balancer, ale nie bezpośrednio pod instancję EC2 czy Lightsail. Witryna, przed którą nie stoi żaden WAF, ma jedną ochronę: aktualizację.
Wyłączenie register_argc_argv
Domyślnie PHP ma tę opcję włączoną, a plik php.ini-production ją wyłącza. Od PHP 8.5 opcja jest przestarzała i dokumentacja PHP zaleca ustawienie register_argc_argv=0 dla serwerów WWW. WordPress jej nie potrzebuje, więc możesz ją wyłączyć w konfiguracji PHP-FPM albo Apache i zrestartować usługę.
Uwaga na pułapkę przy sprawdzaniu. php -i uruchomione w terminalu zawsze pokaże tę opcję jako włączoną, bo PHP w wierszu poleceń wymusza ją niezależnie od konfiguracji. Sprawdzaj wartość dla PHP, który obsługuje stronę, na przykład przez php-fpm -i.
Przegląd logów
Próby ataku widać w logach dostępu serwera WWW po parametrze pagename z podwójnie zakodowaną kropką %252e. Na serwerze wystarczy grep. Jeśli zbierasz logi centralnie, na przykład w CloudWatch, to samo zrobisz zapytaniem:
# na serwerze (dopasuj ścieżkę do logów Apache albo Nginx)
grep -iE "pagename=[^& ]*%252e" /var/log/apache2/access.log
# CloudWatch Logs Insights
fields @timestamp, @message
| filter @message like /pagename=[^& ]*%252[eE]/
| sort @timestamp desc
Pojedyncze trafienia po 22 września to najpewniej automatyczne skanowanie całego internetu, a nie atak wymierzony w Ciebie. Jeśli jednak witryna nie była wtedy załatana, a warunki z pierwszej sekcji są spełnione, uruchom wp core verify-checksums i przejrzyj pliki zmienione w ostatnich dniach.
Plan na dziś
- Zrób spis. Znajdź wszystkie swoje WordPressy: na hostingu, na własnych serwerach i w kontenerach. Najłatwiej przeoczyć starą witrynę, która od lat stoi bez opieki.
- Sprawdź wersje.
wp core versionna każdej witrynie. Porównaj wynik z tabelą bezpiecznych wersji. - Zaktualizuj.
wp core update --minorna serwerze, a przy wdrożeniach z repozytorium podbij wersję w kodzie i wdróż. - Załóż zabezpieczenia doraźne tam, gdzie aktualizacja musi poczekać: regułę w WAF i wyłączone
register_argc_argv. - Przejrzyj logi od 22 września i sprawdź sumy kontrolne rdzenia na witrynach, które były wtedy podatne.
Druga krytyczna luka w rdzeniu w ciągu dwóch miesięcy to dobry moment, żeby przestać traktować aktualizacje WordPressa jako coś, co dzieje się samo. Jeśli planujesz przenieść WordPressa z hostingu na własny serwer w chmurze, zacznij od poradnika migracji.
Co to oznacza w praktyce
Które wersje WordPressa są podatne na CVE-2026-87902?
Czy WordPress sam zainstaluje wersję 7.1.2?
.git, .svn albo .hg, gdy aktualizacje wyłączają stałe w wp-config.php albo gdy serwer nie ma prawa zapisu do plików rdzenia.Mam WordPressa 6.8, czy muszę przechodzić na 7.1?
wp core update --minor. Pamiętaj jednak, że oficjalnie wspierana jest tylko najnowsza wersja, a poprawki dla starszych gałęzi to gest dobrej woli.Czy CVE-2026-87902 jest już wykorzystywana w atakach?
Czym ta luka różni się od wp2shell?
register_argc_argv, odpowiedniego motywu i użytecznego pliku PHP na serwerze. Obie nie wymagają logowania.Czy WAF zablokuje ataki na tę lukę?
pagename. Przykład dla AWS WAF jest wyżej. Reguła działa tylko wtedy, gdy ruch do witryny przechodzi przez WAF, i jest zabezpieczeniem doraźnym, które nie zastępuje aktualizacji.
