Доверено зареждане на Шрьодингер. Intel Boot Guard

Доверено зареждане на Шрьодингер. Intel Boot Guard
Предлагаме отново да се спуснем на ниско ниво и да говорим за безопасността на фърмуерa на компютърни платформи, съвместими с x86. Този път основната съставка на изследването е Intel Boot Guard (да не се бърка с Intel BIOS Guard!) – хардуерно поддържана технология за доверена зареждане на BIOS, която производителят на компютърната система може постоянно да включва или изключва в етапа на производство. Рецептата за изследването е вече позната: фино нарязване на реверс-инженеринг на имплементацията на тази технология, описание на архитектурата ѝ, запълнена с недокументирани детайли, подправяне на вкус с атаки и разбъркване. Ще добавим малко огън, като разкажем как дългогодишна производствена грешка на няколко производители позволява на потенциален злонамерен субект да използва тази технология за създаване на неелиминируем (даже с програматор) скрит руткит в системата.

Статията е основана на докладите "На страже на рутките: Intel BootGuard" от конференцията ZeroNights 2016 и 29-то издание на DefCon Russia (двете презентации тук).

Фърмуер на компютърна платформа с архитектура Intel 64

Първо, нека отговорим на въпроса: какво представлява фърмуерът на съвременната компютърна платформа с архитектура Intel 64? Разбира се, UEFI BIOS. Но такъв отговор би бил неточен. Нека да погледнем в изображението, където е показан десктоп (или лаптоп) вариант на тази архитектура.

Доверено зареждане на Шрьодингер. Intel Boot Guard
Основата е комбинация от:

  • Процесор (CPU, Central Processing Unit), който, освен основните ядра, интегрира графично ядро (не във всички модели) и вградил контролер за памет (IMC, Integrated Memory Controller);
  • Чипсета (PCH, Platform Controller Hub), който съдържа различни контролери за взаимодействие с периферийни устройства и управление на подсистеми. Сред тях е известният Intel Management Engine (ME), който също има свой фърмуер (Intel ME firmware).

Лаптопите, освен споменатото по-горе, предвиждат наличие на вграден контролер (ACPI EC, Advanced Control and Power Interface Embedded Controller), който отговаря за функционирането на подсистемата за захранване, тъчпада, клавиатурата, Fn клавишите (яркост на екрана, сила на звука, подсветка на клавиатурата и т.н.) и други. И той също има свой фърмуер.

И така, комбинацията от горепосочените фърмуери представлява фърмуера на компютърната платформа (system firmware), който се съхранява в общата SPI флаш-памет. За да не се объркват потребителите на тази памет относно местоположението на файловете, съдържанието на паметта е разделено на следните региони (както е показано на изображението):

  • UEFI BIOS;
  • фърмуер ACPI EC (отделен регион се появи с микроархитектурата на процесора Skylake (2015 г.), но в реалните условия досега не сме виждали примери за неговото използване, така че фърмуерът на вградения контролер все още попада в UEFI BIOS);
  • фърмуер Intel ME;
  • конфигурация (MAC адрес и т.н.) на вградения мрежов адаптер GbE (Gigabit Ethernet);
  • флаш-дескриптори (Flash Descriptors) – основният регион на флаш-паметта, който съдържа указатели към останалите региони, а също и разрешения за достъп до тях.

Доверено зареждане на Шрьодингер. Intel Boot Guard
Разграничението на достъпа до регионите (в съответствие с определените разрешения) се извършва от майстора на шина SPI – вграден в чипсета SPI контролер, чрез който става достъпът до тази памет. Ако разрешенията са зададени на препоръчаните стойности (от съображения за безопасност) от Intel, всеки потребител на SPI флаш-паметта има пълен достъп (четене/писане) само до своя регион. Останалите региони – или са достъпни само за четене, или са недостъпни. Известен факт е, че на много системи CPU има пълен достъп до UEFI BIOS и GbE, достъп само за четене до флаш-дескрипторите, а достъпът до региона Intel ME е напълно забранен. Защо на много, а не на всички? Каквото е препоръчително, не е задължително. Повече подробности ще представим по-късно в статията.

Механизми за защита на фърмуера на компютърната платформа от модификации

