Zaufane pobieranie Schrödingera. Intel Boot Guard

Zaufane pobieranie Schrödingera. Intel Boot Guard
Proponujemy ponownie zjechać na niski poziom i porozmawiać o bezpieczeństwie oprogramowania układowego platform komputerowych zgodnych z x86. Tym razem głównym składnikiem badania jest Intel Boot Guard (nie mylić z Intel BIOS Guard!) – technologia zaufanego rozruchu BIOS wspierana sprzętowo, którą producent systemu komputerowego może na stałe włączyć lub wyłączyć na etapie produkcji. Przepis badania jest nam już znany: cienko pokroić inżynierię odwrotną implementacji tej technologii, opisać jej architekturę, wzbogacając o niedokumentowane szczegóły, doprawić wektorami ataków i wymieszać. Dodamy ognia opowieścią o tym, jak od lat klonowany błąd w produkcji kilku producentów pozwala potencjalnemu napastnikowi wykorzystać tę technologię do stworzenia w systemie niewykrywalnego (nawet przez programatorów) ukrytego rootkita.

A propos, w podstawie artykułu znajdują się wystąpienia "Na straży rootkitów: Intel BootGuard" z konferencji ZeroNights 2016 i 29. spotkania DefCon Russia (oba wystąpienia tutaj).

Oprogramowanie układowe platformy komputerowej architektury Intel 64

Na początek odpowiemy na pytanie: czym jest oprogramowanie układowe nowoczesnej platformy komputerowej architektury Intel 64? Oczywiście, to UEFI BIOS. Ale taka odpowiedź nie będzie dokładna. Przejrzyjmy rysunek, na którym przedstawiono wersję desktopową (laptopową) tej architektury.

Zaufane pobieranie Schrödingera. Intel Boot Guard
Podstawą jest zestaw:

  • Procesora (CPU, Central Processing Unit), w którym oprócz podstawowych rdzeni zintegrowane jest rdzenie graficzne (nie w wszystkich modelach) oraz zintegrowany kontroler pamięci (IMC, Integrated Memory Controller);
  • Chipsetu (PCH, Platform Controller Hub), zawierającego różne kontrolery do interakcji z urządzeniami peryferyjnymi oraz zarządzania podsystemami. Wśród nich znajduje się znana Intel Management Engine (ME), która również ma swoje oprogramowanie układowe (Intel ME firmware).

Laptopy, oprócz wyżej wymienionych, zakładają obecność wbudowanego kontrolera (ACPI EC, Advanced Control and Power Interface Embedded Controller), który odpowiada za funkcjonowanie podsystemu zasilania, touchpada, klawiatury, klawiszy Fn (jasność ekranu, głośność dźwięku, podświetlenie klawiatury itp.) i innych. I on również ma swoje oprogramowanie układowe.

Zatem zbiór wymienionych powyżej firmware'ów stanowi firmware platformy komputerowej (system firmware), który jest przechowywany w wspólnej pamięci flash SPI. Aby użytkownicy tej pamięci nie mylili się, zawartość tej pamięci jest podzielona na następujące obszary (jak pokazano na rysunku):

  • UEFI BIOS;
  • firmware ACPI EC (oddzielny obszar pojawił się z mikroarchitekturą procesora Skylake (2015 rok), ale w warunkach rzeczywistych wciąż nie spotkaliśmy przykładów jego wykorzystania, więc firmware kontrolera wciąż wchodzi w skład UEFI BIOS);
  • firmware Intel ME;
  • konfiguracja (adres MAC itd.) wbudowanego adaptera sieciowego GbE (Gigabit Ethernet);
  • deskriptory flash (Flash Descriptors) – główny obszar pamięci flash, który zawiera wskaźniki do pozostałych obszarów, a także uprawnienia do ich dostępu.

Zaufane pobieranie Schrödingera. Intel Boot Guard
Podział dostępu do obszarów (zgodnie z określonymi uprawnieniami) odbywa się przez mastera szyny SPI – wbudowany w chipset kontroler SPI, przez który następuje dostęp do tej pamięci. Jeśli uprawnienia są ustawione na zalecane (z względów bezpieczeństwa) przez firmę Intel wartości, to każdy użytkownik pamięci flash SPI ma pełny dostęp (odczyt/zapis) tylko do swojego obszaru. Pozostałe – są dostępne tylko do odczytu lub całkowicie niedostępne. Znany fakt: w wielu systemach CPU ma pełny dostęp do UEFI BIOS i GbE, dostęp tylko do deskriptorów flash, a do obszaru Intel ME dostęp jest całkowicie zablokowany. Dlaczego w wielu, a nie we wszystkich? Co jest zalecane, nie jest obowiązkowe. Więcej opowiemy dalej w artykule.

Mechanizmy ochrony firmware'u platformy komputerowej przed modyfikacjami

Oczywiście firmware platformy komputerowej powinien być chroniony przed możliwą kompromitacją, która mogłaby pozwolić potencjalnemu napastnikowi na osiedlenie się w nim (przetrwanie aktualizacji/ponownej instalacji systemu operacyjnego), wykonywanie swojego kodu w najbardziej uprzywilejowanych trybach itd. A podział dostępu do obszarów pamięci flash SPI jest oczywiście niewystarczający. Dlatego w celu ochrony firmware'u przed modyfikacjami stosuje się różne mechanizmy, specyficzne dla każdego środowiska wykonawczego.

