Эксплуатация подписанных загрузчиков для обхода защиты UEFI Secure Boot

Введение

Прошивки современных материнских плат компьютера работают по спецификации UEFI, и с 2013 года поддерживают технологию проверки подлинности загружаемых программ и драйверов Secure Boot, призванную защитить компьютер от буткитов. Secure Boot блокирует выполнение неподписанного или недоверенного программного кода: .efi-файлов программ и загрузчиков операционных систем, прошивок дополнительного оборудования (OPROM видеокарт, сетевых адаптеров).
Secure Boot можно отключить на любой магазинной материнской плате, но обязательное требование для изменения его настроек — физическое присутствие за компьютером. Необходимо зайти в настройки UEFI при загрузке компьютера, и только тогда получится отключить технологию или изменить её настройки.

Большинство материнских плат поставляется только с ключами Microsoft в качестве доверенных, из-за чего создатели загрузочного ПО вынуждены обращаться в Microsoft за подписью загрузчиков, проходить процедуру аудита, и обосновывать необходимость глобальной подписи их файла, если они хотят, чтобы диск или флешка запускались без необходимости отключения Secure Boot или добавления их ключа вручную на каждом компьютере.
Подписывать загрузчики у Microsoft приходится разработчикам дистрибутивов Linux, гипервизоров, загрузочных дисков антивирусов и программ для восстановления компьютера.

Мне хотелось сделать загрузочную флешку с различным ПО для восстановления компьютера, которая бы грузилась без отключения Secure Boot. Посмотрим, как это можно реализовать.

Подписанные загрузчики загрузчиков

Итак, чтобы загрузить Linux при включенном Secure Boot, нужен подписанный загрузчик. Microsoft запретила подписывать ПО, лицензированное под GPLv3, из-за запрета тивоизации правилами лицензии, поэтому GRUB подписать не получится.
В ответ на это, Linux Foundation выпустили PreLoader, а Мэтью Гарретт написал shim — маленькие начальные загрузчики, проверяющие подпись или хеш следующего загружаемого файла. PreLoader и shim не используют сертификаты UEFI db, а содержат базу разрешенных хешей (PreLoader) или сертификатов (shim) внутри себя.
Обе программы, помимо автоматической загрузки доверенных файлов, позволяют загружать и любые ранее недоверенные файлы в режиме Secure Boot, но требуют физического присутствия пользователя: при первом запуске необходимо выбрать добавляемый сертификат или файл для хеширования в графическом интерфейсе, после чего данные заносятся в специальную переменную NVRAM материнской платы, которая недоступна для изменения из загруженной операционной системы. Файлы становятся доверенными только для этих пред-загрузчиков, а не для Secure Boot вообще, и запустить их без PreLoader/shim всё равно не получится.

Действия, необходимые для запуска недоверенной программы через shim.
Действия, необходимые при первом запуске недоверенной программы через shim.

Все современные популярные дистрибутивы Linux используют shim, из-за поддержки сертификатов, которая позволяет легко обновлять следующий загрузчик без необходимости взаимодействия с пользователем. Как правило, shim используется для запуска GRUB2 — наиболее популярного бутлоадера в Linux.

GRUB2

Чтобы злоумышленники втихую не наделали делов с помощью подписанного загрузчика какого-либо дистрибутива, Red Hat сделал патчи для GRUB2, блокирующие «опасные» функции при включенном Secure Boot: insmod/rmmod, appleloader, linux (заменён linuxefi), multiboot, xnu, memrw, iorw. К модулю chainloader, загружающему произвольные .efi-файлы, дописали собственный загрузчик .efi (PE), без использования команд UEFI LoadImage/StartImage, а также код валидации загружаемых файлов через shim, чтобы сохранялась возможность загрузки файлов, доверенных для shim, но не доверенных с точки зрения UEFI. Почему сделали именно так — непонятно; UEFI позволяет переопределять (хукать) функции проверки загружаемых образов, именно так работает PreLoader, да и в самом shim такая функция имеется, но по умолчанию отключена.

Так или иначе, воспользоваться подписанным GRUB из какого-то дистрибутива Linux не получится. Для создания универсальной загрузочной флешки, которая бы не требовала добавление ключей каждого загружаемого файла в доверенные, есть два пути:

  • Использование модифицированного GRUB, загружающего EFI-файлы своими силами, без проверки цифровой подписи, и без блокирования модулей;
  • Использование собственного пред-загрузчика (второго), переопределяющего функции проверки цифровой подписи UEFI (EFI_SECURITY_ARCH_PROTOCOL.FileAuthenticationState, EFI_SECURITY2_ARCH_PROTOCOL.FileAuthentication)


Второй вариант предпочтительней — загруженные недоверенные программы тоже смогут загружать недоверенные программы (например, можно загружать файлы через UEFI Shell), а в первом варианте загружать всё может только сам GRUB. Модифицируем PreLoader, убрав из него лишний код и разрешив запуск любых файлов.

Итого, архитектура флешки получилась следующая:

   ______            ______                ______
  ╱│     │          ╱│     │              ╱│     │
 /_│     │    →    /_│     │      →      /_│     │
 │       │    →    │       │      →      │       │
 │  EFI  │    →    │  EFI  │      →      │  EFI  │
 │_______│         │_______│             │_______│

BOOTX64.efi        grubx64.efi        grubx64_real.efi

  (shim)      (FileAuthentication         (GRUB2)
                override)

    ↓↓↓                ↑
                       ↑
   ______              ↑
  ╱│     │             ║
 /_│     │             ║
 │       │  ═══════════╝
 │  EFI  │
 │_______│

MokManager.efi

(Key enrolling
 tool)

Так появился Super UEFIinSecureBoot Disk.

Super UEFIinSecureBoot Disk — образ диска с загрузчиком GRUB2, предназначенным для удобного запуска неподписанных efi-программ и операционных систем в режиме UEFI Secure Boot.

Диск можно использовать в качестве основы для создания USB-накопителя с утилитами восстановления компьютера, для запуска различных Live-дистрибутивов Linux и среды WinPE, загрузки по сети, без отключения Secure Boot в настройках материнской платы, что может быть удобно при обслуживании чужих компьютеров или корпоративных ноутбуков, например, при установленном пароле на изменение настроек UEFI.

Образ состоит из трех компонентов: предзагрузчика shim из Fedora (подписан ключом Microsoft, предустановленным в подавляющее большинство материнских плат и ноутбуков), модифицированного предзагрузчика PreLoader от Linux Foundation (для отключения проверки подписи при загрузке .efi-файлов), и модифицированного загрузчика GRUB2.

Во время первой загрузки диска на компьютере с Secure Boot необходимо выбрать сертификат через меню MokManager (запускается автоматически), после чего загрузчик будет работать так, словно Secure Boot выключен: GRUB загружает любой неподписанный .efi-файл или Linux-ядро, загруженные EFI-программы могут запускать другие программы и драйверы с отсутствующей или недоверенной подписью.

Для демонстрации работоспособности, в образе присутствует Super Grub Disk (скрипты для поиска и загрузки установленных операционных систем, даже если их загрузчик поврежден), GRUB Live ISO Multiboot (скрипты для удобной загрузки Linux LiveCD прямо из ISO, без предварительной распаковки и обработки), One File Linux (ядро и initrd в одном файле, для восстановления системы), и несколько UEFI-утилит.

Диск совместим с UEFI без Secure Boot, а также со старыми компьютерами с BIOS.

Подписанные загрузчики

Мне было интересно, можно ли как-то обойти необходимость добавления ключа через shim при первом запуске. Может, есть какие-то подписанные загрузчики, которые позволяют делать больше, чем рассчитывали авторы?
Как оказалось — такие загрузчики есть. Один из них используется в Kaspersky Rescue Disk 18 — загрузочном диске с антивирусным ПО. GRUB с диска позволяет загружать модули (команда insmod), а модули в GRUB — обычный исполняемый код. Пред-загрузчик у диска собственный.

Разумеется, просто так GRUB из диска не загрузит недоверенный код. Необходимо модифицировать модуль chainloader, чтобы GRUB не использовал функции UEFI LoadImage/StartImage, а самостоятельно загружал .efi-файл в память, выполнял релокацию, находил точку входа и переходил по ней. К счастью, почти весь необходимый код есть в репозитории GRUB’а с поддержкой Secure Boot от Red Hat, единственная проблема: код парсинга заголовка PE отсутствует, заголовок парсит и возвращает shim, в ответ на вызов функции через специальный протокол. Это легко исправить, портировав соответствующий код из shim или PreLoader в GRUB.

Так появился Silent UEFIinSecureBoot Disk. Получившаяся архитектура диска выглядит следующим образом:

   ______            ______                ______
  ╱│     │          ╱│     │              ╱│     │
 /_│     │         /_│     │      →      /_│     │
 │       │         │       │      →      │       │
 │  EFI  │         │  EFI  │      →      │  EFI  │
 │_______│         │_______│             │_______│

BOOTX64.efi        grubx64.efi        grubx64_real.efi

(Kaspersky     (FileAuthentication         (GRUB2)
  Loader)        override)

    ↓↓↓                ↑
                       ↑
   ______              ↑
  ╱│     │             ║
 /_│     │             ║
 │       │  ═══════════╝
 │  EFI  │
 │_______│

 fde_ld.efi + custom chain.mod

(Kaspersky GRUB2)

Заключение

В этой статье мы выяснили, что существуют недостаточно надежные загрузчики, подписанные ключом Microsoft, разрешающим работу в режиме Secure Boot.
С помощью подписанных файлов Kaspersky Rescue Disk мы добились «тихой» загрузки любых недоверенных .efi-файлов при включенном Secure Boot, без необходимости добавления сертификата в UEFI db или shim MOK.
Эти файлы можно использовать как для добрых дел (для загрузки с USB-флешек), так и для злых (для установки буткитов без ведома владельца компьютера).
Предполагаю, что сертификат Касперского долго не проживет, и его добавят в глобальный список отозванных сертификатов UEFI, который установят на компьютеры с Windows 10 через Windows Update, что нарушит загрузку Kaspersky Rescue Disk 18 и Silent UEFIinSecureBoot Disk. Посмотрим, как скоро это произойдет.

Скачать Super UEFIinSecureBoot Disk: https://github.com/ValdikSS/Super-UEFIinSecureBoot-Disk
Скачать Silent UEFIinSecureBoot Disk в сети ZeroNet Git Center: http://127.0.0.1:43110/1KVD7PxZVke1iq4DKb4LNwuiHS4UzEAdAv/

Про ZeroNet
ZeroNet — очень мощная система создания децентрализованных распределенных динамических веб-сайтов и сервисов. При посещении какого-либо ресурса, пользователь начинает его скачивать и раздавать, как в BitTorrent. При этом, возможно создание полноценных ресурсов: блогов с комментариями, форумов, видеохостингов, wiki-сайтов, чатов, email, git.
ZeroNet разделяет понятия кода и данных сайта: пользовательские данные хранятся в .json-файлах, а при синхронизации импортируются в sqlite-базу данных сайта со стандартизированной схемой, что позволяет делать умопомрачительные вещи: локальный поиск текста по всем когда либо открытым сайтам за миллисекунды, автоматический real-time аналог RSS для всех сайтов разом.
Стандартизированная система аутентификации и авторизации (похожа на OAuth), поддержка работы за NAT и через Tor.
ZeroNet очень быстро работает, дружелюбен к пользователю, имеет современный интерфейс и мелкие, но очень удобные фишки, вроде глобального переключения дневной/ночной темы на сайтах.

Я считаю ZeroNet очень недооцененной системой, и намеренно публикую Silent-версию только в ZeroNet Git, для привлечения новых пользователей.

© Habrahabr.ru