Ясно е, че фърмуерът на компютърната платформа трябва да бъде защитен от потенциални компрометации, които биха могли да позволят на потенциалния злонамерен субект да се закрепи в него (да оцелее при актуализации/преинсталации на ОС), да изпълнява своя код в най-привилегированите режими и т.н. Разграниченият достъп до регионите на SPI флаш-паметта, разбира се, не е достатъчен. Затова за защита на фърмуера от модификации се прилагат различни механизми, специфични за всяка среда на изпълнение.

Така, фърмуерът Intel ME е подписан за контрол на целостта и автентичността, и се проверява от ME контролера при всяко зареждане в паметта ME UMA. Процесът на верификация вече беше разгледан в една от статиите, свързана с подсистемата Intel ME.

Фърмуерът ACPI EC обикновено се проверява само за целостност. Но тъй като този бинарен код е част от UEFI BIOS, на него почти винаги се прилагат същите механизми за защита, както и за UEFI BIOS. Нека ги разгледаме.

Тези механизми могат да бъдат разделени на две категории.

Защита от запис в региона на UEFI BIOS

  1. Физическа защита на съдържанието на SPI флаш паметта чрез джъмпер за защита от запис;
  2. Защита на проекцията на UEFI BIOS в адресното пространство на CPU чрез PRx регистрите на чипсета;
  3. Блокиране на опити за запис в региона на UEFI BIOS чрез генериране и обработка на съответното прекъсване SMI чрез настройване на битовете BIOS_WE/BLE и SMM_BWP в регистрите на чипсета;
  4. По-усъвършенстван вариант на такава защита е Intel BIOS Guard (PFAT).

В допълнение към тези механизми, доставчиците могат да разработват и прилагат свои собствени мерки за сигурност (например подписване на капсули с актуализации на UEFI BIOS).

Важно е да се отбележи, че на конкретна система (в зависимост от доставчика) могат да не бъдат приложени всички изброени механизми за защита, да не бъдат приложени изобщо или да бъдат реализирани уязвимо. Повече за тези механизми и ситуацията с тяхната реализация можете да прочетете в тази статия. На заинтересованите препоръчваме да се запознаят с целия цикъл от статии относно сигурността на UEFI BIOS от CodeRush.

Верификация на легитимността на UEFI BIOS

Когато говорим за технологии за доверено зареждане, първото нещо, което идва наум, е Secure Boot. Но архитектурно той е предназначен за проверка на автентичността на външни компоненти, спрямо UEFI BIOS (драйвери, зареждачи и т.н.), а не самия фърмуер.

Затова компанията Intel е реализирала хардуерен, недеактивируем Secure Boot (Verified Boot) в SoC с микропроцесорна архитектура Bay Trail (2012 г.), който няма нищо общо с горепосочената технология Secure Boot. По-късно (2013 г.) този механизъм беше усъвършенстван и под името Intel Boot Guard беше пуснат за десктопи с микропроцесорна архитектура Haswell.

Преди да опишем Intel Boot Guard, нека разгледаме средите на изпълнение в архитектурата Intel 64, които съвпадат с корените на доверието за тази технология за доверено зареждане.

Intel CPU

Кэп подказва, че процесорът е основната среда на изпълнение в архитектурата Intel 64. Защо той е корен на доверието? Оказва се, че това се дължи на наличието на следните елементи:

  • Микрокод ROM — нерезервирана, неперезаписваема памет за съхранение на микрокода. Счита се, че микрокодът е имплементация на командната система на процесора с най-прости инструкции. В микрокода също могат да възникнат грешки. Така че в BIOS може да се намерят бинарни файлове с актуализации на микрокода (те се прилагат по време на зареждане, тъй като ROM не може да бъде презаписан). Съдържанието на тези бинарни файлове е криптирано, което значително усложнява анализа (поради това конкретното съдържание на микрокода е известно само на разработчиците му) и е подписано за контрол на целостта и автентичността;
  • AES ключ за декриптиране на съдържанието на актуализациите на микрокода;
  • хеш на публичния ключ RSA, с който се проверява подписът на актуализациите на микрокода;
  • хеш на публичния ключ RSA, с който се проверява подписът на кодовите модули ACM (Authenticated Code Module), разработени от компания Intel, които CPU може да стартира преди изпълнението на BIOS (здравей, микрокод) или по време на работата му, при възникване на определени събития.

