Xlera8

Chrome zero-day: „Ten exploit jest powszechny”, więc sprawdź teraz swoją wersję

Najnowsza aktualizacja Google Chrome jest już dostępna i tym razem firma nie przebiera w słowach o jednej z dwóch poprawek bezpieczeństwa, które zawiera:

Google zdaje sobie sprawę, że exploit dla CVE-2023-3079 istnieje w stanie dzikim.

Nie ma mowy o dwóch stopniach separacji, jak często widzieliśmy wcześniej w Google, aby powiedzieć, że firma „jest świadoma doniesień” o exploicie.

Tym razem jest to „sami jesteśmy tego świadomi”, co przekłada się jeszcze bardziej dosadnie na „wiemy, że oszuści nadużywają tego, gdy mówimy”, biorąc pod uwagę, że raport o błędzie pochodzi bezpośrednio od własnej grupy badawczej Google ds. Badań nad Zagrożeniami.

Jak zwykle oznacza to, że Google badał aktywny atak (czy to na samego Google, czy na jakąś zewnętrzną organizację, nie wiemy), w którym Chrome został zaatakowany przez nieznaną wcześniej lukę w zabezpieczeniach.

Błąd jest opisany po prostu jako: Wpisz Zamieszanie w V8. (Co zrozumiałe, na tym etapie Google nie mówi nic więcej).

Jak wyjaśniliśmy wcześniej, a pomyłka typu błąd występuje, gdy dostarczasz programowi fragment danych, który ma analizować, sprawdzać, przetwarzać i działać w jeden sposób…

…ale później udaje ci się oszukać program, aby zinterpretował dane w inny, nieautoryzowany, niesprawdzony i potencjalnie niebezpieczny sposób.

Wyjaśnienie niebezpieczeństw związanych z pomieszaniem typów

Wyobraź sobie, że piszesz program w C. (Nie ma znaczenia, czy znasz C, czy nie, i tak możesz po prostu nadążyć).

W C zwykle deklaruje się zmienne indywidualnie, nie tylko rezerwując pamięć, w której mogą być przechowywane, ale także sygnalizując programowi, w jaki sposób te zmienne mają być używane.

Na przykład:

 long long int JulianNumerDnia; znak znak* nazwa_klienta;

Pierwsza deklaracja zmiennej rezerwuje 64 bity do przechowywania zwykłej starej wartości całkowitej reprezentującej astronomiczny numer dnia. (Jeśli się zastanawiasz, dziś po południu jest JDN 23157 – dni juliańskie zaczynają się w południe, a nie o północy, ponieważ astronomowie często pracują w nocy, a północ jest środkiem ich dnia pracy).

Drugi rezerwuje 64 bity do przechowywania adresu pamięci, w którym można znaleźć ciąg tekstowy nazwy klienta.

Jak możesz sobie wyobrazić, lepiej nie mieszaj tych dwóch wartości, ponieważ liczba, która ma sens i jest bezpieczna do użycia jako liczba dnia, taka jak 23157, prawie na pewno byłaby niebezpieczna w użyciu jako adres pamięci.

Jak widać z tego zrzutu pamięci uruchomionego programu Windows, najniższy adres pamięci, który jest przydzielony do użycia, zaczyna się od 0x00370000, czyli 3,604,480 XNUMX XNUMX dziesiętnie, znacznie więcej niż jakakolwiek rozsądna liczba dni.

Rzeczywiste adresy pamięci używane przez system Windows zmieniają się losowo w czasie, aby oszustom trudniej było odgadnąć układ pamięci, więc jeśli uruchomisz ten sam program, otrzymasz wartości, ale mimo to będą one podobne:

I (chociaż jest to poza dolną częścią powyższego obrazu) adresy pamięci sekcji danych użytkownika środowiska wykonawczego, gdy ten program był uruchamiany z 0x01130000 do 0x01134FFF, reprezentujący mało prawdopodobny zakres dat od 22 lipca 44631 do 16 sierpnia 44687.

Rzeczywiście, jeśli spróbujesz pomieszać te dwie zmienne, kompilator powinien spróbować cię ostrzec, na przykład w ten sposób:

 JulianDayNumber = nazwa klienta; NazwaKlienta = JulianDayNumber; ostrzeżenie: przypisanie tworzy liczbę całkowitą ze wskaźnika bez rzutowania ostrzeżenie: przypisanie tworzy wskaźnik z liczby całkowitej bez rzutowania

Teraz, jeśli kiedykolwiek programowałeś w C, wiesz, że dla wygody możesz deklarować zmienne z wieloma różnymi interpretacjami, używając union słowo kluczowe, takie jak to:

 union { long long int JulianDayNumer; znak znak* nazwa_klienta; } dane;

Możesz teraz odwoływać się dokładnie do tej samej zmiennej w pamięci na dwa różne sposoby.

