hasher: технология безопасной сборки дистрибутива
Abstract:
Рассматривается задача безопасной воспроизводимой сборки дистрибутива,
изучаются требования, накладываемые этой задачей на архитектуру системы
сборки, рассматривается архитектура hasher'а и существенные моменты
её реализации. Приводятся примеры производных решений на базе hasher'а.
Давным-давно, когда дистрибутивы операционных систем помещались
на один компакт-диск вместе с исходным кодом, а создавали их узкие
группы специалистов, никакой сборочной технологии по существу не было,
а отдельные элементы дистрибутива собирались прямо в хост-системе,
полученной из полностью установленного дистрибутива.
Со временем инструментальные дистрибутивы выросли в размере, увеличилось
число принимающих участие в разработке дистрибутивов, и в результате
сборка дистрибутива в хост-системе стала неудобной, ненадёжной
и небезопасной.
Необходимость установить дистрибутив целиком приводит к неоправданно
большому размеру сборочной среды.
В свою очередь, при таком размере среды проявляется несовместимость
инструментальных средств, которые не всегда удаётся разрешить с помощью
альтернатив, переключателей и других приёмов.
Поскольку все инструментальные средства установить в систему не удаётся,
возникает необходимость прав администратора для установки произвольных
требующихся для сборки пакетов в хост-систему.
Кроме того, невозможно обеспечить параллельную сборку пакетов с
несовместимыми сборочными зависимостями.
И, наконец, при таком слабоконтролируемом составе сборочной среды, которой
является хост-система, возникает неявная, не очевидная и нигде не
обозначенная зависимость результата сборки от конкретной сборочной среды,
возникают `неприкосновенные сборочные серверы '.
Небезопасность самой хост-системы проистекает из-за самой возможности
запуска произвольного кода с правами администратора при установке пакетов,
требуемых для сборки.
Небезопасность пользователя, занимающегося сборкой, связана с запуском
произвольного кода с правами сборщика непосредственно во время сборки.
Небезопасность сборок друг от друга обусловлена двумя факторами:
возможностью произвольного изменения сборочного окружения во время сборки,
и возможностью непосредственного воздействия на последующие сборочные
процессы.
Почему безопасности сборочной технологии уделяется так много внимания?
Потому что сборка дистрибутива является областью повышенного риска.
Внимание blackhat community связано с привлекательностью компрометации
дистрибутива, через который можно легко получить контроль над множеством
серверов и рабочих станций.
Большое число разработчиков разной квалификации приводит к тому, что
некоторые из них могут стать лёгкой добычей для злоумышленников и
впоследствии могут быть использованы для атаки на дистрибутив.
Скомпрометированным может оказаться как клиентское ПО, используемое
разработчиком, так и ПО, собираемое разработчиком. За последние два года
были публичные случаи и того, и другого.
Нельзя исключать и возможность непосредственной атаки на сборочную систему.
Таким образом, технология сборки элементов дистрибутива (пакетов) должна:
- не снижать уровень безопасности хост-системы;
- обеспечивать собственную безопасность от атак со стороны пакетов;
- обеспечивать безопасность сборки пакетов от атак со стороны других пакетов;
- гарантировать надёжность (воспроизводимость) результатов сборки;
- обеспечивать приемлемый уровень производительности.
hasher базируется на принципе создания новой сборочной среды для
каждой сборки.
В основе архитектуры hasher'а лежит трёхпользовательская
модель: вызывающий непривилегированный пользователь (C) и два
непривилегированных вспомогательных псевдопользователя; первый (R)
играет роль root в порождаемой сборочной среде (далее псевдоroot),
второй (U) - обычного пользователя, собирающего программы (далее
псевдосборщик).
Переключение между вызывающим и вспомогательными пользователями
осуществляется с помощью специальной привилегированной программы
(вызываемой посредством sudo), написанной с применением параноидальных
мер защиты от непривилегированных пользователей. Кроме того, с помощью
этой программы удаляются процессы, запущенные вспомогательными
псевдопользователями и не завершившиеся в срок, а также создаются
устройства. Наконец, эта программа предоставляет возможность
контролировать ресурсы, выделяемые процессам непривилегированных
пользователей, для защиты от DoS-атак.
Путь пакета через сборочную систему в общих чертах выглядит следующим
образом:
- Пользователь C порождает среду (aptbox) для работы с apt.
- Полностью удаляется сборочная среда, возможно оставшаяся
от предыдущей сборки. Удаление происходит последовательно в чруте
пользователем U, в чруте пользователем R и, наконец,
пользователем C.
- Пользователь C создаёт каркас новой сборочной среды,
состоящий из вспомогательных каталогов и вспомогательных статически
слинкованных программ (ash, find и cpio). С помощью вспомогательной
привилегированной программы создаётся фиксированный набор устройств,
достаточной для нормального функционирования сборочной среды и при этом
не несущий угрозы host-системе.
- Порождается базовая установочная среда, представляющая собой
набор средств, необходимых для штатной установки пакетов в эту среду.
Пользователь C с помощью aptbox определяет набор пакетов, необходимых
для порождения базовой установочной среды. Пользователь R с
помощью вспомогательных статически слинкованных программ распаковывает
эти пакеты.
- Порождается базовая сборочная среда, представляющая собой набор
средств, необходимых для сборки любого пакета. Пользователь C с
помощью aptbox определяет набор пакетов, пользователь R устанавливает их.
- Проверяется исходный пакет.
- Порождается сборочная среда для данного пакета. Пользователь
U извлекает сборочные зависимости пакета, пользователь C с помощью
aptbox определяет набор пакетов для установки, и пользователь R
устанавливает их.
- Пользователь U осуществляет сборку пакета и проверку результатов
сборки.
Такая схема призвана исключить атаки вида U->R,
U->C, R->C,
а также все виды атак на root.
Для повышения производительности, особенно важной при сборке большого числа
пакетов, применяется кэширование базовой сборочной среды.
С помощью средств apt реализована возможность использования собранных ранее
пакетов для сборки последующих пакетов.
Благодаря свойству воспроизводимости результатов сборки hasher
можно использовать для параллельной сборки большого числа пакетов на
нескольких серверах. Таким образом удаётся достичь разумного времени
сборки при средних вычислительных ресурсах. Открывается возможность
организовать регулярное тестирование на пересобираемость большого
репозитария пакетов, что и было сделано на примере Sisyphus с помощью
средства параллельной сборки beehive.