Tak, firmware Intel ME jest podpisany w celu kontroli integralności i autentyczności i jest weryfikowany przez kontroler ME przy każdym jego ładowaniu do pamięci ME UMA. Proces weryfikacji był już przedmiotem naszych rozważań w jednym z artykułów, poświęconym subsystemowi Intel ME.

Oprogramowanie ACPI EC jest zazwyczaj weryfikowane tylko pod kątem integralności. Jednak, ponieważ ten binarny plik jest włączony w skład UEFI BIOS, zazwyczaj dotyczą go te same mechanizmy ochrony, które stosuje UEFI BIOS. O nich będziemy rozmawiać.

Te mechanizmy można podzielić na dwie kategorie.

Ochrona przed zapisem w obszarze UEFI BIOS.

  1. Fizyczna ochrona zawartości pamięci flash SPI za pomocą zworki write-protect;
  2. Ochrona projekcji regionu UEFI BIOS w przestrzeni adresowej CPU przy użyciu rejestrów PRx chipsetu;
  3. Zablokowanie prób zapisu w regionie UEFI BIOS przez generowanie i przetwarzanie odpowiedniego przerwania SMI poprzez ustawienie bitów BIOS_WE/BLE oraz SMM_BWP w rejestrach chipsetu;
  4. Bardziej zaawansowaną wersją tej ochrony jest Intel BIOS Guard (PFAT).

Oprócz tych mechanizmów, dostawcy mogą opracowywać i stosować własne środki bezpieczeństwa (na przykład, podpisywanie kapsuł z aktualizacjami UEFI BIOS).

Warto zauważyć, że na konkretnej systemie (zależy od dostawcy) mogą być stosowane nie wszystkie wymienione powyżej mechanizmy ochrony, mogą być całkowicie nie stosowane, a mogą być źle zaimplementowane. Szczegóły na temat tych mechanizmów i sytuacji z ich implementacją można znaleźć w w tym artykule. Osobom zainteresowanym zalecamy zapoznanie się z całym cyklem artykułów na temat bezpieczeństwa UEFI BIOS autorstwa CodeRush.

Weryfikacja autentyczności UEFI BIOS

Kiedy mówimy o technologiach zaufanego uruchamiania, pierwsze, co przychodzi na myśl, to Secure Boot. Jednak architektonicznie przeznaczony jest do weryfikacji autentyczności komponentów zewnętrznych w stosunku do UEFI BIOS (sterowników, bootloaderów itp.), a nie samego oprogramowania.

Dlatego firma Intel w SoC-ach z mikroarchitekturą Bay Trail (2012 rok) wdrożyła sprzętowy, nieodłączalny Secure Boot (Verified Boot), który nie ma nic wspólnego z wcześniej wspomnianą technologią Secure Boot. Później (w 2013 roku) ten mechanizm został udoskonalony i pod nazwą Intel Boot Guard wydany dla komputerów stacjonarnych z mikroarchitekturą Haswell.

Przed omówieniem Intel Boot Guard przyjrzyjmy się środowiskom wykonawczym w architekturze Intel 64, które jednocześnie są korzeniami zaufania dla tej technologii zaufanego uruchamiania.

Intel CPU

Kapitanka podpowiada, że procesor jest podstawowym środowiskiem wykonawczym w architekturze Intel 64. Dlaczego jest on także korzeniem zaufania? Okazuje się, że jest to związane z posiadaniem następujących elementów:

  • Mikrokod ROM — nieulotna, nieprzepisywalna pamięć do przechowywania mikrokodu. Mikrokod uważa się za implementację systemu instrukcji procesora w najprostszych komendach. W mikrokodzie zdarzają się również błędy. Dlatego w BIOS można znaleźć binaria z aktualizacjami mikrokodu (nałożone podczas rozruchu, ponieważ ROM nie można przepisać). Zawartość tych binariów jest zaszyfrowana, co znacznie utrudnia analizę (dlatego konkretna zawartość mikrokodu jest znana tylko tym, którzy go opracowują) i podpisana, w celu kontrolowania integralności i autentyczności;
  • klucz AES do dekodowania zawartości aktualizacji mikrokodu;
  • hash publicznego klucza RSA, którym weryfikowany jest podpis aktualizacji mikrokodu;
  • hash publicznego klucza RSA, którym weryfikowany jest podpis modułów kodowych ACM (Authenticated Code Module) opracowanych przez firmę Intel, które CPU może uruchomić przed rozpoczęciem działania BIOS (cześć mikrokodu) lub w trakcie jego działania, w przypadku wystąpienia niektórych zdarzeń.

Intel ME

Temu subsystemowi w naszym blogu poświęcono aż dwie artykułu. Przypomnijmy, że to środowisko wykonawcze opiera się na wbudowanym w chipset mikro kontrolerze i jest najbardziej skrytą oraz uprzywilejowaną w systemie.

Pomimo swojej ukrytości, Intel ME również jest korzeniem zaufania, ponieważ ma:

  • ME ROM — nieulotną, nieprzepisywalną pamięć (nie przewiduje się sposobu aktualizacji), zawierającą kod startowy oraz hash SHA256 publicznego klucza RSA, którym weryfikowany jest podpis oprogramowania Intel ME;
  • klucz AES do przechowywania tajnych informacji;
  • dostęp do wbudowanego w chipset zestawu bezpieczników (FPFs, Field Programmable Fuses) do trwałego przechowywania pewnych informacji, w tym także tych określonych przez dostawcę systemu komputerowego.

Intel Boot Guard 1.x

