open atlas
↑ К треку
Безопасность облака и инфраструктуры CLOUD · 03 · 03

SLSA and SBOM in delivery

SolarWinds и бэкдор в XZ приехали через доверенные пайплайны сборки, а не через эксплойты. Provenance SLSA плюс подпись доказывают, как собран артефакт и что это именно тот, который ты ревьюил; а SBOM перечисляет содержимое, чтобы за минуты ответить «затронуты ли мы».

CLOUD Middle ◷ 15 min
Уровень
ОсновыJuniorMiddleSenior

Сканеры были зелёные. У каждой зависимости — чистый отчёт по CVE, образ прошёл политику реестра, деплой ушёл в пятницу. Через три недели выясняется: версия, которую ты выкатил, никогда не была версией из репозитория — кто-то с правом записи на self-hosted раннер подменил один скомпилированный объект уже после прогона тестов. Это ровно форма SolarWinds: вредоносная DLL, внедрённая в доверенную, подписанную, прошедшую сборку и разосланная 18 000 организаций. Никакой эксплойт не пробивал периметр. Периметр сам собрал им вредонос. Весь класс компрометаций цепочки поставок живёт в зазоре между «этот артефакт прошёл» и «этот артефакт — тот самый, который я ревьюил», и закрыть этот зазор — задача provenance SLSA, подписи артефактов и SBOM.

К концу урока ты будешь знать, что именно доказывают provenance и подпись (и чего не доказывают), где встаёт SBOM и как дойти до уровня SLSA, который поймал бы подмену в стиле SolarWinds.

Зазор доверия, который оставляет прошедшая сборка

Обычный пайплайн отвечает на вопрос «прошёл ли код?». Он не отвечает на «то, что я собираюсь деплоить, — это подлинный, неизменённый вывод того прошедшего прогона, из источника, который контролирую я?». Это разные вопросы, и именно во втором живут атаки на цепочку поставок. SolarWinds (имплант в системе сборки), Codecov (утёкший креденшл bash-uploader’а, переписывавший вывод CI) и бэкдор в XZ Utils 2024 года (вредоносный мейнтейнер протащил обфусцированный код в релизные тарболы, отличавшиеся от git-дерева) — все обошли любой контроль, сканирующий вход. Ни один из них не был injection-багом или непропатченным CVE. Они вмешивались в производство артефакта, а твой сканер зависимостей по своей природе туда не смотрит.

Поэтому проблема цепочки поставок раскладывается на три вопроса, на которые ты обязан уметь ответить про всё, что деплоишь:

  • Как это собрано?provenance сборки: из какого коммита источника, каким сборщиком, с какими параметрами, и без человека, способного молча внедрить шаги. Это область SLSA.
  • Это ровно тот артефакт, который собрали?целостность, устанавливаемая криптографической подписью над дайджестом артефакта и проверяемая в момент допуска.
  • Что внутри? — его bill of materials: каждый компонент и версия, чтобы при следующем Log4Shell ответить «затронуты ли мы?» по индексу, а не лихорадочным grep по всем сервисам. Это и есть SBOM.

SLSA, подпись и SBOM — не конкурирующие стандарты, они по очереди отвечают на эти три вопроса, и нужны все три. Provenance без подписи — заявление, которое любой может подделать; подпись без provenance доказывает, кто выпустил, но не что сборка была честной; и то и другое без SBOM оставляет тебя слепым в день, когда транзитивная зависимость окажется радиоактивной.

SLSA: provenance и лестница уровней

SLSA (Supply-chain Levels for Software Artifacts, читается «сальса») — это фреймворк, который оценивает, насколько процессу сборки можно доверять. Его ключевой артефакт — provenance: подписанное, машиночитаемое утверждение, что этот дайджест вывода произведён из той ревизии источника, тем сборщиком, с этими параметрами. Смысл — неотрекаемость самой сборки: проверяющий ниже по потоку может убедиться, что бинарь перед ним действительно вышел из пайплайна, на который ссылается, а не подменён после.