Intel ME

На нашия блог беше посветена цяло две статии. Напомняме, че тази изпълнима среда е базирана на вградения в чипсета микроконтролер и е най-скритата и привилегирована в системата.

Въпреки своята скритост, Intel ME също е корен на доверието, тъй като има:

  • ME ROM — нерезервирана, неперезаписваема памет (не е предвиден начин за актуализация), съдържаща стартиращ код, а също и SHA256 хеш на публичния ключ RSA, с който се проверява подписът на фърмуера на Intel ME;
  • AES ключ за съхранение на секретна информация;
  • достъп до интегрирания в чипсета набор от фюзи (FPFs, Field Programmable Fuses) за перманентно съхранение на известна информация, включително и зададена от вендора на компютърната система.

Intel Boot Guard 1.x

Небольшо предупреждение. Номерата на версиите на технологията Intel Boot Guard, с които работим в тази статия, са условни и може да нямат нищо общо с номерацията, която се прилага във вътрешната документация на компания Intel. Освен това информацията, представена тук относно имплементацията на тази технология, бе получена в ходе на реверс-инжиниринг и може да съдържа неточности в сравнение с спецификацията на Intel Boot Guard, която вероятно никога няма да бъде публикувана.

И така, Intel Boot Guard (BG) – хардуерно поддържана технология за верификация на автентичността на UEFI BIOS. Съдейки по краткото ѝ описание в книгата [Platform Embedded Security Technology Revealed, глава Boot with Integrity, or Not Boot], тя работи като верига за доверена зареждане. И първото звено в нея е зареждащият код (микрокод) в CPU, който стартира при събитие RESET (не бъркайте с RESET-вектора в BIOS!). CPU открива на SPI флаш паметта проектиран и подписан от Intel кодов модул (Intel BG startup ACM), зарежда го в кеша си, верифицира (както беше споменато по-горе, CPU има хеш на публичния ключ, с който се проверява подписът на ACM) и го стартира.

Доверено зареждане на Шрьодингер. Intel Boot Guard

Този кодов модул отговаря за верификацията на малка стартова част от UEFI BIOS – Initial Boot Block (IBB), който от своя страна съдържа функционалност за верификация на основната част на UEFI BIOS. Така че, Intel BG позволява да се уверите в автентичността на BIOS преди зареждането на ОС (която може да работи под наблюдението на технологията Secure Boot).

Технологията Intel BG предвижда два режима на работа (като единият не пречи на другия, т.е. и двата режима могат да бъдат активирани на системата, или двата могат да бъдат деактивирани).

Measured Boot

В режима Measured Boot (MB) всеки зареждащ компонент (от CPU boot ROM) "измерва" следващия, използвайки възможностите на TPM (Trusted Platform Module). За тези, които не са запознати, нека поясня.

TPM разполага с PCR-ы (Platform Configuration Registers), в които се записва резултатът от операцията по хеширане по формулата:

Доверено зареждане на Шрьодингер. Intel Boot Guard

Т.е. текущото значение на PCR зависи от предишното, като данните в регистрите се нулират само при RESET на системата.

Така че, в режим MB, в някакъв момент PCR-ите отразяват уникален (в рамките на възможностите на операцията по хеширане) идентификатор на кода или данните, които са "измервани". Значенията на PCR могат да бъдат използвани при операцията по шифроване на някои данни (TPM_Seal). След това, тяхната декодировка (TPM_Unseal) ще бъде възможна само ако значенията на PCR не са се променили в резултат на зареждането (т.е. нито един "измерван" компонент не е бил модифициран).

Verified Boot

Най-тревожното за любителите на модификацията на UEFI BIOS е режимът Verified Boot (VB), при който всеки зареждащ компонент криптографски проверява целостта и автентичността на следващия. А в случай на грешка при верификацията, се случва (едно от):

  • изключване по таймер от 1 минута до 30 минути (за да може потребителят да разбере причината, поради която компютърът му не стартира и, ако е възможно, да се опита да възстанови BIOS);
  • незабавно изключване (така че потребителят да не успее да разбере нищо и, още повече, да направи нещо);
  • продължаване на работа с невъзмутимо изражение (в случая, когато безопасността не е приоритет, защото има по-важни неща);