Małe zastrzeżenie. Numery wersji technologii Intel Boot Guard, których używamy w tym artykule, są umowne i mogą nie mieć nic wspólnego z numeracją stosowaną w wewnętrznej dokumentacji firmy Intel. Dodatkowo, zawarte tutaj informacje o implementacji tej technologii zostały uzyskane w toku inżynierii odwrotnej i mogą zawierać nieścisłości w porównaniu ze specyfikacją Intel Boot Guard, która prawdopodobnie nigdy nie zostanie opublikowana.

Zatem Intel Boot Guard (BG) to sprzętowo wspierana technologia weryfikacji autentyczności UEFI BIOS. Na podstawie jej krótkiego opisu w książce [Platform Embedded Security Technology Revealed, rozdział Boot with Integrity, or Not Boot], działa jak łańcuch zaufanego uruchamiania. A pierwszym ogniwem w tym łańcuchu jest kod startowy (mikrokod) wewnątrz CPU, który uruchamia się w momencie RESET (nie mylić z wektorem RESET w BIOS!). CPU znajduje na pamięci flash SPI zaprojektowany i podpisany przez firmę Intel moduł kodowy (Intel BG startup ACM), ładuje go do swojego cache, weryfikuje (jak już wspomniano, CPU posiada hash publicznego klucza, którym sprawdzana jest podpis ACM) i uruchamia.

Zaufane pobieranie Schrödingera. Intel Boot Guard

Ten moduł kodowy odpowiada za weryfikację małej startowej części UEFI BIOS — Initial Boot Block (IBB), który z kolei zawiera funkcjonalność do weryfikacji głównej części UEFI BIOS. W ten sposób Intel BG pozwala upewnić się w autentyczności BIOS przed uruchomieniem systemu operacyjnego (który może działać pod nadzorem technologii Secure Boot).

Technologia Intel BG przewiduje dwa tryby działania (przy czym jeden nie przeszkadza drugiemu, tj. oba tryby mogą być aktywne w systemie, a mogą być również oba wyłączone).

Measured Boot

W trybie Measured Boot (MB) każdy komponent startowy (począwszy od ROM-u startowego CPU) "mierzy" następny, wykorzystując możliwości TPM (Trusted Platform Module). Dla tych, którzy nie są zaznajomieni, wyjaśnijmy.

TPM ma PCR-y (Platform Configuration Registers), do których zapisywany jest wynik operacji haszowania według wzoru:

Zaufane pobieranie Schrödingera. Intel Boot Guard

Tzn. bieżąca wartość PCR zależy od poprzedniej, przy czym dane te są zerowane tylko przy RESET-ie systemu.

W ten sposób w trybie MB w pewnym momencie wartości PCR odzwierciedlają unikalny (w ramach możliwości operacji haszowania) identyfikator kodu lub danych, które były "mierzone". Wartości PCR mogą być użyte przy operacji szyfrowania niektórych danych (TPM_Seal). Po tym ich deszyfrowanie (TPM_Unseal) będzie możliwe tylko w przypadku, jeśli wartości PCR w wyniku uruchomienia się nie zmieniły (tj. żaden "mierzony" komponent nie został zmodyfikowany).

Verified Boot

Najstraszniejszym dla miłośników modyfikowania UEFI BIOS jest tryb Verified Boot (VB), w którym każdy komponent startowy kryptograficznie sprawdza integralność i autentyczność następnego. A w przypadku błędu weryfikacji, następuje (jedno z):

  • wyłączenie po czasie od 1 min do 30 min (aby użytkownik miał czas zrozumieć, dlaczego jego komputer się nie uruchamia, i w razie możliwości spróbowałby przywrócić BIOS);
  • natychmiastowe wyłączenie (żeby użytkownik nie zdążył niczego zrozumieć i, tym bardziej, zrobić);
  • kontynuowanie pracy z kamienną twarzą (ten przypadek, gdy nie myślimy o bezpieczeństwie, ponieważ są ważniejsze sprawy).

Wybór działania zależy od ustawionej konfiguracji Intel BG (a dokładniej, od tzw. polityki egzekwowania), która przez dostawcę platformy komputerowej jest na stałe zapisywana w specjalnie przeznaczonym magazynie – fusach chipsetu (FPF). Szczegóły omówimy później.

Oprócz konfiguracji, dostawca generuje dwa klucze RSA 2048 i tworzy dwie struktury danych (przedstawione na rysunku):

  1. Manifest klucza głównego dostawcy (KEYM, Manifest Klucza Głównego OEM), w którym umieszcza SVN (Numer Wersji Zabezpieczeń) tego manifestu, SHA256 hash klucza publicznego następnego manifestu, klucz publiczny RSA (czyli publiczną część klucza głównego dostawcy) do weryfikacji podpisu tego manifestu i sam podpis;
  2. Manifest IBB (IBBM, Manifest Początkowego Bloku Uruchamiania), w którym umieszcza SVN tego manifestu, SHA256 hash IBB, klucz publiczny do weryfikacji podpisu tego manifestu i sam podpis.

SHA256 hash klucza publicznego OEM Root Key na stałe zapisuje się we fusach chipsetu (FPF), tak samo jak konfiguracja Intel BG. Jeśli konfiguracja Intel BG przewiduje włączenie tej technologii, od tego momentu na danym systemie aktualizować BIOS (czyli mieć możliwość przeliczenia tych manifestów) może tylko posiadacz prywatnej części klucza OEM Root, czyli dostawca.

Zaufane pobieranie Schrödingera. Intel Boot Guard

Patrząc na obrazek, od razu rodzi się pytanie o sens tak długiego łańcucha weryfikacji – można było użyć jednego manifestu. Po co komplikować?