SLSA v1.0 определяет Build-трек с уровнями, которые наращивают гарантии о сборщике, а не объём бумаг:

Уровень BuildЧто требуетЧто останавливает
L0Никаких гарантийНичего — состояние по умолчанию
L1Скриптовая сборка + provenance существует (может быть без подписи)Ошибки учёта; «чем это собрано?» имеет ответ
L2Хостируемая платформа сборки + подписанный provenanceПодделку provenance; подмена после сборки обнаружима
L3Усиленный изолированный сборщик; provenance неподделываем шагами сборкиВредоносный шаг сборки, внедряющий себя — форма SolarWinds

Решающий скачок — L2 → L3. На L2 подписанный provenance доказывает, что артефакт не подменили после сборки, но скомпрометированный сборочный скрипт всё ещё может солгать в provenance, который сам генерирует. L3 требует, чтобы сборка шла в изолированном эфемерном окружении, где provenance генерирует платформа, а не контролируемые пользователем шаги, — так что вредоносный шаг, подменивший объект SolarWinds, не сможет заодно подделать чистую аттестацию о самом себе. Эта изоляция и есть настоящая граница безопасности; номер уровня — лишь сокращение для «насколько может солгать плохой шаг сборки».

Практический путь неэффектен: большинство управляемых CI (GitHub Actions с официальным генератором SLSA, GCB, Tekton Chains) дают подписанный provenance L2/L3 ценой изменения воркфлоу. Ловушка — self-hosted раннер, который ты переиспользуешь между джобами: общее состояние между сборками возвращает тебя ниже L3, какую бы аттестацию ты ни выдавал, потому что предыдущая джоба может отравить следующую.

Подпись: keyless и журнал прозрачности

Provenance хорош ровно настолько, насколько хороша подпись над ним, а управление ключами — место, где умирают программы подписания. Современный ответ — keyless-подпись (cosign из Sigstore): вместо долгоживущего приватного ключа, лежащего в хранилище секретов в ожидании утечки, сборщик аутентифицируется короткоживущей OIDC-личностью (например, workload identity у GitHub Actions), Fulcio выдаёт эфемерный сертификат, привязанный к этой личности, делается подпись, ключ выбрасывается, а всё событие записывается в Rekor — публичный журнал прозрачности, дополняемый только в конец.

Это даёт два свойства, недостижимых для статического ключа. Во-первых, красть нечего — ключ подписи жил секунды. Во-вторых, запись в Rekor доказуемо неподменна: у задним числом сделанной или подделанной подписи нет соответствующей записи в журнале, поэтому проверка может требовать «должна быть в Rekor до момента T». Ты проверяешь по личности и provenance, а не по вере в то, что ключ хранили в безопасности три года.

Частая ошибка

Соблазнительная ошибка — считать зелёную подпись доказательством безопасности. Подпись доказывает лишь целостность и происхождение — «это ровно тот артефакт, который опубликовала личность X». О том, вредоносен ли артефакт, она не говорит ничего. Бэкдор в XZ в каком-то смысле был корректно выпущен самим мейнтейнером проекта; подпись прошла бы проверку чисто. Подпись останавливает подмену и выдачу себя за другого; она не ручается за намерение. Тебе всё ещё нужны provenance (была ли сборка честной?), сканирование по SBOM (что внутри?) и ревью кода (доверяем ли мы самому источнику?). Считать «подписано» равным «безопасно» — это как проверенный-но-злой артефакт проходит через gate.

SBOM: ответ «затронуты ли мы?» за минуты

SBOM (Software Bill of Materials) — это список ингредиентов: каждый компонент, версия и лицензия внутри артефакта в стандартном машинном формате — SPDX или CycloneDX. Ты генерируешь его на сборке (например, Syft или родным экспортёром твоего сборочного инструмента), прикладываешь как подписанную аттестацию рядом с provenance и кладёшь туда, где его сможет запросить реагирование на инциденты.

Его ценность асимметрична и проявляется ровно в один тип дня. Когда в декабре 2021 рвануло Log4Shell, команды без SBOM сутками гоняли find по сотням сервисов, чтобы выяснить, вшит ли log4j-core — часто транзитивно, на три уровня вглубь, внутри fat JAR, о содержимом которого они не подозревали. Команды с запрашиваемым индексом SBOM за минуты ответили «в каких из наших 400 задеплоенных артефактов есть log4j-core в затронутом диапазоне?» и сузили реакцию до тех немногих, где он был. SBOM не предотвращает уязвимость; он схлопывает твоё среднее-время-до-ответа с суток до запроса, а это разница между управляемым раскатом и выходными в панике.

Зрелый нюанс: SBOM достоин доверия, только если он сгенерирован из собранного артефакта и подписан как аттестация, а не поддерживается вручную в вики. Устаревший или собранный только-из-исходников SBOM, упускающий то, что финальный образ реально вшил, хуже, чем никакой, потому что отвечает на «затронуты ли мы?» ложной уверенностью.

Выбери лучший вариант

Команда собирает релизные артефакты на self-hosted CI-раннере, переиспользуемом между всеми джобами, подписывает их долгоживущим приватным ключом из менеджера секретов и выдаёт provenance SLSA. Они хотят реально предотвратить подмену в стиле SolarWinds. Выбери изменение, которое закрывает настоящий зазор.

Викторина

Что на самом деле доказывает подпись артефакта (например, cosign)?

Викторина

Почему скачок SLSA L2 → L3 — именно тот, что важен для атаки в стиле SolarWinds?

Расставь шаги по порядку

Упорядочь проверяемый пайплайн цепочки поставок от источника до работающей нагрузки:

  1. 1 Отревьюенный коммит источника входит в изолированный эфемерный сборщик
  2. 2 Сборщик выдаёт артефакт + его дайджест
  3. 3 Платформа выдаёт подписанный provenance SLSA и аттестацию SBOM
  4. 4 Gate допуска проверяет подпись, provenance и политику
  5. 5 Артефакт допущен, и нагрузка запускается
Вспомните перед уходом
  1. 01
    Объясни три вопроса, на которые отвечают SLSA, подпись и SBOM по отдельности, и почему нужны все три.
  2. 02
    Почему скачок SLSA L2→L3 — это граница безопасности, и что keyless-подпись добавляет сверху?
Итог

Атаки на цепочку поставок вроде SolarWinds, Codecov и бэкдора в XZ не пробивали периметр — они вмешивались в то, как производится артефакт, в зазоре между «эта сборка прошла» и «это честный, неизменённый вывод источника, которому я доверяю». Три контроля закрывают этот зазор, каждый отвечает на свой вопрос. Provenance SLSA отвечает, как он собран: подписанная аттестация, связывающая дайджест вывода с ревизией источника и сборщиком, где скачок L2→L3 — прогон сборки в изолированном эфемерном окружении с provenance от платформы — это граница, не дающая вредоносному шагу сборки подделать чистую запись о самом себе (а переиспользуемый self-hosted раннер молча опускает тебя ниже неё). Подпись отвечает, тот ли это ровно артефакт, причём keyless-подпись Sigstore убирает долгоживущий ключ как цель для кражи, а журнал прозрачности Rekor делает задним числом сделанные подписи обнаружимыми, — но подпись доказывает происхождение и целостность, а никогда не то, что код безвреден. SBOM (SPDX или CycloneDX, сгенерированный из собранного артефакта и подписанный как аттестация) отвечает, что внутри, схлопывая «затронуты ли мы этим новым CVE?» из суточного grep в минутный запрос. Проверяй все три на gate допуска, и в следующий раз, когда сборка вернётся зелёной, твой первый вопрос — уже не «прошла ли?», а «могу ли я доказать, что это артефакт, который мой пайплайн честно собрал из отревьюенного мной источника, — и знаю ли я, что внутри?».

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 6 завершено
Связанные уроки
углубляется в

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.