Ostatnie dwa tygodnie były dla mnie dość pracowite, tak więc tylko kątem oka przyglądałem się temu, co działo się wokół krytycznej luki bezpieczeństwa w WordPressie 4.7 i 4.7.1. Zawierająca poprawkę błędu wersja 4.7.2 została wydana 26 stycznia, o czym wspomniałem na Facebooku i uznałem temat za zamknięty. Nie znalazłem niestety czasu na dokładniejsze opisanie tej podatności, a szkoda, bo luka jest nie tylko bardzo poważna, ale również nietypowa, a wykorzystujące ją zmasowane ataki, które rozpoczęły się na początku lutego, trwają do dzisiaj.
Zgłębiając temat doszedłem do kilku wniosków, którymi chciałbym się z wami podzielić.
Co to w ogóle za luka i dlaczego jest taka groźna?
WordPress 4.7.2 zawierał poprawki czterech błędów związanych z bezpieczeństwem. Najpoważniejszym z nich był błąd związany z uprawnieniami w REST API.
REST API to interfejs, nad którym twórcy WordPressa pracowali od dawna i który nazywany jest często „przyszłością WordPressa” (z czym jako wielki fan tego rozwiązania muszę się zgodzić). „Infrastrukturę” dla REST API, czyli możliwość tworzenia własnych interfejsów, wprowadzono już w wersji 4.4, ale dopiero wersja 4.7 przyniosła gotowe interfejsy dla wszystkich danych. Oznacza to, że za pośrednictwem REST API można teraz odczytywać i (co ważne) zapisywać wszystkie informacje dostępne w panelu administracyjnym.
Oczywiście do modyfikacji danych potrzebujemy odpowiednich uprawnień (nie każdy użytkownik może to przecież robić). Odkryty błąd pozwalał na modyfikację treści wpisów bez konieczności autoryzacji – czyli mógł to zrobić każdy. Na dodatek z technicznego punktu widzenia wykorzystanie tej luki jest trywialne, w związku z czym niedługo po podaniu informacji na temat błędu do publicznej wiadomości dostępne już były gotowe narzędzia do atakowania stron opartych na dziurawych wersjach WordPressa (4.7 i 4.7.1), a pierwsze poważne ataki rozpoczęły się w mniej niż 48 godzin po publikacji.
Nietypowość tego ataku polega na tym, że w jego efekcie nie są modyfikowane żadne pliki, a większość skanerów wykrywa infekcje na podstawie zmian w plikach. Dodatkowo atak ten jest możliwy do przeprowadzenia nawet w serwisach, w których całkowicie uniemożliwiono modyfikację plików.
Rodzaje i skala ataku
Skala ataków wykorzystujących opisaną wyżej lukę nie jest wbrew pozorom jakaś gigantyczna. W większości przypadków zadziałał wbudowany w WordPressa mechanizm automatycznych aktualizacji, który samoczynnie (bez konieczności interakcji ze strony administratora) instaluje kolejne uaktualnienia w ramach wersji głównej (czyli na przykład z 4.7.1 do 4.7.2). Dlaczego ten mechanizm nie zadziałał wszędzie? O tym za chwilę.
Jeśli natomiast chodzi o rodzaje ataków, to (jak wynika z tego opracowania) większość z nich ma na celu po prostu zniszczenie atakowanej strony przez podmienienie jej oryginalnej treści. Problem w tym, że prawdopobnie już trwają bardziej dyskretne ataki, których celem może być na przykład wstrzykiwanie do treści atakowanych stron linków pozycjonujących – tego typu „infekcje” potrafią pozostać niezauważone przez całe miesiące, przynosząc atakującym wymierne korzyści materialne (a nie tylko dziwnie pojmowany rozgłos).
Warto też dodać, że część atakujących próbuje wykorzystać wtyczki Insert PHP lub Exec-PHP, które pozwalają na wykonywanie wstawionego do treści wpisów kodu PHP, co daje atakującemu ogromne wręcz możliwości.
Co z mechanizmem automatycznych aktualizacji?
Wspomniany wcześniej mechanizm automatycznych aktualizacji z całą pewnością zminimalizował skalę ataków. Pojawia się jednak pytanie, co ze stronami, na których on nie zadziałał? Mówimy w końcu o dziesiątkach tysięcy zainfekowanych serwisów!
W większości przypadków winni są właściciele tych stron. Sam widziałem wiele serwisów, których administratorzy celowo wyłączali automatyczne aktualizacje z obawy, że „coś się może popsuć”. O ile takie działanie można jeszcze wytłumaczyć niewiedzą, o tyle wyłączanie automatycznych aktualizacji przez osoby tworzące strony dla klientów jest po prostu niedopuszczalne (a z takimi przypadkami również się spotkałem).
Oczywiście istnieją też na pewno przypadki, w których mechanizm aktualizacji nie zadziałał z przyczyn technicznych, takich jak konfiguracja serwera czy problem z uprawnieniami. Wciąż jednak wina leży po stronie właścicieli stron, do których wysyłane są wiadomości o problemach z wykonaniem uaktualnienia.
Odchodząc na chwilę od tematu wpisu: regularnie na różnych grupach czy forach czytam wypowiedzi ludzi, którzy nie aktualizują WordPressa i wtyczek, bo się boją, że „coś zepsują”. Naprawdę nie rozumiem, dlaczego takie osoby nie wykonają kopii bezpieczeństwa i nie spróbują po prostu kliknąć przycisku „Aktualizuj” – w razie niepowodzenia w ciągu kilkunastu minut można przywrócić stronę do stanu sprzed nieudanej aktualizacji. A jeśli tak bardzo się boją, to dlaczego nie poproszą o pomoc kogoś, kto nie będzie bał się dbać o bezpieczeństwo ich strony?
Ze stroną internetową jest trochę jak z samochodem. Trzeba go regularnie serwisować, bo jeśli nie będziemy tego robić, to prędzej czy później odmówi posłuszeństwa. A jeśli nie potrafimy sami zadbać o swój samochód, to przekazujemy go raz na jakiś czas w ręce fachowca, który dokona przeglądu i zrobi co trzeba.
Dla WordPressa to wizerunkowa klapa
WordPress nigdy nie miał dobrej opinii wśród programistów. Od zawsze wytykano mu kiepsko napisany, przestarzały kod, złe podejście do tworzenia nowych lub przepisywania istniejących kawałków kodu czy kulawy proces rozwoju. I ten błąd tylko umocni wszystkie krytyczne głosy.
Bo tak naprawdę winni tej sytuacji są tylko i wyłącznie osoby pracujące nad rozwojem WordPressa. Nie ludzie, którzy nie aktualizują swoich stron, ale osoby, które napisały wadliwy kod i osoby, które udawały, że go testują. Prace nad REST API rozpoczęły się na początku 2013 roku – czy naprawdę przez cztery lata nie można było zrobić tego dobrze?
Dużym błędem było domyślne włączenie interfejsu REST API. To funkcja, której tak naprawdę potrzebuje niewielki procent użytkowników WordPressa, tak więc zdecydowanie powinna być ona domyślnie wyłączona. Aby samodzielnie wyłączyć REST API trzeba zainstalować dodatkową wtyczkę lub skorzystać z kawałka gotowego kodu – nie tak to powinno wyglądać. Oczywiście gdyby domyślnie funkcja ta była nieaktywna, to opisywanego tutaj problemu prawdopodobnie w ogóle by nie było.
Dla jasności dodam, że nie uważam tego typu błędów za powód do zmiany CMSa, bo oprogramowanie bez błędów nie istnieje, a u konkurencji wcale nie jest lepiej. Uważam jednak, że w tym konkretnym przypadku problemu dało się uniknąć i osobom pracującym bezpośrednio przy rozwoju WordPressa należy się za to żółta kartka.