W rzeczywistości firma Intel w ten sposób daje dostawcy możliwość używania różnych kluczy IBB dla różnych linii swoich produktów i jednego – jako klucza głównego. Jeśli wycieknie prywatna część klucza IBB (którym podpisywany jest drugi manifest), incydent dotknie tylko jednej linii produktów i tylko do momentu, gdy dostawca nie wygeneruje nowej pary i nie włączy przeliczonych manifestów w następnej aktualizacji BIOS.

Jednakże, jeśli klucz główny (którym podpisywany jest pierwszy manifest) zostanie skompromitowany, jego wymiana będzie niemożliwa, ponieważ nie przewidziano procedury odwołania, a skrót publicznej części tego klucza jest programowany w FPF tylko raz na zawsze.

Konfiguracja Intel Boot Guard

Teraz skupmy się bardziej na konfiguracji Intel BG i procesie jej tworzenia. Jeśli spojrzymy na odpowiednią zakładkę w GUI narzędzia Flash Image Tool w zestawie Intel System Tool Kit (STK), zauważymy, że konfiguracja Intel BG zawiera skrót publicznej części klucza głównego dostawcy, parę niejasnych wartości i tzw. profil Intel BG.

Zaufane pobieranie Schrödingera. Intel Boot Guard

Struktura tego profilu:

typedef struct BG_PROFILE
{
	unsigned long Force_Boot_Guard_ACM : 1;
	unsigned long Verified_Boot : 1;
	unsigned long Measured_Boot : 1;
	unsigned long Protect_BIOS_Environment : 1;
	unsigned long Enforcement_Policy : 2; // 00b – nie rób nic
                                              // 01b – wyłącz z opóźnieniem
                                              // 11b – natychmiastowe wyłączenie
	unsigned long : 26;
};

W ogóle, konfiguracja Intel BG jest bardzo elastyczna. Rozważmy na przykład flagę Force_Boot_Guard_ACM. Kiedy jest ona wyłączona, jeśli moduł BG startup ACM na pamięci SPI flash nie zostanie znaleziony, nie będzie żadnego zaufanego uruchamiania. Będzie to uruchamianie niezaufane.

Już wcześniej pisaliśmy, że politykę egzekucji dla trybu VB można skonfigurować tak, aby w przypadku błędu weryfikacji wystąpiło, ponownie, uruchamianie niezaufane.

Pozostawianie takich rzeczy na uznanie dostawców…

GUI narzędzia przewiduje następujące „gotowe” profile:

Numer
Tryb
Opis

0
No_FVME
technologia Intel BG wyłączona

1
VE
włączony tryb VB, wyłączenie po czasie

2
VME
włączone oba tryby (VB i MB), wyłączenie po czasie

3
VM
włączone oba tryby, bez wyłączenia systemu

4
FVE
włączony tryb VB, natychmiastowe wyłączenie

5
FVME
włączone oba tryby, natychmiastowe wyłączenie

Jak już wspomniano, konfiguracja Intel BG musi być na zawsze zapisana przez dostawcę systemu w bezpiecznych fuse'ach chipsetu (FPF) – małym (według niepotwierdzonych informacji, tylko 256 bajtów) magazynie sprzętowym informacji wewnątrz chipsetu, które można zaprogramować poza zakładami produkcyjnymi firmy Intel (dlatego właśnie Field Programmable Fuses).

Idealnie nadaje się do przechowywania konfiguracji, ponieważ:

  • ma obszar jednorazowego programowania do przechowywania danych (dokładnie tam, gdzie zapisywana jest konfiguracja Intel BG);
  • może być tylko odczytywana i programowana przez Intel ME.

Aby skonfigurować technologię Intel BG na konkretnej platformie, producent wykonuje następujące kroki podczas produkcji:

  1. Za pomocą narzędzia Flash Image Tool (z Intel STK) tworzy obraz firmware'u z zadaną konfiguracją Intel BG w postaci zmiennych wewnątrz obszaru Intel ME (tzw. tymczasowe lustro dla FPF-ów);
  2. Następnie narzędzie Flash Programming Tool (z Intel STK) zapisuje ten obraz w pamięci FLASH SPI systemu i zamyka tzw. tryb produkcyjny (przy tym wysyłana jest odpowiednia komenda do Intel ME).

W wyniku tych operacji Intel ME zapisuje w FPF-ach podane wartości z lustra dla FPF-ów w regionie ME, ustawia uprawnienia w opisanych przez firmę Intel wartościach w descriptorach FLASH SPI (opisanych na początku artykułu) i wykonuje RESET systemu.

Analiza implementacji Intel Boot Guard

W celu analizy realizacji tej technologii na konkretnym przykładzie sprawdziliśmy następujące systemy pod kątem obecności śladów technologii Intel BG:

System
Uwaga

Gigabyte GA-H170-D3H
Skylake, wsparcie dostępne

Gigabyte GA-Q170-D3H
Skylake, wsparcie dostępne

Gigabyte GA-B150-HD3
Skylake, wsparcie dostępne

MSI H170A Gaming Pro
Skylake, brak wsparcia

Lenovo ThinkPad 460
Skylake, wsparcie dostępne, technologia włączona

Lenovo Yoga 2 Pro
Haswell, brak wsparcia

Lenovo U330p
Haswell, brak wsparcia

Pod "wsparciem" rozumiemy obecność modułu startup ACM Intel BG, wspomnianych wyżej manifestów oraz odpowiedniego kodu w BIOS, tzn. implementacji do analizy.

