Poważne bezpieczeństwo: GnuTLS podąża za OpenSSL, naprawia błąd ataku czasowego

Poważne bezpieczeństwo: GnuTLS podąża za OpenSSL, naprawia błąd ataku czasowego

Węzeł źródłowy: 1956368

W zeszłym tygodniu pisaliśmy o kilku błędy zarządzania pamięcią które zostały naprawione w najnowszej aktualizacji zabezpieczeń popularnej biblioteki szyfrowania OpenSSL.

Wraz z tymi błędami pamięci zgłosiliśmy również błąd dubbingowany CVE-2022-4304: Timing Oracle w deszyfrowaniu RSA.

W przypadku tego błędu wysyłanie w kółko tej samej zaszyfrowanej wiadomości na serwer, ale modyfikowanie dopełnienia na końcu danych w celu unieważnienia danych, a tym samym prowokowania nieprzewidywalnego zachowania…

… nie zajęłoby to stałej ilości czasu, zakładając, że jesteś blisko celu w sieci i możesz wiarygodnie odgadnąć, jak długo zajmie część procesu przesyłania danych.

Nie wszystkie dane przetwarzane jednakowo

Jeśli uruchomisz żądanie, czas, jaki zajmuje odpowiedź, i odejmiesz czas zużyty na niskopoziomowe wysyłanie i odbieranie danych sieciowych, wiesz, ile czasu zajęło serwerowi wykonanie wewnętrznych obliczeń w celu przetworzenia żądania .

Nawet jeśli nie masz pewności, ile czasu zużywa się w sieci, możesz szukać różnic w czasie podróży w obie strony, uruchamiając wiele żądań i zbierając mnóstwo próbek.

Jeśli sieć jest wystarczająco niezawodna, aby założyć, że narzut sieciowy jest w dużej mierze stały, możesz użyć metod statystycznych, aby wywnioskować, jaki rodzaj modyfikacji danych powoduje jakie dodatkowe opóźnienie przetwarzania.

Na tej podstawie wielu z was może wywnioskować coś o strukturze, a nawet zawartości oryginalnych niezaszyfrowanych danych, które mają być utrzymywane w tajemnicy w każdym powtarzanym żądaniu.

Nawet jeśli możesz wyodrębnić tylko jeden bajt zwykłego tekstu, cóż, to nie powinno się zdarzyć.

Tak zwane ataki czasowe tego rodzaju są zawsze kłopotliwe, nawet jeśli konieczne może być wysłanie milionów fałszywych pakietów i taktowanie ich wszystkich, aby mieć jakąkolwiek szansę na odzyskanie tylko jednego bajtu danych w postaci zwykłego tekstu…

…ponieważ sieci są szybsze, bardziej przewidywalne i zdolne do obsługi znacznie większego obciążenia niż jeszcze kilka lat temu.

Można by pomyśleć, że miliony zdradzieckich pakietów wysyłanych do ciebie spamem w ciągu, powiedzmy, następnej godziny, będą się wyróżniać jak kciuk.

Ale „milion pakietów na godzinę więcej lub mniej niż zwykle” po prostu nie jest już szczególnie dużą odmianą.

Podobny błąd „wyroczni” w GnuTLS

Cóż, ta sama osoba, która zgłosiła błąd w czasie naprawiania błędów w OpenSSL, również zgłosiła błąd podobny błąd w GnuTLS mniej więcej w tym samym czasie.

Ten ma identyfikator błędu CVE-2023-0361.

Chociaż GnuTLS nie jest tak popularny ani szeroko stosowany jak OpenSSL, prawdopodobnie masz wiele programów w swojej firmie IT, a nawet na własnym komputerze, które go używają lub zawierają, być może w tym FFmpeg, GnuPG, Mplayer, QEMU , Rdesktop, Samba, Wget i Wireshark.

Jak na ironię, luka czasowa w GnuTLS pojawiła się w kodzie, który miał rejestrować błędy ataku czasowego.

Jak widać z różnicy w kodzie (diff) poniżej, programista był świadomy, że wszelkie warunki (if ... then) operacja używana do sprawdzania i radzenia sobie z błędami deszyfrowania może powodować zmiany taktowania, ponieważ procesory generalnie potrzebują różnej ilości czasu w zależności od tego, w którą stronę kod idzie po instrukcji „rozgałęzienia”.

(Jest to szczególnie prawdziwe w przypadku gałęzi, która często idzie w jedną stronę, a rzadko w drugą, ponieważ procesory mają tendencję do zapamiętywania lub buforowania wielokrotnie uruchamianego kodu w celu poprawy wydajności, przez co rzadko wykonywany kod działa wykrywalnie wolniej).

Różnica w kodzie gnutls-3.7.8/lib/auth/rsa.c w stosunku do 3.7.9

Ale programista nadal chciał zarejestrować, że może mieć miejsce atak, co ma miejsce, jeśli plik if (ok) powyższy test kończy się niepowodzeniem i rozgałęzia się do else { ... }

W tym momencie kod wywołuje metodę _gnutls_debug_log() funkcji, której wykonanie może zająć trochę czasu.

Dlatego programista wstawił celowe wywołanie do _gnutls_no_log() then { ... } część kodu, która udaje, że rejestruje „atak”, gdy go nie ma, aby spróbować wyrównać czas, jaki kod spędza w dowolnym kierunku, w którym if (ok) instrukcja oddziału może zająć.

Najwyraźniej jednak dwie ścieżki kodu nie były wystarczająco podobne w czasie, w którym się zużyły (a może w _gnutls_debug_log() sama funkcja była niewystarczająco spójna w radzeniu sobie z różnymi rodzajami błędów), a osoba atakująca mogła zacząć rozróżniać sygnały deszyfrowania po około milionie prób.

Co robić?

Jeśli jesteś programistą: naprawa błędu tutaj była prosta i zgodna z zasadą „mniej znaczy więcej”.

Powyższy różowy kod, który i tak uznano za niezbyt przydatny do wykrywania ataków, został po prostu usunięty, ponieważ kod, którego tam nie ma, nie może zostać wkompilowany przez pomyłkę, niezależnie od ustawień kompilacji…

… a kod, który nie jest wkompilowany, nigdy nie może działać, czy to przez przypadek, czy projekt.

Jeśli jesteś użytkownikiem GnuTLS: niedawno wydana wersja 3.7.9 oraz „nowy smak produktu” 3.8.0 uwzględnij tę poprawkę wraz z różnymi innymi.

Jeśli korzystasz z dystrybucji Linuksa, sprawdź aktualizacje dowolnej centralnie zarządzanej wersji biblioteki współdzielonej GnuTLS, a także aplikacje, które udostępniają własną wersję.

W systemie Linux wyszukaj pliki o podanej nazwie libgnutls*.so aby znaleźć wszelkie biblioteki współdzielone leżące w pobliżu i wyszukać gnutls-cli aby znaleźć kopie narzędzia wiersza poleceń, które często jest dołączane do biblioteki.

Możesz biegać gnutls-cli -vv aby dowiedzieć się, która wersja libgnutls jest dynamicznie powiązany z:

 $ gnutls-cli -vv gnutls-cli 3.7.9 <-- moja dystrybucja Linuksa otrzymała aktualizację w zeszły piątek (2023)

Znak czasu:

Więcej z Nagie bezpieczeństwo