Изборът на действие зависи от зададената конфигурация Intel BG (а именно, от т.н. enforcement policy), която производителят на компютърната платформа постоянно записва в специално предназначено хранилище – фюзите на чипсета (FPF-ите). Повече по този въпрос ще разгледаме по-късно.

В допълнение към конфигурацията, производителят генерира два ключа RSA 2048 и създава две структури от данни (изобразени на фигурата):

  1. Манифест на коренния ключ на производителя (KEYM, OEM Root Key Manifest), в който се съдържа SVN (Security Version Number) на този манифест, SHA256 хеш на публичния ключ на следващия манифест, публичен ключ RSA (т.е. публичната част на коренния ключ на производителя) за проверка на подписа на този манифест и самият подпис;
  2. Манифест IBB (IBBM, Initial Boot Block Manifest), в който се съдържа SVN на този манифест, SHA256 хеш на IBB, публичен ключ за проверка на подписа на този манифест и самият подпис.

SHA256 хешът на публичния ключ на OEM Root Key постоянно се записва във фюзите на чипсета (FPF-ите), както и конфигурацията Intel BG. Ако конфигурацията Intel BG предвижда активиране на тази технология, то от този момент нататък само собственикът на частния ключ на OEM Root Key, т.е. производителят, може да обновява BIOS на тази система (т.е. да има възможност да преизчислява тези манифести).

Доверено зареждане на Шрьодингер. Intel Boot Guard

При поглед към картинката веднага възниква съмнение в необходимостта от такава дълга верига за проверка – можеше да се използва само един манифест. Защо да се усложнява?

Всъщност компанията Intel по този начин предоставя на производителя възможността да използва различни ключове IBB за различни линии на своите продукти и един – като коренен. Ако частният ключ на IBB (с който се подписва вторият манифест) изтече, инцидентът ще засегне само една линия продукти и само дотогава, докато производителят не генерира нова двойка и не включи преизчислените манифести в следващото обновление на BIOS.

Но ако кореновият ключ (с който се подписва първият манифест) бъде компрометиран, не може да бъде заменен, тъй като не съществуват процедури за отмяна, тъй като хешът на публичната част на този ключ е програмиран в FPF-ите веднъж завинаги.

Конфигурация на Intel Boot Guard

Сега ще разгледаме по-подробно конфигурацията на Intel BG и процеса на нейното създаване. Ако погледнете съответната вкладка в GUI на инструмента Flash Image Tool от комплекта Intel System Tool Kit (STK), можете да видите, че конфигурацията на Intel BG включва хеш на публичната част от кореновия ключ на доставчика, двойка непознати стойности и т.н. профил на Intel BG.

Доверено зареждане на Шрьодингер. Intel Boot Guard

Структурата на този профил:

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 – не прави нищо
                                              // 01b – изключване с таймер
                                              // 11b – незабавно изключване
	unsigned long : 26;
};

Всъщност, конфигурацията на Intel BG е много гъвкава. Да разгледаме, например, флага Force_Boot_Guard_ACM. Когато е деактивиран, ако модулът BG startup ACM не бъде намерен в SPI флаш паметта, няма да има доверено зареждане. Ще има недоверено.

По-горе вече споменахме, че политиката за прилагане за режим VB може да бъде настроена така, че при грешка в проверката да се случи отново недоверено зареждане.

Да се оставят такива неща на произвола на доставчиците...

GUI на инструмента предвижда следните 'готови' профили:

Номер
Режим
Описание

0
No_FVME
технологията Intel BG е изключена

1
VE
включен режим VB, изключване по таймер

2
VME
включени и двата режима (VB и MB), изключване по таймер

3
VM
включени и двата режима, без изключване на системата

4
FVE
включен режим VB, незабавно изключване

5
FVME
включени и двата режима, незабавно изключване

Както вече бе споменато, конфигурацията на Intel BG трябва да бъде записана веднъж завинаги от доставчика на системата в фюзите на чипсета (FPF-ите) – малко (по непотвърдени данни, само 256 байта) хардуерно хранилище на информация вътре в чипсета, което може да бъде програмирано извън производствените мощности на компанията Intel (затова именно Field Programmable Fuses).