Jeśli piszesz data.JulianDayNumber, magicznie interpretujesz zapisane dane jako liczbę całkowitą, ale piszesz data.CustomerName informuje kompilator, że odwołujesz się do adresu pamięci, mimo że uzyskujesz dostęp do tych samych przechowywanych danych.

To, co robisz, mniej więcej, polega na przyznaniu się kompilatorowi, że czasami będziesz traktować otrzymane dane jako datę, a innym razem jako adres pamięci, i że bierzesz odpowiedzialność za pamiętanie, która interpretacja ma zastosowanie w jakim momencie w kodzie.

Możesz zdecydować się na drugą zmienną, znaną jako a tag (zwykle liczba całkowita), aby pasowały do ​​twojego union aby śledzić, z jakimi danymi aktualnie pracujesz, na przykład:

 struct { znacznik int; union { long long int JulianDayNumer; znak znak* nazwa_klienta; } dane; } wartość;

Możesz zdecydować, kiedy value.tag jest ustawione na 0, dane nie są jeszcze zainicjowane do użytku, 1 oznacza, że ​​przechowujesz datę, 2 oznacza, że ​​jest to adres pamięci, a cokolwiek innego oznacza błąd.

Cóż, lepiej nie pozwól nikomu innemu w to mieszać value.tag ustawienia, lub twój program może skończyć się dramatycznie niewłaściwie.

Bardziej niepokojącym przykładem może być coś takiego:

 struct { znacznik int; // 1 = hash, 2 = function pointers union { unsigned char hash[16]; // zapisz losowy hash struct { void* openfunc; // lub dwa starannie sprawdzone void* closefunc; // wskaźniki kodu do późniejszego wykonania } validate; } } wartość;

Teraz przeciążamy ten sam blok pamięci, więc czasami możemy go użyć do przechowywania 16-bajtowego skrótu, a czasami do przechowywania dwóch 8-bajtowych wskaźników do funkcji, które nasz program będzie później wywoływał.

Jasne, kiedy value.tag == 1, bylibyśmy szczęśliwi mogąc pozwolić naszemu oprogramowaniu na przechowywanie dowolnego 16-bajtowego łańcucha w pamięci przydzielonej dla unii, ponieważ skróty są pseudolosowe, więc każdy zbiór bajtów jest równie prawdopodobny.

Ale kiedy value.tag == 2, nasz kod musiałby być bardzo ostrożny, aby nie pozwolić użytkownikowi na podanie niezweryfikowanych, niezaufanych, nieznanych adresów funkcji do późniejszego wykonania.

Teraz wyobraź sobie, że możesz przesłać wartość do tego kodu, gdy tag był ustawiony na 1, więc nie został sprawdzony i zweryfikowany…

… ale później, tuż przed tym, jak program faktycznie użył zapisanej wartości, udało się oszukać kod, aby zmienił tag na 2.

Kod zaakceptowałby wtedy Twoje niezweryfikowane adresy funkcji jako „znane i już zweryfikowane bezpieczne” (mimo że tak nie było) i ufnie wysłałby wykonanie programu do nieuczciwej lokalizacji w pamięci, którą wcześniej podstępnie wybrałeś.

I tak właśnie dzieje się w przypadku błędu związanego z pomyłką typu, aczkolwiek przy użyciu wymyślonego i uproszczonego przykładu,

Pamięć, która byłaby bezpieczna do użycia, gdyby była obsługiwana w jeden sposób, jest złośliwie dostarczana do programu w celu przetworzenia w alternatywny, niebezpieczny sposób.

Co robić?

Upewnij się, że masz najnowszą wersję Chrome lub Chromium.

Chcesz Chrome'a 114.0.5735.106 lub nowszy na Macu i Linuksie oraz 114.0.5735.110 lub później w systemie Windows.

Ten błąd dotyczy również Microsoft Edge, który jest oparty na Chromium.

Microsoft do tej pory [2023-06-06T16:25:00Z] zauważyłem to

Firma Microsoft jest świadoma ostatnich exploitów istniejących w środowisku naturalnym. Aktywnie pracujemy nad wydaniem poprawki bezpieczeństwa.

Edge jest obecnie w wersji 114.0.1823.37, więc wszystko jest policzone później niż to powinna zawierać poprawki CVE-2023-3079 firmy Microsoft.

Aby sprawdzić swoją wersję i wymusić aktualizację, jeśli jest taka, której jeszcze nie otrzymałeś:

  • Google Chrome. Menu z trzema kropkami (⋮) > Pomoc > O Chrome.
  • Microsoft Edge. Ustawienia i więcej (…) > Pomoc i opinie > O Microsoft Edge.

Nie ma za co.


Czat z nami

Cześć! Jak mogę ci pomóc?