Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book

Krytyczna podatność we wtyczce Litespeed Cache – łatajcie swoje WordPressy

22 sierpnia 2024, 16:03 | W biegu | komentarzy 9

Krytyczna podatność w wordpressowej wtyczce Litespeed Cache (podatne są wersje do 6.3.0.1 włącznie), oznaczona jako CVE-2024-28000, została właśnie załatana. Według statystyk dodatek ten jest używany przez przeszło 5 milionów stron (z czego zaktualizowanych do tej pory zostało na razie około połowy). 

Podatność została opisana jako podniesienie uprawnień, ponieważ pozwala nieuwierzytelnionemu użytkownikowi uzyskać prawa administratora na odwiedzanej witrynie. Od tego momentu droga do zdalnego wykonania kodu (RCE), zwykle bywa krótka. 

Autor znaleziska został wynagrodzony kwotą 14.400 USD za zgłoszenie luki w programie BugBounty. 

W serwisie patchstack.com pojawił się bardziej szczegółowy opis podatności. Za możliwość eskalacji uprawnień odpowiada wbudowany we wtyczkę mechanizm crawlera, który ma za zadanie symulować zalogowanych użytkowników. W celu realizacji tego zadania, wtyczka dokonuje sprawdzenia dwóch ciasteczek: litespeed_role i litespeed_hash. Po pozytywnej weryfikacji hasha, ID użytkownika jest zmieniane z wykorzystaniem funkcji wp_set_current_user

Bezpieczeństwo funkcjonalności zależy więc od hasha, a właściwie tokenu, który chroni dostępu do zasobów, pozwalając jedynie crawlerowi odwiedzić podstrony w kontekście innego użytkownika. 

Jak można się domyślić, to właśnie w tym miejscu zlokalizowane są problemy, prowadzące w efekcie do możliwości wykonania ataku:

Listing 1. Fragment klasy src/str.clos.php() – implementacja funkcji rrand() (źródło)

<?php
public static function rrand($len, $type = 7)
{
    mt_srand((int) ((float) microtime() * 1000000));

    switch ($type) {
        case 0:
            $charlist = '012';
            break;
        case 1:
            $charlist = '0123456789';
            break;
        case 2:
            $charlist = 'abcdefghijklmnopqrstuvwxyz';
            break;
        case 3:
            $charlist = '0123456789abcdefghijklmnopqrstuvwxyz';
            break;
        case 4:
            $charlist = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            break;
        case 5:
            $charlist = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            break;
        case 6:
            $charlist = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
            break;
        case 7:
            $charlist = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
            break;
    }

    $str = '';

    $max = strlen($charlist) - 1;
    for ($i = 0; $i < $len; $i++) {
        $str .= $charlist[mt_rand(0, $max)];
    }

    return $str;
}
?>

Wnikliwy Czytelnik zauważy, że generator jest zasilany ziarnem zależnym od czasu (funkcja microtime()). To znacząco obniża zakres możliwych wartości startowych do miliona. 

Samo generowanie liczb jest realizowane przez dobrze znany, szybki generator Mersenne Twister. Jak wskazuje dokumentacja, nie jest to rozwiązanie kryptograficznie bezpieczne.

Obrazek 1. Ostrzeżenie w dokumentacji funkcji mt_rand()

Oprócz tego, wartość wygenerowana przez kod z listingu 1, jest generowana raz – następnie trafia do bazy danych, następnie nigdy się nie zmienia. Próżno też szukać dodatkowych mechanizmów bezpieczeństwa jak np. solenie. Wartość hasha jest więc niezależna od środowiska.

Jak można się domyślić, to znacząco zmniejsza przestrzeń poszukiwania, do miliona wartości. Nie wygląda to dobrze zarówno z punktu widzenia entropii, jak i późniejszego procesu sprawdzenia hasha, który odbywa się bez pomocy funkcji porównujących o stałym czasie wykonania (może czytelniejsze jest angielskie określenie: constant-time comparison). 

Luka nie byłaby aż tak poważna, gdyby nie jeden fakt. Okazuje się, że crawler nie jest domyślnie skonfigurowany. Informacja o tym, czy może on działać wynika wprost z obecności wyżej określonego hasha w bazie danych. Jeśli go nie ma, to atak się nie powiedzie…. No chyba, że atakujący jest sobie w stanie ten hash wygenerować i umieścić w bazie danych… Badacz odnalazł taką ścieżkę:

A call to /wp-admin/admin-ajax.php?action=async_litespeed&litespeed_type=crawler by any unauthenticated user will call this method with the routing parameter that’s needed to ultimately trigger a call to Router::get_hash and generate the security hash.

Co ciekawe, podatne są tylko instalacje na systemach Linux, ponieważ w wyniku najpewniej niedopatrzenia, jedna z funkcji wywoływanych na etapie generowania hasha jest niedostępna w systemie Microsoftu. 

Na podstawie przeprowadzonych testów udowodniono, że atakujący jest w stanie dokonać pełnego sprawdzenia całego zakresu, generując niewiele ruchu – bo tylko 3 zapytania HTTP na sekundę. Atak w najgorszym razie skończy się sukcesem po tygodniu. 

Pozostaje jedynie odgadnięcie ID docelowego użytkownika (w tym przypadku administratora) i jest to zależne od konkretnego, podatnego portalu. Okazuje się jednak, że często użytkownik o ID wynoszącym 1 jest tym, czego szuka atakujący. 

Na domiar złego, jeśli logi we wtyczce Litespeed Cache są włączone (ustawienie Debug Log), to poszukiwany (poprawny, ten z bazy danych) hash zostanie również umieszczony w pliku debug.log w katalogu /wp-content/, dla każdego zapytania z przesłanym niepoprawnym hashem. 

Autorzy wtyczki zareagowali sprawnie implementując wymagane mitygacje takie jak zmiana sposobu walidacji hasha, skrócenie czasu życia hasha do 120 sekund. Zwiększona została też entropia samego hasha/tokenu. Ze szczegółami łaty można zapoznać się tutaj

WordPress to bardzo dojrzały CMS, którego bezpieczeństwo z biegiem czasu się bardzo poprawiło. Wciąż jednak należy mieć świadomość, że luki związane z samym silnikiem jak i wtyczkami będą się pojawiać, dlatego tak ważne jest, aby świadomie zarządzać swoimi instancjami i dbać o regularne aktualizacje. 

~fc

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

  1. Ddd

    Tak bywa, jak się zatrudnia programistów spod biedronki

    Odpowiedz
    • Maciek Palmowski

      Błędy się zdarzają. Akurat ekipa odpowiedzialna na Litespeed Cache zachowała się bardzo profesjonalnie gdy tylko dostali od nas info. Jasne – dziura poważna, tutaj nie ma usprawiedliwienia, ale załatana od ręki, bez ukrywania faktu że ta dziura była.

      Uwierz mi – tych spod biedronki rozpoznaje się po tym jak reagują na info o podatności. Mamy tu duże doświadczenie w kontakcie z różnymi devami. Nie zawsze jest tak różowo.

      Odpowiedz
  2. Imię
    Odpowiedz
  3. Imię
    Odpowiedz
  4. Maciek

    Dzięki za opublikowanie naszego artykułu 💪

    Odpowiedz
  5. ajajAI

    Ostatni akapit wygląda jak żywcem wyjęty z GPT :D Nawet narzędzia do sprawdzania pochodzenia tekstu określiły go jako pochodzący z jakiegoś AI z wynikiem 100% :D

    Odpowiedz
    • fc

      W odróżnieniu od niektórych portali piszących o bezpieczeństwie, nie korzystamy z GPT. Mam poważne uwagi co do metodologii i skuteczności działania narzędzi do wykrywania generowanych przez duże modele językowe tekstów. To jeden z powodów witchhuntów na uniwersytetach np. w USA. Bo o ile zagrożenie jest prawdziwe i powstało dużo publikacji tekstów wygenerowanych przez LLMy, o tyle nie ma obecnie skutecznej metody na wykrywanie tego.

      A że wyszedł generyczny truizm… Cóż, najważniejsze, że prawdziwy. W następnym artykule postaram się bardziej w ostatnim akapicie.

      Odpowiedz
    • gicher

      Przez jaki model to puszczałeś? Ja dałem przez gpt0 i dostałęm, że na 95% człowiek to napisał.

      Odpowiedz
  6. Maria

    Czy mod security by sobie z tym atakiem poradził?

    Odpowiedz

Odpowiedz