Na przykład, weźmy pobrany z oficjalnej strony producenta obraz pamięci FLASH SPI dla Gigabyte GA-H170-D3H (wersja F4).

Intel CPU boot ROM

Na początku porozmawiajmy o działaniach procesora, gdy technologia Intel BG jest włączona.

Nie udało się znaleźć próbek odszyfrowanego mikrokodu, dlatego to, jak opisane poniżej działania są realizowane (w mikrokodzie lub sprzętowo) – jest otwartym pytaniem. Niemniej jednak, fakt, że nowoczesne procesory Intel potrafią te działania wykonywać, jest oczywistością.

Po wyjściu ze stanu RESET, procesor (w adresowym obszarze którego już zamapowane jest zawartość pamięci FLASH) odnajduje tabelę FIT (Firmware Interface Table). Znalezienie jej jest proste, wskaźnik do niej jest zapisany pod adresem FFFF FFC0h.

Zaufane pobieranie Schrödingera. Intel Boot Guard
W omawianym przykładzie pod tym adresem znajduje się wartość FFD6 9500h. Odwołując się do tego adresu, procesor widzi tabelę FIT, której zawartość jest podzielona na wpisy. Pierwszy wpis to nagłówek następującej struktury:

typedef struct FIT_HEADER
{
	char           Tag[8];     // ‘_FIT_   ’
	unsigned long  NumEntries; // w tym wpis nagłówka FIT
	unsigned short Version;    // 1.0
	unsigned char  EntryType;  // 0
	unsigned char  Checksum;
};

Zaufane pobieranie Schrödingera. Intel Boot Guard
Z nieznanych przyczyn suma kontrolna nie zawsze jest obliczana w tych tabelach (pole pozostaje zerowe).

Pozostałe wpisy wskazują na różne binaria, które należy przeanalizować/wykonać jeszcze przed uruchomieniem BIOS-u, tzn. przed przejściem do legacy RESET-wektora (FFFF FFF0h). Struktura każdego takiego wpisu jest następująca:

typedef struct FIT_ENTRY
{
	unsigned long  BaseAddress;
	unsigned long  : 32;
	unsigned long  Size;
	unsigned short Version;     // 1.0
	unsigned char  EntryType;
	unsigned char  Checksum;
};

Zaufane pobieranie Schrödingera. Intel Boot Guard
Pole EntryType wskazuje na typ bloku, na który wskazuje ten wpis. Znamy kilka typów:

enum FIT_ENTRY_TYPES
{
	FIT_HEADER = 0,
	MICROCODE_UPDATE,
	BG_ACM,
	BIOS_INIT = 7,
	TPM_POLICY,
	BIOS_POLICY,
	TXT_POLICY,
	BG_KEYM,
	BG_IBBM
};

Teraz jest oczywiste, że jeden z wpisów wskazuje na lokalizację binariów Intel BG startup ACM. Struktura nagłówka tego binarium jest typowa dla kodowych modułów opracowywanych przez firmę Intel (ACM-y, aktualizacje mikrokodu, kodowe obszary Intel ME itp.).

typedef struct BG_ACM_HEADER
{
	unsigned short ModuleType;     // 2
	unsigned short ModuleSubType;  // 3
	unsigned long  HeaderLength;   // w dwords
	unsigned long  : 32;
	unsigned long  : 32;
	unsigned long  ModuleVendor;   // 8086h
	unsigned long  Date;           // w formacie BCD
	unsigned long  TotalSize;      // w dwords
	unsigned long  unknown1[6];
	unsigned long  EntryPoint;
	unsigned long  unknown2[16];
	unsigned long  RsaKeySize;     // w dwords
	unsigned long  ScratchSize;    // w dwords
	unsigned char  RsaPubMod[256];
	unsigned long  RsaPubExp;
	unsigned char  RsaSig[256];
};

Zaufane pobieranie Schrödingera. Intel Boot Guard
Procesor ładuje to binarium do swojego cache, weryfikuje je i uruchamia.

Intel BG startup ACM

W wyniku analizy działania tego ACM stało się jasne, że wykonuje on następujące czynności:

  • otrzymuje od Intel ME konfigurację Intel BG, zapisaną we fuse'ach chipsetu (FPF-y);
  • znajduje manifesty KEYM i IBBM, weryfikuje je.

Aby znaleźć te manifesty, ACM również korzysta z tabeli FIT, w której przewidziano dwa typy wpisów wskazujących na dane struktury (patrz FIT_ENTRY_TYPES powyżej).

Skupmy się bardziej szczegółowo na manifestach. W strukturze pierwszego manifestu widzimy kilka niejasnych stałych, hash klucza publicznego z drugiego manifestu oraz klucz publiczny OEM Root Key z podpisem w postaci zagnieżdżonej struktury:

typedef struct KEY_MANIFEST
{
	char           Tag[8];          // ‘__KEYM__’
	unsigned char  : 8;             // 10h
	unsigned char  : 8;             // 10h
	unsigned char  : 8;             // 0
	unsigned char  : 8;             // 1
	unsigned short : 16;            // 0Bh
	unsigned short : 16;            // 20h == hash size?
	unsigned char  IbbmKeyHash[32]; // SHA256 of an IBBM public key
	BG_RSA_ENTRY   OemRootKey;
};

typedef struct BG_RSA_ENTRY
{
	unsigned char  : 8;             // 10h
	unsigned short : 16;            // 1
	unsigned char  : 8;             // 10h
	unsigned short RsaPubKeySize;   // 800h
	unsigned long  RsaPubExp;
	unsigned char  RsaPubKey[256];
	unsigned short : 16;            // 14
	unsigned char  : 8;             // 10h
	unsigned short RsaSigSize;      // 800h
	unsigned short : 16;            // 0Bh
	unsigned char  RsaSig[256];
};

