W zestawie bibliotek kryptograficznych NSS (Network Security Services), rozwijanych przez firmę Mozilla, zidentyfikowano krytyczną lukę (CVE-2021-43527), która może prowadzić do wykonania kodu przez atakującego podczas przetwarzania podpisów cyfrowych DSA lub RSA-PSS, zadanych za pomocą metody kodowania DER (Distinguished Encoding Rules). Problem, któremu nadano kryptonim BigSig, został rozwiązany w wersjach NSS 3.73 oraz NSS ESR 3.68.1. Aktualizacje pakietów w dystrybucjach są dostępne dla Debian, RHEL, Ubuntu, SUSE, Arch Linux, Gentoo, FreeBSD. Aktualizacje dla Fedory są obecnie niedostępne.
Problem występuje w aplikacjach, które używają NSS do przetwarzania podpisów cyfrowych CMS, S/MIME, PKCS #7 i PKCS #12, lub podczas weryfikacji certyfikatów w implementacjach TLS, X.509, OCSP i CRL. Luka może pojawić się w różnych aplikacjach klienckich i serwerowych obsługujących TLS, DTLS i S/MIME, w klientach poczty oraz przeglądarkach PDF, które w użyciu mają wywołanie NSS CERT_VerifyCertificate() do sprawdzania podpisów cyfrowych.
Jako przykłady podatnych aplikacji wymieniane są LibreOffice, Evolution i Evince. Potencjalnie problem ten może również dotyczyć takich projektów jak Pidgin, Apache OpenOffice, Suricata, Curl, Chrony, Red Hat Directory Server, Red Hat Certificate System, mod_nss dla serwera http Apache, Oracle Communications Messaging Server oraz Oracle Directory Server Enterprise Edition. Luka nie występuje w Firefox, Thunderbird i Tor Browser, które do weryfikacji używają osobnej biblioteki mozilla::pkix, również wchodzącej w skład NSS. Problemu nie mają również przeglądarki oparte na Chromium (chyba że specjalnie zbudowano je z NSS), które korzystały z NSS do 2015 roku, a następnie przeszły na BoringSSL.
Luka jest spowodowana błędem w kodzie weryfikacji certyfikatów w funkcji vfy_CreateContext z pliku secvfy.c. Problem objawia się zarówno podczas odczytu certyfikatu klienta z serwera, jak i podczas przetwarzania serwerem certyfikatów klientów. Podczas weryfikacji podpisu cyfrowego zakodowanego metodą DER, NSS dekoduje podpis do bufora o stałym rozmiarze i przekazuje ten bufor do modułu PKCS #11. Podczas dalszego przetwarzania, dla podpisów DSA i RSA-PSS, niewłaściwie sprawdzana jest wielkość, co prowadzi do przepełnienia bufora przydzielonego dla struktury VFYContextStr, jeśli rozmiar podpisu cyfrowego przekracza 16384 bity (bufer otrzymuje 2048 bajtów, ale nie sprawdza się, czy podpis może być większy).
Kod zawierający lukę jest śledzony od 2003 roku, ale nie stanowił zagrożenia do refaktoryzacji przeprowadzonej w 2012 roku. W 2017 roku podczas implementacji wsparcia dla RSA-PSS popełniono ten sam błąd. Do przeprowadzenia ataku nie jest wymagana zasobożerna generacja określonych kluczy w celu uzyskania potrzebnych danych, ponieważ przepełnienie występuje na etapie przed weryfikacją poprawności podpisu cyfrowego. Wychodząca poza granice część danych jest zapisywana w obszarze pamięci zawierającym wskaźniki do funkcji, co ułatwia tworzenie działających exploitów.
Luka została wykryta przez badaczy z Google Project Zero podczas eksperymentów z nowymi metodami testowania fuzzingowego i jest dobrym przykładem tego, jak w szeroko testowanym, znanym projekcie mogą przez długi czas pozostawać niezauważone trywialne luki:
- Kod NSS jest wspierany przez doświadczony zespół odpowiedzialny za bezpieczeństwo, stosujący nowoczesne metody testowania i analizy błędów. Funkcjonuje kilka programów wypłacających znaczne nagrody za odkrywanie luk w NSS.
- NSS był jednym z pierwszych projektów przystępujących do inicjatywy Google oss-fuzz i był również testowany w rozwijanym przez Mozillę systemie testowania fuzzingowego opartym na libFuzzer.
- Kod biblioteki był wielokrotnie sprawdzany w różnych analizatorach statycznych, w tym od 2008 roku monitorowany przez usługę Coverity.
- Do 2015 roku NSS był używany w Google Chrome i niezależnie od Mozilli był sprawdzany przez zespół Google (od 2015 roku Chrome przeszedł na BoringSSL, ale wsparcie dla portu opartego na NSS jest nadal dostępne).
Główne problemy, które sprawiały, że problem przez długi czas pozostawał niezauważony:
- NSS to modułowa biblioteka, a testowanie fuzzingowe prowadzone było nie w całości, lecz na poziomie poszczególnych komponentów. Na przykład, oddzielnie sprawdzano kod dekodowania DER i przetwarzania certyfikatów — podczas fuzzingu mogło być uzyskane certyfikat prowadzący do manifestacji omawianej luki, ale jego weryfikacja nie docierała do kodu weryfikacji i problem nie ujawniał się.
- Podczas testowania fuzzingu wprowadzono rygorystyczne ograniczenia na rozmiar wyjścia (10 000 bajtów) przy braku takich ograniczeń w NSS (wiele struktur w normalnym trybie mogło mieć rozmiar większy niż 10 000 bajtów, dlatego aby zidentyfikować problemy, wymagano większej ilości danych wejściowych). Dla pełnej weryfikacji limit powinien wynosić 224-1 bajt (16 MB), co odpowiada maksymalnemu rozmiarowi certyfikatu dozwolonemu w TLS.
- Błędne wyobrażenie o zasięgu kodu testami fuzzingu. Wrażliwy kod był aktywnie testowany, ale przy użyciu fuzzera, który nie był w stanie wygenerować wymaganych danych wejściowych. Na przykład, fuzzer tls_server_target używał predefiniowanego zestawu gotowych certyfikatów, co ograniczało testowanie kodu weryfikacji certyfikatu tylko do komunikatów TLS i zmian stanu protokołu.
Źródło: opennet.ru
