Защищаем конвейер. Четыре столпа безопасности

В ИТ очень любят автоматизацию и ускорение. Особенно, если эти решения позволяют на самом деле ускорить Time to Market, не отставать от конкурентов (а то и обгонять их) и свести к минимуму влияние человеческого фактора. Одним из способов автоматизации, если мы говорим о разработке и развитии ПО, является использование конвейера — автоматизированной последовательности шагов, которые проходит код, попадая из заботливых рук разработчика на целевые окружения. Именно конвейер проводит код через все нужные проверки, автоматически сообщает о найденных ошибках. То есть скорость, масштабируемость и прозрачность — все это сильно помогает и дисциплинирует.
С точки зрения безопасности у людей порой немного смещается фокус — все смотрят на сам программный продукт, выходящий из этого конвейера (на его стабильность, надежность и уровень ИБ), но при этом забывают про сам конвейер. А как на самом деле с ним дела? Почему мы в нем настолько уверены? Можем ли мы точно дать гарантию, что наш собственный производственный узел нас нигде не подведет и не станет фактором компрометации?
Как вы поняли, сегодня поговорим о безопасности конвейера. Меня зовут Владимир Ковтунов, я начальник отдела безопасности разработки и автоматизации в департаменте ИБ Группы Rubytech.
Под катом — четыре столпа, на которых мы строим ИБ своих конвейеров для B2G-проектов, и общие советы, которые пригодятся вам, если вы занимаетесь аналогичными вещами.
Защита среды разработки.
Управление конфигурацией.
Самопроверка конвейера.
Разграничение ролей и минимальные привилегии.
А теперь подробнее.
С точки зрения ИБ главной проблемой в использовании конвейеров является именно способность гарантировать безопасность самого конвейера. Аналогию тут можно провести с большой кофемашиной. Вы в целом привыкли, что она работает и просто делает вам отличный кофе по нажатию одной кнопки. По умолчанию все должно быть хорошо, но где именно гарантия, что внутри узлов не начала заводиться плесень, потихонечку расширяющая свою экспансию? Или что молоко в специальном отсеке не успело скиснуть за ночь? Или что какой-нибудь злоумышленник, выбравший себе цель (да-да, вас) не добавил в отсек для воды какой-то отравы?
С конвейером примерно так же. Вот для примера пара инцидентов, в которых все пошло не так именно из-за недостаточной защищенности конвейеров.
SolarWinds (2020) — компания, занимающаяся разработкой систем мониторинга, предлагает крупное enterprise-решение. Однажды к их системе сборки (Orion-based) получили доступ злоумышленники, после чего все обновления их программного обеспечения начали вызывать понятную реакцию у антивирусов. В легитимные обновления платформы Orion (версии 2019.4 HF5 — 2020.2.1, март–июнь 2020) внедрили бэкдор SUNBURST. Обновления были подписаны валидным сертификатом SolarWinds и распространялись примерно 18 000 клиентам. Компания при этом первое время отмахивалась в формате «Это просто ложные срабатывания, так бывает», пока не выявили брешь в защите.
Ущерб — акции компании рухнули на 35%, выплаты клиентам по коллективному иску — 26 миллионов долларов США. Удар по репутации — после этого компания де-факто стала той самой, кого и приводят в пример при описании таких атак. Потеря доверия и снижение лояльности со стороны госзаказчиков и корпклиентов.
Codecov (2021) — тоже конвейер, модификация bash-скрипта, благодаря чему атакующий смог скомпрометировать окружение у тысяч клиентов компании. Одним из продуктов компании и был определенный скрипт, загружающий на инфру клиентов обновления. Модифицированный скрипт при каждом запуске в CI клиентов отправлял на сервер злоумышленника git remote и все environment variables (токены, ключи AWS/GCP, deploy keys, секреты и прочее). Фишка в том, что уязвимость обнаружил клиент, который сравнивал SHA-суммы.
Что получается? Самой компании как таковой вред нанесен не был, но она стала точкой входа для целевой атаки сразу на множество ее клиентов. Внедрившись в конвейер разово, злоумышленники могли раскручивать примерно любые свои дополнительные сценарии, ограниченные лишь фантазией.
Ущерб — компания тоже стала притчей во языцех, когда речь заходит о supply-chain атаках через CI-инструмент. Собственно, поэтому вы и читаете о ней в этой статье. О денежном ущербе в открытых источниках данных нет, но часть клиентов компания потеряла.
CircleCI (2023) — были скомпрометированы токены сессии, после чего атакующие получили доступ ко внутренним системам клиентов компании и выгрузили данные из продуктивных баз, прямо из пайплайнов. Зимой 2022 ноутбук инженера компании был заражён вирусом, который украл валидную 2FA-backed SSO сессионную куку. Затем атакующий использовал эту куку для имперсонации сотрудника, получил доступ к проду и сгенерировал ещё токенов для доступа.
Здесь проблема была в изоляции — злоумышленники получили доступ к CI-конвейеру как к сервису, а оттуда смогли проникнуть в инфраструктуру самой компании. Последствия похожие, как и у случая выше: компании не навредили, но через нее как точку входа попали к ее клиентам и стали похищать их данные. К слову, это все еще одна из самых главных ценностей в даркнете — данные, секреты и токены, персональные данные, платежные данные и подобное.
Ущерб — репутационный. Представьте, каково было компании писать всем клиентам с просьбой обновить любые секреты, хранящиеся на CircleCI.
Спасибо всем трем компаниям за открытость и публикацию подробностей инцидентов — они не стали замыливать произошедшее, что позволило сообществу учесть подобные риски у себя, да и в целом повысило зрелость ИБ-отрасли.
Вот три сценария (как минимум — из публично известных и значимых для отрасли), которые заставляют задуматься: что же именно и как стоит защищать в своем конвейере?
Практическая польза ГОСТов
Увы и ах, какого-то золотого стандарта для создания единственно верной и неуязвимой защиты конвейеров нет. Все всегда зависит от точечных потребностей конечного потребителя.
Если говорить про нас, то мы по большей части работаем в B2G-сегменте, то есть с госсектором. Для этих клиентов значимым является соответствие программных продуктов текущих отраслевым ГОСТам. Это не только формальность, но и на самом деле важная штука. Чтобы доказать госзаказчикам, что ваш продукт на самом деле серьезный, безопасный и вообще достойный, мало знать это внутри собственных команд. Важно именно соответствие конкретным ГОСТам, в которых на самом деле прописаны полезные тезисы, потому что регуляторная часть подтянулась благодаря взаимодействию с профильными экспертами.
Вот примеры. Они же — те самые четыре столпа из заголовка статьи.
Знакомьтесь, ГОСТ Р 56939-2024.
Пункт 5.13 — защита среды разработки: среда должна быть защищена от несанкционированного доступа и модификации.
По сути, это как раз про адекватную сегментацию, которой пренебрегли в CircleCI. Ведь если ваш конвейер не находится в продуктиве, то даже внедрившись в него и завладев локальными привилегиями, злоумышленник никуда дальше не пройдет просто за счет сетевых разграничений. Никакого доступа к чувствительным данным, никакого дополнительного увеличения поверхности атаки. Как по мне, это то, к чему нужно стремиться, и это справедливо для всего, что есть: чем изолированнее все вокруг, чем меньше привилегий, тем как бы лучше. Это паттерн. Полезный.
Это же касается и серверов. Если мы говорим про конвейер, что это такое с точки зрения техники? Это оркестратор, система, которая хранит в себе код настройки пайплайна, своего рода главная боевая единица конвейера. В нашем случае есть раннеры, некие воркеры, в общем, дополнительные сущности, контейнерные или виртуальные машины, не суть, которые внутри себя получают команду от оркестратора и что-то выполняют. Настроенный пайплайн обычно представляют в UI или в формате as a code. Лучше, конечно, хранить ещё и as a code, потому что это упрощает контроль и консистентность.
Так вот, репозитории с исходниками, которые обрабатывают содержимое конвейера, — все это должно быть изолировано. И здесь очень нужны регламенты и ролевые разграничения. Нельзя допускать ситуации, когда в компании есть один DevOps-инженер с какими-то ультрадоступами вообще ко всему. Мало кто может сказать, чем именно он занимается, при этом его учетка — это сразу суперточка отказа в любых непонятных ситуациях. Так что обращайте особое внимание на ролевые доступы. Просто распределить всё по сетям и изолировать — это здорово. Но недостаточно, надо еще понимать, кто, где и с каким сегментом от какой роли работает.
Пункт 5.4. Управление конфигурацией. Должны быть исключены несанкционированные изменения исходного кода, конфигурации сборки.
Есть такой оркестратор — Bamboo. Он написан на Java, и единственный вариант обращаться с ним as-code (по крайней мере, так было в 2018) — это через загрузку java-страничек. Это супернеудобно, непонятно, и по факту вся работа происходит в графическом веб-интерфейсе. Соответственно, кто туда зашел, что понажимал, зачем, как это залогируется на уровне приложения — всё очень спорно и непрозрачно.
Зато при этом есть два изумительных чуть ли не стандарта отрасли — это GitLab и Jenkins, у которых полностью все пайплайны описаны в виде кода и хранятся в системе контроля версий. То есть пайплайн написан от и до текстом, там есть свой синтаксис, он также хранится в системе контроля версий, нельзя просто где-то что-то исправить и не узнать об этом. Потому что, работая с ним как с кодом, команда создает коммиты, получает возможность настроить code review. Отсюда вы получаете и полный контроль в плане заливки чего-то нового, и историю про ветвление — в мастер ничего не льется автоматом, всегда есть предварительные шаги.
Также на конвейер распространяется справедливое замечание, что у него должно быть разделение на test- и dev-окружения. В боевом сразу делать ничего нельзя — с высокой долей вероятности на нем уже висит промышленная эксплуатация. А скорее всего, еще и бизнес-функционал.
Конвейер должен функционировать четко, ровно, не давая сбои. И это как раз про управление конфигурацией.
Пункт 6.2. Сам конвейер должен не просто предоставлять услуги сканеров — он должен проверять этими инструментами еще и сам себя.
Я бы не привел вам в пример те три случая про взломы в начале статьи, если бы конвейеры всех трех компаний сами себя проверяли — на уровне исходного кода, контрольных сумм, код-ревью и прочего. Потому что в таком случае сотрудники бы точно заметили, что, скажем, где-то есть модифицированные bash-скрипты. Тем более, что это довольно простая и дешевая история в плане ресурсов — на bash пишут примерно все, он прекрасно читабелен, это де-факто чуть ли не базовый скилл любого айтишника, хоть раз сталкивавшегося с конвейерами.
Пункт 7.1. Разграничение ролей.
Например, разработчик не должен иметь доступа к продуктивной среде. Команды состоят из разных людей, есть группа тестирования, есть аналитики, и все-все-все участвующие в процессе роли должны быть продуманы, как и их права доступа. Если проще, разработчику, который пишет код, нужно разрешить писать код. А вот доступ до раннеров, который написанный им код будет собирать, ему в целом-то и не нужен. Да, да, это бы могло (гипотетически) пригодиться для отладки, но это как раз уже дополнительный уровень привилегий, а не рекомендуемый минимальный. Потому что один из паттернов построения безопасного конвейера — это именно минимальные привилегии. Так что в проде достаточно наличия ребят из SRE и эксплуатации.
С чего же начинать защищать свои конвейеры
Для начала представьте себе ситуацию. Жила-была компания, которая решила выбрать классический путь — защитить сразу все, до чего дотянется. Начала выделять на это благое дело бюджеты, последовательно все внедрять, и получила в итоге довольно ожидаемый результат. А именно — процентов 90 вложенных средств ушло на защиту вещей, которые в целом-то никак не влияют на благополучие компании. Скажем, сделали сверхсекьюрное облако под требования 152-ФЗ, но пользуются им для галочки. В итоге бюджет успешно освоен, презентации собраны, все причастные награждены.
Вот только у компании один монорепозиторий на все окружения с maintainer-правами для всего ДИТа и ДИБа, причем в условиях дикой текучки. И в какой-то момент случается так, что очередной обиженный сотрудник прикарманивает себе всю интеллектуальную базу. Или разозлившийся на начальника разраб внедряет вредонос (ибо компания не озаботилась SAST при освоении бюджета, зато вот с облачным WAF всё хорошо). И все.
Если вы думаете, что это совсем карикатурная ситуация и такого не бывает — увы, бывает.
Так вот, с чего начинать, чтобы нормально защитить конвейер.
Прежде всего — с оценки собственного бизнеса, надо определить, что вообще стоит защищать.
Потому что ИБ в этом плане работает с двух сторон медали. С одной стороны, без ИБ никуда, и если с инфобезом у вас все плохо, рано или поздно (скорее, рано) плохо будет с чем-то ещё. С другой стороны, бизнес — всегда про развитие, скорости и догонялки с конкурентами. ИБ же в этом контексте всегда отрицательно сказывается на time to market. Просто потому, что это еще один слой проверок. Да, правда жизни такова, что ИБ конвейера отчасти просадит сразу два показателя компании — скорость и деньги.
При этом стоит понимать, что правильно настроенный конвейер — это скорость выкатки любых изменений и фич в продакшн. А правильно защищенный конвейер — это сохранение нужной вам скорости без лишних рисков в плане того, что кто-то через конвейер пролезет в инфру к вам или к вашим клиентам через вас.
Пока именно на этих четырех столпах зиждется наш подход к построению конвейера. Само собой, в ходе сдачи и разработки мы получаем запросы, уточнения и поручения из совершенно разных областей, которые пока этот ГОСТ обходит стороной. Но это обычно истории, в которых заказчик сам является соархитектором качественной системы, которую он будет понимать и которой он будет доверять.
Итак, это была верхнеуровневая статья про общие принципы безопасности конвейера, которые особенно важны для B2G. В следующей расскажу подробнее о проектировании безопасного пайплайна: о сегментации и принципе минимальных привилегий — именно эти вещи, как минимум, спасли бы в свое время SolarWinds. Поговорим о разделении контуров сборки, тестирования и продакшена, об опасности запуска всех джобов под одним root-ом и рассмотрим архитектуру изолированных раннеров и агентов.
А если у вас есть вопросы — с радостью отвечу в комментариях.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.