Zaufane pobieranie Schrödingera. Intel Boot Guard
Do weryfikacji publicznego klucza OEM Root Key używany jest skrót SHA256 z bezpieczników, który został już uzyskany od Intel ME.

Przejdźmy do drugiego manifestu. Składa się on z trzech struktur:

typedef struct IBB_MANIFEST
{
	ACBP Acbp;         // Polityki uruchamiania
	IBBS Ibbs;         // Opis IBB
	IBB_DESCRIPTORS[];
	PMSG Pmsg;         // Podpis IBBM
};

W pierwszej - jakieś stałe wartości:

typedef struct ACBP
{
	char           Tag[8];          // ‘__ACBP__’
	unsigned char  : 8;             // 10h
	unsigned char  : 8;             // 1
	unsigned char  : 8;             // 10h
	unsigned char  : 8;             // 0
	unsigned short : 16;            // x & F0h = 0
	unsigned short : 16;            // 0 < x <= 400h
};

W drugiej znajduje się skrót SHA256 IBB oraz liczba deskryptorów, które opisują zawartość IBB (tj. to, od czego oblicza się skrót):

typedef struct IBBS
{
	char           Tag[8];            // ‘__IBBS__’
	unsigned char  : 8;               // 10h
	unsigned char  : 8;               // 0
	unsigned char  : 8;               // 0
	unsigned char  : 8;               // x <= 0Fh
	unsigned long  : 32;              // x & FFFFFFF8h = 0
	unsigned long  Unknown[20];
	unsigned short : 16;              // 0Bh
	unsigned short : 16;              // 20h == hash size ?
	unsigned char  IbbHash[32];       // SHA256 of an IBB
	unsigned char  NumIbbDescriptors;
};

Deskryptory IBB następują za tą strukturą jeden za drugim. Ich zawartość ma następujący format:

typedef struct IBB_DESCRIPTOR
{
	unsigned long  : 32;
	unsigned long  BaseAddress;
	unsigned long  Size;
};

Wszystko jest proste: każdy deskryptor zawiera adres/rozmiar fragmentu IBB. Tak więc, konkatenacja bloków, na które wskazują te deskryptory (w kolejności ich występowania) stanowi IBB. I, jak zazwyczaj, IBB to zbiorcze moduły faz SEC i PEI.

Drugi manifest kończy struktura, zawierająca publiczny klucz IBB (weryfikowany przez skrót SHA256 z pierwszego manifestu) oraz podpis tego manifestu:

typedef struct PMSG
{
	char           Tag[8];            // ‘__PMSG__’
	unsigned char  : 8;               // 10h
	BG_RSA_ENTRY   IbbKey;
};

Zaufane pobieranie Schrödingera. Intel Boot Guard
Tak więc, jeszcze przed uruchomieniem UEFI BIOS procesor uruchomi ACM, który zweryfikuje autentyczność zawartości sekcji z kodem faz SEC i PEI. Następnie procesor wychodzi z ACM, przechodzi do wektora RESET i zaczyna wykonywać BIOS.

Zweryfikowana sekcja PEI musi zawierać moduł, który sprawdzi pozostałą część BIOS-u (kod DXE). Moduł ten opracowuje już IBV (Independent BIOS Vendor) lub sam dostawca systemu. Ponieważ w naszej dyspozycji były tylko systemy Lenovo i Gigabyte z obsługą Intel BG, rozważymy kod pozyskany właśnie z tych systemów.

UEFI BIOS moduł LenovoVerifiedBootPei

W przypadku Lenovo był to moduł LenovoVerifiedBootPei {B9F2AC77-54C7-4075-B42E-C36325A9468D}, opracowany przez firmę Lenovo.

Jego zadaniem jest wyszukiwanie (po GUID) tabeli haszy dla DXE i weryfikacja DXE.

if (EFI_PEI_SERVICES->GetBootMode() != BOOT_ON_S3_RESUME)
{
	if (!FindHashTable())
		return EFI_NOT_FOUND;
	if (!VerifyDxe())
		return EFI_SECURITY_VIOLATION;
}

Tabela haszy {389CC6F2-1EA8-467B-AB8A-78E769AE2A15} ma następujący format:

typedef struct HASH_TABLE
{
	char          Tag[8];            // ‘$HASHTBL’
	unsigned long NumDxeDescriptors;
	DXE_DESCRIPTORS[];
};

typedef struct DXE_DESCRIPTOR
{
	unsigned char BlockHash[32];     // SHA256
	unsigned long Offset;
	unsigned long Size;
};

UEFI BIOS moduł BootGuardPei

W przypadku Gigabyte był to moduł BootGuardPei {B41956E1-7CA2-42DB-9562-168389F0F066}, opracowany przez firmę AMI, a zatem obecny w każdym BIOS-ie AMI z obsługą Intel BG.

Jego algorytm działania jest nieco inny, jednak sprowadza się do tego samego:

int bootMode = EFI_PEI_SERVICES->GetBootMode();

if (bootMode != BOOT_ON_S3_RESUME &&
    bootMode != BOOT_ON_FLASH_UPDATE &&
    bootMode != BOOT_IN_RECOVERY_MODE)
{
	HOB* h = CreateHob();
	if (!FindHashTable())
		return EFI_NOT_FOUND;
	WriteHob(&h, VerifyDxe());
	return h;
}

Tabela haszy {389CC6F2-1EA8-467B-AB8A-78E769AE2A15}, którą poszukuje, ma następujący format:

typedef HASH_TABLE DXE_DESCRIPTORS[];

typedef struct DXE_DESCRIPTOR
{
	unsigned char BlockHash[32];     // SHA256
	unsigned long BaseAddress;
	unsigned long Size;
};

Intel Boot Guard 2.x

Krótko opowiemy jeszcze o jednej implementacji Intel Boot Guard, która została znaleziona w nowszym systemie opartym na Intel SoC z mikroarchitekturą Apollo Lake — ASRock J4205-IT.

Chociaż ta wersja będzie stosowana tylko w SoC, nowe systemy z mikroarchitekturą procesora Kaby Lake wciąż korzystają z Intel Boot Guard 1.x, przedstawia ona duże zainteresowanie w badaniach nowej wersji architektury dla platform na Intel SoC, w której zaszły zauważalne zmiany, takie jak:

  • regiony BIOS i Intel ME (właściwie Intel TXE, zgodnie z terminologią dla Intel SoC) są teraz jednym regionem IFWI;
  • choć platforma miała włączony Intel BG, nie znaleziono takich struktur jak FIT, KEYM, IBBM w pamięci flash;
  • oprócz rdzeni TXE i ISH (x86), w chipsecie dodano trzecie jądro (znowu ARC, nawiasem mówiąc) – PMC (Power Management Controller), związane z zapewnieniem funkcjonowania podsystemu zasilania oraz monitorowaniem wydajności.

Zaufane pobieranie Schrödingera. Intel Boot Guard
Zawartość nowego regionu IFWI składa się z następujących modułów:

Przesunięcie
Nazwa
Opis

0000 2000h
SMIP
jakieś konto konfiguracji platformy, podpisane przez dostawcę

0000 6000h
RBEP
sekcja kodowa firmware'u Intel TXE, x86, podpisana przez Intel

0001 0000h
PMCP
sekcja kodowa firmware'u Intel PMC, ARC, podpisana przez Intel

0002 0000h
FTPR
sekcja kodowa firmware'u Intel TXE, x86, podpisana przez Intel

0007 B000h
UCOD
aktualizacje mikrokodu dla CPU, podpisane przez Intel

0008 0000h
IBBP
UEFI BIOS, fazy SEC/PEI, x86, podpisane przez dostawcę

0021 8000h
ISHC
sekcja kodowa firmware'u Intel ISH, x86, podpisana przez dostawcę

0025 8000h
NFTP
sekcja kodowa firmware'u Intel TXE, x86, podpisana przez Intel

0036 1000h
IUNP
nieznane

0038 1000h
OBBP
UEFI BIOS, faza DXE, x86, niepodpisane

Podczas analizy firmware'u TXE stało się jasne, że po RESET-e TXE utrzymuje procesor w tym stanie, dopóki nie przygotuje podstawowej zawartości przestrzeni adresowej dla CPU (FIT, ACM, RESET-wektor …). TXE umieszcza te dane w swoim SRAM, a następnie tymczasowo udostępnia procesorowi do nich dostęp i „uwalnia” go z RESET-u.

Na straży rootkitów

A teraz przejdźmy do „gorącego” tematu. Pewnego razu odkryliśmy, że w wielu systemach w opisach KO FLASH SPI zapisane są uprawnienia dostępu do regionów pamięci flash SPI w taki sposób, że wszyscy użytkownicy tej pamięci mogą zarówno pisać, jak i czytać dowolny region. Tzn. w ogóle.

Po sprawdzeniu za pomocą narzędzia MEinfo (z Intel STK) zobaczyliśmy, że tryb manufacturing mode na tych systemach nie jest zamknięty, a zatem fusy chipsetu (FPF-y) pozostają w nieokreślonym stanie. Tak, Intel BG w takich przypadkach ani nie jest włączony, ani wyłączony.

Mowa o następujących systemach (w odniesieniu do Intel BG i tego, co zostanie opisane dalej w artykule, będziemy mówić o systemach z mikroarchitekturą procesora Haswell i wyższą):

  • cała produkcja Gigabyte;
  • cała produkcja MSI;
  • 21 model laptopów Lenovo i 4 modele serwerów Lenovo.

Oczywiście zgłosiliśmy to odkrycie tym dostawcom, a także firmie Intel.

Adekwatna reakcja przyszła tylko od Lenovo, którzy przyznali problem i wydali łatkę.

Gigabyte , podobno przyjęli informację o podatności, ale w żaden sposób się do niej nie odnieśli.

Komunikacja z MSI wszystko utknęło na naszej prośbie o przesłanie swojego publicznego klucza PGP (aby przesłać im powiadomienie o bezpieczeństwie w zaszyfrowanej formie). Odpowiedzieli, że „są producentem sprzętu, a klucze PGP nie są produkowane”.

Ale wracając do sedna. Ponieważ fusy są pozostawione w nieustalonym stanie, użytkownik (lub haker) może je samodzielnie zaprogramować (najtrudniejsze - znaleźć Intel STK). W tym celu należy wykonać następujące kroki.

1. Uruchomić się w systemie operacyjnym Windows (w ogóle, opisane poniżej działania można również wykonać pod Linuxem, jeśli opracuje się odpowiednik Intel STK dla potrzebnego systemu operacyjnego). Używając narzędzia MEinfo, upewnić się, że fusy w danym systemie nie są zaprogramowane.

Zaufane pobieranie Schrödingera. Intel Boot Guard
2. Wczytać zawartość pamięci flash za pomocą Flash Programming Tool.