То е отлично за съхранение на конфигурацията, тъй като:

  • има еднократно програмирана област за съхранение на данни (точно там, където се записва конфигурацията на Intel BG);
  • може да се чете и програмира само от Intel ME.

Следовательно, за да се зададе конфигурацията за технологията Intel BG на конкретна система, производителят по време на производството предприема следното:

  1. С помощта на утилитата Flash Image Tool (от Intel STK) се създава образ на фърмуера с зададената конфигурация Intel BG под формата на променливи в региона Intel ME (т.н. временно огледало за FPF-ите);
  2. С помощта на утилитата Flash Programming Tool (от Intel STK) този образ се записва в SPI флаш паметта на системата и се затваря т.н. manufacturing mode (при което се отправя съответната команда в Intel ME).

В резултат на тези операции, Intel ME ще запише в FPF-ите зададените стойности от огледалото за FPF-ите в ME региона, ще зададе разрешенията в SPI флаш дескрипторите на препоръчаните от Intel стойности (описани в началото на статията) и ще извърши RESET на системата.

Анализ на имплементацията на Intel Boot Guard

С цел анализ на реализацията на тази технология на конкретен пример, проверихме следните системи за наличие на следи от технологията Intel BG:

Система
Забележка

Gigabyte GA-H170-D3H
Skylake, има поддръжка

Gigabyte GA-Q170-D3H
Skylake, има поддръжка

Gigabyte GA-B150-HD3
Skylake, има поддръжка

MSI H170A Gaming Pro
Skylake, няма поддръжка

Lenovo ThinkPad 460
Skylake, има поддръжка, технологията е активирана

Lenovo Yoga 2 Pro
Haswell, няма поддръжка

Lenovo U330p
Haswell, няма поддръжка

Под "поддръжка" се разбира наличието на модула Intel BG startup ACM, споменатите по-горе манифести и съответния код в BIOS, т.е. имплементацията за анализ.

Като пример, взимаме изтегления от официалния сайт на производителя образ на SPI флеш паметта за Gigabyte GA-H170-D3H (версия F4).

Intel CPU boot ROM

На първо място, нека поговорим за действията на процесора в случай, че технологията Intel BG е активирана.

Не успяхме да намерим образци на декодирания микрокод, така че как описаните по-долу действия се реализират (в микрокода или хардуерно) – остава открит въпрос. Въпреки това, факт е, че съвременните процесори Intel "знаят" как да извършват тези действия.

След като процесорът излезе от състояние RESET (в адресното пространство на който вече е картографирано съдържанието на флаш паметта), той намира таблицата FIT (Firmware Interface Table). Намирането ѝ е лесно, указателят към нея е записан на адрес FFFF FFC0h.

Доверено зареждане на Шрьодингер. Intel Boot Guard
В разглеждания пример, на този адрес се намира стойността FFD6 9500h. Объркайки се на този адрес, процесорът вижда таблицата FIT, съдържанието на която е разделено на записи. Първият запис е заглавие на следната структура:

typedef struct FIT_HEADER
{
	char           Tag[8];     // ‘_FIT_   ’
	unsigned long  NumEntries; // including FIT header entry
	unsigned short Version;    // 1.0
	unsigned char  EntryType;  // 0
	unsigned char  Checksum;
};

Доверено зареждане на Шрьодингер. Intel Boot Guard
По неизвестна причина чексума не всегда правильно считается в этих таблицах (поле остается нулевым).

Остальные записи указывают на различные бинарники, которые необходимо распарсить/исполнить до запуска BIOS, т.е. до перехода на вектор legacy RESET (FFFF FFF0h). Структура каждой записи имеет следующий вид:

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

Доверено зареждане на Шрьодингер. Intel Boot Guard
Поле EntryType определяет тип блока, на который указывает эта запись. Нам известны несколько типов:

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

Теперь очевидно, что одна из записей указывает на местоположение бинаря Intel BG startup ACM. Заголовок этого бинаря типичен для кодовых модулей, разрабатываемых компанией Intel (ACM-ы, обновления микрокода, кодовые секции Intel ME, …).

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

Доверено зареждане на Шрьодингер. Intel Boot Guard
Процессор загружает этот бинарь в свой кэш, верифицирует и запускает.

Intel BG startup ACM

В результате анализа работы этого ACM стало понятно, что он выполняет следующие действия:

  • получает от Intel ME конфигурацию Intel BG, записанную в фьюзы чипсета (FPF-ы);
  • находит манифесты KEYM и IBBM, верифицирует их.

Для нахождения этих манифестов ACM также использует таблицу FIT, в которой отведено два типа записей для указания на данные структуры (см. FIT_ENTRY_TYPES выше).

Остановимся подробнее на манифестах. В структуре первого манифеста мы видим несколько неясных констант, хеш публичного ключа из второго манифеста и публичный ключ OEM Root Key с подписью в виде вложенной структуры:

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];
};

Доверено зареждане на Шрьодингер. Intel Boot Guard
За верификация на публичния ключ OEM Root Key се използва SHA256 хеш от фюзовете, който е получен от Intel ME.

Преминаваме към втория манифест. Той се състои от три структури:

typedef struct IBB_MANIFEST
{
	ACBP Acbp;         // Boot policies
	IBBS Ibbs;         // IBB description
	IBB_DESCRIPTORS[];
	PMSG Pmsg;         // IBBM signature
};

В първата – определени константи:

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
};

Във втората структура се съдържа SHA256 хеш на IBB и брой на дескрипторите, които описват съдържанието на IBB (т.е. от което се изчислява хешът):

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 на IBB
	unsigned char  NumIbbDescriptors;
};

Дескрипторите на IBB следват след тази структура, един след друг. Съдържанието им има следния формат:

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

Всичко е просто: всеки дескриптор съдържа адрес/размер на част от IBB. Така че, конкатенацията на блоковете, на които сочат тези дескриптори (в реда, в който се намират самите дескриптори), образува IBB. И, като правило, IBB е сбор от всички модули на фазите SEC и PEI.

Вторият манифест завършва със структура, съдържаща публичния ключ на IBB (който се верифицира чрез SHA256 хеш от първия манифест) и подписа на този манифест:

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

Доверено зареждане на Шрьодингер. Intel Boot Guard
Така, още преди началото на изпълнението на UEFI BIOS, процесорът стартира ACM, който проверява автентичността на съдържанието на разделите с кодовете SEC и PEI. След това процесорът излиза от ACM, преминава по RESET-вектора и започва да изпълнява BIOS.

Провереният PEI раздел трябва да съдържа модул, който да провери останалата част от BIOS (DXE код). Този модул е разработен от IBV (Independent BIOS Vendor) или самия производител на системата. Тъй като в нашето разположение имаме само системи Lenovo и Gigabyte с поддръжка на Intel BG, ще разгледаме кода, извлечен от тези системи.

UEFI BIOS модул LenovoVerifiedBootPei

В случая с Lenovo, това е модулът LenovoVerifiedBootPei {B9F2AC77-54C7-4075-B42E-C36325A9468D}, разработен от компанията Lenovo.

Неговата работа се състои в търсене (по GUID) на хеш-таблица за DXE и верификация на DXE.

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

Хеш таблицата {389CC6F2-1EA8-467B-AB8A-78E769AE2A15} има следния формат:

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 модул BootGuardPei

В случая с Gigabyte, това е модулът BootGuardPei {B41956E1-7CA2-42DB-9562-168389F0F066}, разработен от AMI, следователно, той присъства във всеки AMI BIOS с поддръжка на Intel BG.

Алгоритъмът на работа му е малко по-различен, но по същество е същият:

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;
}

Хеш таблицата {389CC6F2-1EA8-467B-AB8A-78E769AE2A15}, която той търси, има следния формат:

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

Нека накратко споменем още една реализация на Intel Boot Guard, която беше намерена в по-нова система на база Intel SoC с микроархитектура Apollo Lake — ASRock J4205-IT.

Въпреки че тази версия ще се прилага само в SoC-ите (новите системи с микроархитектура на процесорите Kaby Lake все още използват Intel Boot Guard 1.x), тя представлява голям интерес за изучаването на новия вариант на архитектурата за платформите на Intel SoC, в която има значителни промени, като например:

  • регионите на BIOS и Intel ME (по-скоро Intel TXE, според терминологията за Intel SoC) сега са един регион IFWI;
  • макар че на платформата беше активиран Intel BG, такива структури, като FIT, KEYM, IBBM не бяха намерени в флаш паметта;
  • освен ядрата TXE и ISH (x86), в чипсета беше добавено трето ядро (между другото отново ARC) – PMC (Power Management Controller), отговорно за функционалността на системата за захранване и мониторинг на производителността.

Доверено зареждане на Шрьодингер. Intel Boot Guard
Съдържанието на новия регион IFWI представлява набор от следните модули:

Сместа
Име
Описание

0000 2000h
SMIP
някаква конфигурация на платформата, подписана от доставчика

0000 6000h
RBEP
кодова част от фърмуера Intel TXE, x86, подписана от Intel

0001 0000h
PMCP
кодова част от фърмуера Intel PMC, ARC, подписана от Intel

0002 0000h
FTPR
кодова част от фърмуера Intel TXE, x86, подписана от Intel

0007 B000h
UCOD
обновления на микрокода за CPU, подписани от Intel

0008 0000h
IBBP
UEFI BIOS, фази SEC/PEI, x86, подписана от доставчика

0021 8000h
ISHC
кодова част от фърмуера Intel ISH, x86, подписана от доставчика

0025 8000h
NFTP
кодова част от фърмуера Intel TXE, x86, подписана от Intel

0036 1000h
IUNP
неизвестно

0038 1000h
OBBP
UEFI BIOS, фаза DXE, x86, не подписана

По време на анализа на фърмуера TXE стана очевидно, че след RESET-а TXE държи процесора в това състояние, докато не подготви основното съдържание на адресното пространство за CPU (FIT, ACM, RESET-вектор…). Освен това TXE разполага тези данни в SRAM, след което временно предоставя достъп на процесора и го "освобождава" от RESET-а.

На страже на руткитовете

А сега да преминем към "горещото". Един ден открихме, че многобройни системи имат разрешения за достъп до регионите на SPI флаш паметта, записани в SPI флаш дескрипторите, така че всички потребители на тази памет могат да записват и четат всеки регион. Т.е. никак.

След проверка с помощта на утилитата MEinfo (от Intel STK) видяхме, че производственият режим на тези системи не е затворен, следователно, фюзите на чипсета (FPF-ите) остават в неопределено състояние. Да, Intel BG в такива случаи нито е включен, нито е изключен.

Става въпрос за следните системи (по отношение на Intel BG и това, което ще се изложи по-долу в статията, ще говорим за системи с процесорна микроархитектура Haswell и нагоре):

  • всички продукти на Gigabyte;
  • всички продукти на MSI;
  • 21 модел лаптопи Lenovo и 4 модела сървъри Lenovo.

Разбира се, съобщихме за находката на тези доставчици, както и на компанията Intel.

Адекватна реакция последва само от Lenovo, които признат проблема и издадоха пач.

Gigabyte изглежда приемат информацията за уязвимостта, но никога не коментираха.

Комуникацията с MSI изобщо не се е задържало на нашето искане да изпратим своя публичен PGP-ключ (за да им изпратим security advisory в encrypted вид). Те заявиха, че „са производители на хардуер и PGP-ключове не произвеждат“.

Но нека да преминем към същността. Тъй като фюзите остават в неопределено състояние, потребителят (или злонамерен достъп) може да ги програмира самостоятелно (най-сложното е да намери Intel STK). За целта е необходимо да се изпълнят следните стъпки.

1. Да се стартира в ОС Windows (въобще, описаните по-долу действия могат да се извършат и от Linux, ако се разработи аналог на Intel STK за нужната ОС). Използвайки инструмента MEinfo, да се уверите, че фюзите на съответната система не са програмирани.

Доверено зареждане на Шрьодингер. Intel Boot Guard
2. Да се счете съдържанието на флаш паметта с помощта на Flash Programming Tool.

Доверено зареждане на Шрьодингер. Intel Boot Guard
3. Да се отвори прочетеният образ с помощта на който и да е инструмент за редактиране на UEFI BIOS, да се направят необходимите промени (например, да се внедри руткит), да се създадат/редактират наличните структури KEYM и IBBM в ME региона.

Доверено зареждане на Шрьодингер. Intel Boot Guard
Доверено зареждане на Шрьодингер. Intel Boot Guard
На картинката е отбелязан публичният ключ RSA, хешът на който ще бъде програмиран във фюзите на чипсета заедно с останалата конфигурация Intel BG.

4. С помощта на Flash Image Tool да се събере нов образ на фърмуера (заяви конфигурацията Intel BG).

Доверено зареждане на Шрьодингер. Intel Boot Guard
5. Да се запише новият образ на флаш паметта с помощта на Flash Programming Tool, да се уверите с помощта на MEinfo, че ME регионът сега съдържа конфигурацията Intel BG.

Доверено зареждане на Шрьодингер. Intel Boot Guard
6. С помощта на Flash Programming Tool да се затвори режимът manufacturing mode.

Доверено зареждане на Шрьодингер. Intel Boot Guard
7. Системата ще се перезареди, след което с помощта на MEinfo можете да се уверите, че FPF-ите сега са програмирани.

Доверено зареждане на Шрьодингер. Intel Boot Guard
Тези действия за винаги включат Intel BG на тази система. Отмяната на действие ще бъде невъзможна, което означава:

  • да актуализира UEFI BIOS на тази система може само притежателят на частния ключ на корена (т.е. този, който е включил Intel BG);
  • ако върнете оригиналната фърмуерна версия на системата, например, с помощта на програматор, тя дори няма да се включи (резултат от enforcement policy в случай на грешка при верификация);
  • за да се отървете от такъв UEFI BIOS, е необходимо да смените чипсета с програмираните FPF-ите на „чист“ (т.е. да се прелепи чипсета, ако имате достъп до инфрачервена паялна станция на цена на автомобил, или просто да смените дънната платка).

За да разберем какво може да причини такъв руткит, е нужно да оценим какво позволява изпълнението на собствен код в средата на UEFI BIOS. Например, в най-привилегирования режим на процесора – SMM. Такъв руткит може да има следните свойства:

  • да се изпълнява паралелно с ОС (може да се настрои да реагира на генерирането на SMI прекъсване, което ще се задейства по таймер);
  • да има всички предимства от наличието в SMM режим (пълен достъп до съдържанието на оперативната памет и хардуерните ресурси, скритост от ОС);
  • програмният код на руткита може да бъде в криптиран вид и да се дешифрира при стартиране в SMM режим. Като ключ за криптиране могат да се използват всякакви данни, достъпни само в SMM режим. Например, хеш от набор адреси в SMRAM. За да получим този ключ, ще е нужно да влезем в SMM. А това може да се направи по два начина. Да намерим RCE в кода на SMM и да я експлоатираме, или да добавим собствен SMM модул в BIOS, което е невъзможно, тъй като сме включили Boot Guard.

Така тази уязвимост позволява на нападателя:

  • да създаде в системата скрит, неизтриваем руткит с неизвестно предназначение;
  • да изпълнява собствен код на едно от ядрата на чипсета в Intel SoC, а именно, на Intel ISH (внимателно разгледайте изображението).

Доверено зареждане на Шрьодингер. Intel Boot Guard
Доверено зареждане на Шрьодингер. Intel Boot Guard
Въпреки че възможностите на подсистемата Intel ISH все още не са изучени, тя представлява интересен вектор за атака срещу Intel ME.

Изводи

  1. Изследването позволи да се получи техническо описание на работата на технологията Intel Boot Guard. Няма много тайни в Intel-овския модел за сигурност чрез неяснота.
  2. Представен е сценарий за атака, позволяващ да се създаде в системата неизтриваем руткит.
  3. Видяхме, че съвременните процесори Intel са способни да изпълняват много проприетарен код още преди да започне работата на BIOS.
  4. Платформите с архитектура Intel 64 стават все по-малко пригодни за стартиране на свободен софтуер: хардуерната верификация, нарастващият брой проприетарни технологии и подсистеми (три ядра в чипсета SoC: x86 ME, x86 ISH и ARC PMC).

Mitigations

На вендорите, които умишлено оставят производствения режим отворен, трябва да се нареди да го затварят. Засега само затварят очите и новите системи Kaby Lake го показват.

Потребителите могат сами да деактивират Intel BG на своите системи (които са податливи на описаната уязвимост), като стартират утилитата Flash Programming Tool с параметъра -closemnf. Преди това е необходимо да се уверят (чрез MEinfo), че конфигурацията на Intel BG в региона ME предвижда именно деактивацията на тази технология след програмирането в FPF-ите.

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster