Обеспечение подлинности — мощный инструмент, позволяющий противостоять растущим атакам на цепочки поставок ПО. При таких атаках в конвейер сборки и доставки ПО попадает вредоносное ПО, и ущерб наносится не только организации, но и неопределённому кругу её клиентов.
Тенденция роста атак отражена в ежегодном отчёте Sonatype, где указано увеличение количества вредоносных компонентов в 156% за 2024 год. Примерами таких атак являются попытка внедрения бэкдора в основной репозиторий PHP путём отправки вредоносных коммитов от имени известных разработчиков, публикация поддельного артефакта в CodeCov (описание), обнаружение неправильных настроек CI/CD в среде Tensorflow, которые могли способствовать внедрению вредоносного кода.
Согласно фреймворку SLSA атаки могут воздействовать на исходный код (добавление кода неавторизованным лицом, взлом репозитория с кодом, что может повлечь сборку артефакта с подменным программным кодом), могут воздействовать на зависимости, используемые для сборки артефакта (добавление вредоносного кода в зависимости), воздействовать на сам процесс сборки (внедрение в сборочный процесс), либо воздействовать на артефакт или хранилище артефактов.
На важность противодействия таким атакам указывают многие международные ИТ и ИБ организации. OWASP выделяет отдельный TOP 10 атак на CI/CD, а количество исправлений безопасности в популярных сборочных системах год от года не уменьшается (GitLab, Jenkins).
Фреймворк SLSA предполагает 3 уровня защиты (и плюсом нулевой уровень, не предполагающий никаких защитных мероприятий). Уровень 1 требует наличия документа о происхождении артефакта, т.н. provenance, а уровень 2, помимо других требований, говорит о необходимости проверки подлинности provenance. Воспользуемся этими требованиями и составим список мероприятий по обеспечению подлинности в конвейерах сборки и доставки:
1. Обеспечить подлинность авторства программного кода
2. Удостовериться в подлинности сборки артефакта
3. Проверить подлинность артефакта перед развёртыванием
1. Проверяем подлинность авторства разработчика
Для этого в Git есть механизм подписи с ключом GPG. У пользователя должен быть создан открытый и закрытый GPG ключи. Закрытым ключом подписывается коммит, а открытым проверяется подлинность коммита. (Примечание: в Gitlab есть удобный графический интерфейс для хранения открытых ключей пользователя и результатов проверки подлинности коммитов. Ссылка)
Пример создания пары ключей и подписи коммита:
1. Установить GPG.
2. Сгенерировать пару ключей:
gpg —gen-key
В процессе нужно указать своё имя, электронный адрес и придумать пароль. Должно получиться примерно так:
открытый и секретный ключи созданы и подписаны.
pub ed25519 2024-09-10 [SC] [ годен до: 2027-09-10]
E883B1F1F2F3F4F5F6F7F8F9C1C2V3C4C5C6C7C7
uid SecondName FirstName
sub cv25519 2024-09-10 [E] [ годен до: 2027-09-10]
PS C:>
Чтобы получить приватный GPG ключ:
gpg —list-secret-keys —keyid-format LONG your_email_here
Результат:
sec ed25519,0123ABCD45678 2024-09-10 [SC] [ годен до: 2027-09-10]
E883B1F1F2F3F4F5F6F7F8F9C1C2V3C4C5C6C7C7
uid [ абсолютно ] SecondName FirstName
ssb cv25519/987654321FDEFEFE 2024-09-10 [E] [ годен до: 2027-09-10]
ID приватного ключа здесь: `0123ABCD45678`
Чтобы получить открытый ключ
gpg —armor —export ID
ID — id приватного ключа.
3. Связать приватный ключ GPG с Git
Это можно сделать через командную строку
git config user.signingkey ID
или через GUI, например TortoiseGit (поле Signing key ID):
4. И вот наконец можно подписать коммит:
git commit -S -m «message»
Обратите внимание на ключ `-S`
Если при подписи возникла ошибка `secret key not available`, то необходимо git указать путь к GPG (решение взято со StackOverflow
git config —global gpg.program «C:Program Files (x86)GnuPGbingpg.exe»
5. Проверить подлинность подписи коммита:
git verify-commit commit_id
2. Составляем provenance и sbom
Для начала давайте разберёмся, что такое provenance и sbom.
Provenance — это документ о происхождении артефакта. В нём перечислены сборщики, переменные окружения, список артефактов и их электронные подписи.
Чтобы добавить provenance в артефакты сборки в Gitlab в пайплайне необходимо объявить локальную переменную:
variables:
RUNNER_GENERATE_ARTIFACTS_METADATA: true
Более подробно об этом написано в документации Gitlab’a.
В дальнейшем на следующих этапах для проверки подлинности из provenance понадобятся:
1. sha коммита
2. sha артефактов
Provenance не содержит информации о компонентах, из которых эта сборка производилась. Для это необходим SBOM — Software Bill Of Materials — документ, содержащий полный перечень зависимостей, используемых для этой сборки.
Наиболее удобным способом генерировать SBOM является использование специализированных утилит. Основным стандартом SBOM является OWASP CycloneDX. На момент написания статьи самой новой является версия 1.6. В рамках OWASP CycloneDX разработано множество средств для создания, хранения, преобразования SBOM. Выбор наиболее подходящего средства оставлю за читателем.
3. Подписываем и проверяем артефакт, provenance и sbom
… и заодно проверим подлинность сборщика. И сделать это всё можно с использованием Cosign.
Основная идея состоит в следующем: создаётся ключевая пара
cosign generate-key-pair
Результатом станут два файла: `cosign.key` и `cosign.pub`.
Далее при помощи этих ключей мы можем:
1. подписать файлы (blob’ы), а именно provenance, sbom и артефакт
cosign sign-blob —key cosign.key sbom.json
2. подписать образы
cosign sign —key cosign.key registry-name/image:latest
3. проверить подлинность файла с именем filename
cosign verify-blob —key cosign.pub —signature your_sign filename
Кроме того, можно сверить sha256 артефакта с тем, что описан в provenance.
4. проверить подлинность образа перед развёртыванием
cosign verify —key cosign.pub registry-name/image:latest
Перед развёртыванием также необходимо проверить подпись кода, из которого он собран. Для этого нужно сделать такой запрос:
Пример:
curl —header «PRIVATE-TOKEN: »
—url «https://gitlab.example.com/api/v4/projects/1/repository/commits/da738facbc19eb2fc2cef57c49be0e6038570352/signature»
sha коммита берётся из provenance.
Если развёртывание идёт в Kubernetes то следует воспользоваться Kyverno, который реализует различные политики и, в том числе, проверка подписи Cosign перед развёртыванием. Kyverno разворачивается через helm-чарт и позволяет создавать манифесты с необходимыми правилами. Пример такого манифеста можно найти в официальной документации.
Возможно, у вас возник вопрос: «Всё это хорошо, но что где хранить ключи к Cosign?». — В отдельном независимом хранилище. Для этого можно использовать платные облачные сервисы, например: Yandex KMS, либо воспользоваться on-premise Open Source решением — Hashicorp Vault, которое может интегрироваться с GitLab посредством протокола OIDC (при этом нужно убедиться, что доступ к ключам доступен лишь из конкретного проекта, а не всего GitLab).
Автор: Виктор Веденеев, инженер по инфраструктурной безопасности УЦСБ.
Оригинал публикации на сайте CISOCLUB: "Обеспечение подлинности в конвейерах сборки и доставки ПО".
Смотреть публикации по категориям: Новости | Мероприятия | Статьи | Обзоры | Отчеты | Интервью | Видео | Обучение | Вакансии | Утечки | Уязвимости | Сравнения | Дайджесты | Прочее.
Подписывайтесь на нас: VK | Rutube | Telegram | Дзен | YouTube | X.