Zaufane pobieranie Schrödingera. Intel Boot Guard
3. Otworzyć wczytany obraz za pomocą dowolnego narzędzia do edytowania UEFI BIOS, wprowadzić niezbędne zmiany (na przykład wprowadzić rootkit), stworzyć/edytować istniejące struktury KEYM i IBBM w regionie ME.

Zaufane pobieranie Schrödingera. Intel Boot Guard
Zaufane pobieranie Schrödingera. Intel Boot Guard
Na rysunku zaznaczona jest publiczna część klucza RSA, którego skrót zostanie zaprogramowany w fusy chipsetu wraz z resztą konfiguracji Intel BG.

4. Za pomocą Flash Image Tool zebrać nowy obraz oprogramowania (ustawiając konfigurację Intel BG).

Zaufane pobieranie Schrödingera. Intel Boot Guard
5. Zatwierdzić nowy obraz na pamięci flash za pomocą Flash Programming Tool, upewnić się przy pomocy MEinfo, że region ME teraz zawiera konfigurację Intel BG.

Zaufane pobieranie Schrödingera. Intel Boot Guard
6. Za pomocą Flash Programming Tool zamknąć tryb manufacturing mode.

Zaufane pobieranie Schrödingera. Intel Boot Guard
7. System się zrestartuje, po czym za pomocą MEinfo można upewnić się, że FPF zostały teraz zaprogramowane.

Zaufane pobieranie Schrödingera. Intel Boot Guard
Te działania na zawsze włączą Intel BG w danym systemie. Odwołanie tych działań nie będzie możliwe, co oznacza:

  • aktualizować UEFI BIOS w danym systemie może tylko posiadacz prywatnej części klucza głównego (tj. ten, kto włączył Intel BG);
  • jeśli przywrócić temu systemowi oryginalne oprogramowanie, na przykład za pomocą programatora, nawet się nie włączy (skutek polityki enforcement w przypadku błędu weryfikacji);
  • aby pozbyć się takiego UEFI BIOS, należy wymienić chipset z zaprogramowanymi FPF na „czysty” (tj. przylutować chipset, jeśli masz dostęp do stacji lutowniczej infra, której koszt wynosi tyle, co samochód, lub po prostu wymienić płytę główną).

Aby zrozumieć, co może spowodować taki rootkit, należy ocenić, co daje możliwość wykonywania własnego kodu w środowisku UEFI BIOS. Na przykład w najbardziej uprzywilejowanym trybie procesora – SMM. Taki rootkit może mieć następujące właściwości:

  • wykonywać się równolegle z systemem operacyjnym (można ustawić uruchomienie przez generację przerwania SMI, które będzie wyzwalane przez timer);
  • mieć wszystkie zalety bycia w trybie SMM (pełny dostęp do zawartości pamięci RAM i do zasobów sprzętowych, ukrycie przed systemem operacyjnym);
  • kod oprogramowania rootkita może znajdować się w postaci zaszyfrowanej i być deszyfrowany podczas uruchamiania w trybie SMM. Jako klucz do szyfrowania można użyć dowolnych danych dostępnych tylko w trybie SMM. Na przykład, hash zestawu adresów w SMRAM. Aby uzyskać ten klucz, trzeba się dostać do SMM. A to można zrobić na dwa sposoby. Znaleźć RCE w kodzie SMM i wykorzystać, lub dodać do BIOS-u własny moduł SMM, co jest niemożliwe, ponieważ włączyliśmy Boot Guard.

W ten sposób ta podatność umożliwia atakującemu:

  • stworzyć w systemie ukryty, niewykasowalny rootkit o nieznanym przeznaczeniu;
  • wykonywać swój kod na jednym z rdzeni chipsetu wewnątrz Intel SoC, a konkretnie na Intel ISH (dokładnie przyjrzyjmy się obrazkowi).

Zaufane pobieranie Schrödingera. Intel Boot Guard
Zaufane pobieranie Schrödingera. Intel Boot Guard
Choć możliwości podsystemu Intel ISH są jeszcze nie zbadane, wydaje się on interesującym wektorem ataku na Intel ME.

Wnioski

  1. Badania pozwoliły uzyskać techniczną charakterystykę działania technologii Intel Boot Guard. Minus kilka tajemnic w modelu Intel security through obscurity.
  2. Przedstawiono scenariusz ataku, który pozwala stworzyć w systemie niewykasowalny rootkit.
  3. Zobaczyliśmy, że nowoczesne procesory Intel są w stanie wykonać wiele własnościowego kodu jeszcze przed rozpoczęciem pracy BIOS-u.
  4. Platformy z architekturą Intel 64 stają się coraz mniej odpowiednie do uruchamiania wolnego oprogramowania: weryfikacja sprzętowa, rosnąca liczba własnościowych technologii i podsystemów (trzy rdzenie w chipsecie SoC: x86 ME, x86 ISH i ARC PMC).

Mitigacje

Dostawcy, którzy celowo pozostawiają otwarty tryb produkcji, powinni go koniecznie zamknąć. Na razie zamykają tylko oczy, a nowe systemy Kaby Lake to pokazują.

Użytkownicy mogą sami wyłączyć Intel BG na swoich systemach (które są podatne na opisaną podatność), uruchamiając narzędzie Flash Programming Tool z parametrem -closemnf. Najpierw należy upewnić się (za pomocą MEinfo), że konfiguracja Intel BG w regionie ME przewiduje wyłączenie tej technologii po zaprogramowaniu w FPF-ach.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster