Безопасность Встроенных Устройств: Защита Систем Linux с Помощью Современных Инструментов

CNXSoft: Это гостевой пост Эрика Вириха, старшего инженера в RISCstar Solutions , демонстрирующий практическую реализацию безопасности для встроенных устройств с использованием стандартных инструментов Linux, таких как dm-verity и TPM 2.0. Рассматриваются модели угроз, безопасность файловых систем и TPM-шифрование с рабочими примерами кода.

В настоящее время невозможно (и справедливо) вывести встроенное устройство на рынок без комплексных мер безопасности. Большинство новых устройств хранят конфиденциальные данные, утечку которых в тёмные уголки интернета недопустима. Также важно предотвратить превращение устройства в часть ботнета.

Linux предоставляет обширный набор инструментов для обеспечения безопасности. Исторически не хватало простого, готового способа интегрировать эти инструменты в конфигурацию, безопасную по умолчанию. В этой статье показано, как современные инструменты упрощают развёртывание, обеспечивая при этом высокий уровень защиты.

Embedded Device Security Protecting data on Linux systems

Область безопасности встроенных устройств

Говоря о безопасности встроенных систем, важно определить, от чего именно мы защищаемся. Невозможно создать универсальную модель угроз для всех устройств, но можно выделить типичные требования.

Обычно в системе присутствуют два типа данных:

  • Статичные бинарные файлы и библиотеки, формирующие ОС
  • Изменяемые конфигурации и пользовательские данные, обновляемые в ходе работы

Для ОС необходимо обеспечить целостность заводского образа. Это защищает от атак на цепочку поставок и загрузки несанкционированного ПО. Однако в рамках этого поста бинарные файлы ОС не считаются конфиденциальными.

Динамические конфигурации и пользовательские данные считаются конфиденциальными. Они генерируются только во время работы устройства, не прошиваются на заводе и не заменяются при обновлениях. Эти данные необходимо защитить от считывания на украденных устройствах.

Существует больше вариантов и сценариев, актуальных для конкретных устройств. Но указанного достаточно для построения основы!

Конфигурация файловой системы

Звучит как план? Перейдём к реализации…

Linux позволяет гибко настраивать файловые системы. Для типичного встроенного устройства обычно требуется возможность записи в некоторые каталоги /etc, /var и /home , тогда как остальная часть может оставаться неизменяемым образом.

Корневую файловую систему (/) можно сделать неизменяемой, а записываемые разделы смонтировать отдельно. Однако управление множеством исключений сложно. Вместо этого есть более простой вариант: сделать / доступной для записи и смонтировать раздел /usr только для чтения. /usr содержит все системные файлы. Они неизменяемы, а остальные файлы могут быть автоматически созданы при первой загрузке. Это позволяет исключить раздел / из заводского образа и поставлять только /usr .

Сначала такой подход может показаться неочевидным. Но он значительно упрощает управление записываемым разделом. Основное преимущество — работа всего с двумя разделами без символьных ссылок между ними. Также чётче разделяются требования: один раздел требует проверки целостности, другой — шифрования.

Управление ключами становится проще (и безопаснее), если создавать их на устройстве при первой загрузке. Внедрение уникального для устройства шифрования при развёртывании с единого заводского образа упрощается созданием зашифрованных разделов на устройстве. В противном случае потребуется сложное перешифрование разделов. Ещё один плюс — упрощение механизма сброса к заводским настройкам: достаточно удалить зашифрованные разделы и ключи, затем пересоздать их заново.

Внимательный читатель спросит, как система переживёт первую загрузку без файловой системы / . Linux нуждается в ней для перехода в пользовательское пространство. Решение — initrd: минимальная файловая система. Не волнуйтесь, её настройка проще, чем кажется.

Защита ОС встроенного устройства

Работа с неизменяемой файловой системой упрощает проверку целостности. Весь раздел можно защитить, поместив его в dm-verity . Это создаёт хеш-дерево над блоками файловой системы, сводящееся к единому корневому хешу для проверки целостности всего дерева и файловой системы.

Теперь нужно подписать корневой хеш, подтверждая его происхождение из доверенного процесса сборки. Здесь обычно начинается усложнение. Один вариант — внедрить хеш в командную строку ядра, добавив usrhash=<корневой_хеш>, который будет подписан вместе с другими артефактами загрузки. Это кажется простым, но усложняет сборку: теперь раздел /usr нужно собрать до внедрения usrhash в командную строку ядра — или, скорее, в Unified Kernel Image (UKI) . Это создаёт зависимость раздела /boot от сборки /usr или требует патчинга собранного образа для добавления опции usrhash= .

Альтернатива — хранение метаданных с хешем и подписью в другом месте. Существуют различные методы, но недавно группа сопровождающих systemd и дистрибутивов Linux стандартизировала этот процесс. uapi-group теперь предоставляет стандарт для безопасного автоматического обнаружения корневого хеша и его подписи. Лучше всего: нам не нужно настраивать dm-verity вручную. systemd-repart поддерживает это и автоматизирует процесс. Systemd также включает systemd-gpt-auto-generator для автоматического обнаружения и монтирования.

Побочная тема: systemd-repart

systemd-repart в своей основе выполняет именно то, что предполагает название: позволяет переразбивать диск на основе простых конфигурационных файлов.

Приведённая ниже конфигурация:

# 00-esp.conf
[Partition]
Type=esp

# 20-root.conf
[Partition]
Type=root
Weight=1000

# 30-home.conf
[Partition]
Type=home
Format=btrfs
SizeMinBytes=1G
Weight=2000

Он сравнит существующие разделы на загруженном диске с конфигурацией и создаст недостающие. формат конфигурации прост , но мощный.

Но это не самая сильная сторона systemd-repart. Он также может создавать образы дисков с нуля!

Пример:

# 00-esp.conf
[Partition]
Type=esp
Format=vfat
CopyFiles=/boot:/
CopyFiles=/efi:/
SizeMinBytes=512M
SizeMaxBytes=512M

# mkosi.repart/10-usr.conf
[Partition]
Type=usr
CopyFiles=/usr:/
Verity=data
VerityMatchKey=usr
Minimize=guess

# mkosi.repart/20-usr-verity.conf
[Partition]
Type=usr-verity
Verity=hash
VerityMatchKey=usr
Minimize=best

# mkosi.repart/30-usr-verity-sig.conf
[Partition]
Type=usr-verity-sig
Verity=signature
VerityMatchKey=usr
Minimize=best

С этой конфигурацией мы можем вызвать:

systemd-repart \
        --root=”/path/to/our/prepared/root/filesystem” \
        --empty=create --size=auto --offline=yes \
        --private-key=<db.key> \
        --certificate=<db.crt> \
        output.img

Он обработает всю настройку dm-verity, подписание и назначит известные UUID разделов GPT, которые systemd-gpt-auto-generator может обнаружить для автоматического монтирования.

systemd repart
Архитектура безопасности встроенного устройства, отображающая зашифрованные разделы и процесс загрузки. Мы упаковываем rootfs в образ, содержащий EFI и три раздела dm-verity. Затем при загрузке снова запускаем systemd-repart, который добавит rootfs – Диаграмма создана в Mermaid Live Editor

Таким образом, мы запишем /usr в заводской образ, а затем используем systemd-repart на устройстве для заполнения оставшихся частей.

Защита перезаписываемых данных в безопасности встроенных устройств

Разобравшись со статической частью, рассмотрим динамический раздел / . Необходима защита от считывания данных на украденных устройствах, что требует применения шифрования.

Запрос пин-кода у пользователя – простое решение, но непрактичное для headless-устройств. Вместо этого требуется безопасный механизм выдачи ключевых материалов только при нахождении системы в чётко определённом состоянии. Различные производители чипов давно предоставляют такие механизмы, но их безопасная реализация сложна и часто требует подписания NDA для доступа к руководствам.

К счастью, существует стандартное решение: Trusted Platform Modules (TPM). Это скорее API, чем конкретное аппаратное решение. TPM могут реализовываться как прошивка в изолированных средах основного процессора. На встроенных устройствах с полным контролем над прошивкой, TPM в виде прошивки обеспечивают стандартное решение без аппаратного TPM.

Детали стандарта TPM 2.0 выходят за рамки этой статьи. Ключевое – механизм привязки ключей к конкретным состояниям системы, делающий их доступными только в этих состояниях. TPM и UEFI совместно используют регистры для измерения состояний прошивки. uapi-group определяет список регистров и их распределение , релевантных для типичных Linux-систем.

В рамках статьи рассмотрим регистр «PCR #7», накапливающий состояния, влияющие на безопасную загрузку. Он позволяет привязываться к ключам и подписям, подтверждающим компоненты загрузки, раскрывая ключ только после успешной проверки цепочки. Это защищает ключи шифрования, если TPM недоступен для чтения после безопасной загрузки. Для TPM в виде прошивки ключи безопасны при надёжном механизме безопасной загрузки.

Как настроить это? Просто: используйте systemd-repart!

[Partition]
Type=root
Encrypt=tpm2

systemd-repart автоматически создаст зашифрованный раздел, зарегистрирует его в TPM и создаст внутри файловую систему. Файловая система получит правильный UUID раздела для автоматического обнаружения initrd на основе systemd.

Собираем всё вместе

Объединим компоненты. Для сборки заводского образа используем mkosi , который хорошо интегрируется с инструментами systemd и упрощает создание.

Простая конфигурация для построения пользовательского образа на основе пакетов Fedora:

[Distribution]
Distribution=fedora
Architecture=arm64

[Content]
Packages=systemd-boot,kernel-core
InitrdPackages=systemd-repart

Bootable=yes

KernelCommandLine=
    # Only allow verity+signed /usr and encrypted auto-mounts
    systemd.image_policy=usr=verity+signed:root=encrypted
    # disable emergency shells
    rd.systemd.mask=emergency.service systemd.mask=emergency.service
    rd.systemd.mask=rescue.service systemd.mask=rescue.service

# INSECURE: Enable password less root for testing :)
RootPassword=hashed:
Autologin=yes

[Validation]
SecureBoot=yes
Verity=yes
VerityKey=mkosi.key
VerityCertificate=mkosi.crt

[Runtime]
RuntimeSize=2G

Конфигурацию разделов поместим в mkosi.repart/ (определит разметку заводского образа). Подойдёт вариант из предыдущего раздела.

Конфигурацию разделов для времени выполнения поместим в mkosi.extra (будет добавлена в образ):

==> mkosi.extra/usr/lib/repart.d/00-esp.conf <==
[Partition]
Type=esp

==> mkosi.extra/usr/lib/repart.d/10-usr.conf <==
[Partition]
Type=usr

==> mkosi.extra/usr/lib/repart.d/20-usr-verity.conf <==
[Partition]
Type=usr-verity

==> mkosi.extra/usr/lib/repart.d/30-usr-verity.conf <==
[Partition]
Type=usr-verity-sig

==> mkosi.extra/usr/lib/repart.d/40-root.conf <==
[Partition]
Type=root
Encrypt=tpm2

==> mkosi.extra/usr/lib/repart.d/00-esp.conf <==
[Partition]
Type=esp

==> mkosi.extra/usr/lib/repart.d/10-usr.conf <==
[Partition]
Type=usr

==> mkosi.extra/usr/lib/repart.d/20-usr-verity.conf <==
[Partition]
Type=usr-verity

==> mkosi.extra/usr/lib/repart.d/30-usr-verity.conf <==
[Partition]
Type=usr-verity-sig

==> mkosi.extra/usr/lib/repart.d/40-root.conf <==
[Partition]
Type=root
Encrypt=tpm2

Сборка и загрузка системы:

mkosi build && mkosi vm

Пример конфигурации доступен в репозитории: https://github.com/riscstar/blogpost-secure-boot-userspace

Итоги

linux embedded system security workflow

Прошивка загружает Unified Kernel Image, который запускает initrd. При первой загрузке initrd создаёт rootfs через вызов systemd-repart.Статья демонстрирует, что безопасность встроенных Linux-систем может быть простой. Современные готовые компоненты обеспечивают уровень защиты выше, чем 90% существующих решений.

Безопасность встроенных устройств всегда требует специфичного анализа. Эта публикация даёт основу для создания зашифрованной корневой ФС с низкой сложностью реализации. Однако важно отметить ограничения: не рассмотрены продвинутые методы сужения раскрытия ключей до initrd и защита от отката, предотвращающая загрузку уязвимых подписанных ядер для доступа к конфиденциальным данным.

В демонстрации использован простой образ mkosi . Те же механизмы применимы к образам, собранным через Yocto. Обеспечивайте безопасность ваших систем!

Выражаем свою благодарность источнику, с которого взята и переведена статья, сайту cnx-software.com.

Оригинал статьи вы можете прочитать здесь.

5 1 vote
Article Rating
Подписаться
Уведомление о
guest

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

0 Комментарий
Oldest
Newest Most Voted
Inline Feedbacks
View all comments