Смешивать, но не взбалтывать. Как мы добавили Sec между Dev и Ops
Привет, Хабр! Меня зовут Натали Дуботолкова, и я старший инженер по разработке безопасного программного обеспечения в Basis. Компания занимается разработкой средств виртуализации — как классической, например, VDI, так и контейнерной. Моя же задача заключается в создании и поддержании процессов безопасной разработки наших продуктов. Расскажу о том, с чего мы начинали погружение в DevSecOps, какие алгоритмы и инструменты используем с коллегами сейчас.
Трое в (одной) лодке
Думаю, нет смысла объяснять на Хабре, что такое DevOps и как он устроен, поэтому пропущу теоретическую часть (если хотите, можете почитать, скажем, этот пост). Важно то, что эта методология помогает эффективнее разрабатывать и потому используется повсеместно. Однако в традиционном DevOps вопросы безопасности часто остаются на втором плане. Проверка кода на уязвимости обычно проводится в конце цикла разработки, когда исправлять их уже оказывается долго и дорого.
Вот как это бывает. У нас есть продукт, его исходный код хранится в системе контроля версий. Этот код собирается, прогоняются функциональные тесты, которые проходят успешно. Пайплайны автоматизированы и не требуют постоянного участия человека. Получается, мы готовы релизить новую версию нашего продукта!
На самом деле не совсем так. Мы должны проверить код на безопасность, потому что компрометация продукта (и данных, с которыми он работает) плохо скажется на бизнесе. Поэтому до деплоя новой версии в прод команда безопасников начинает проверять код на уязвимости и другие проблемы: например, не используются ли устаревшие или уязвимые библиотеки, не нарушаются ли лицензии, может ли утечь чувствительная информация и так далее. То есть смотрит на те вещи, на которые во время разработки никто особо не обращал внимание.
Все то время, пока безопасники проверяют релиз, команда не может его деплоить в прод и занимается чем-то другим — например, разработкой следующего релиза. Через пару недель приходит отчет об обнаруженных уязвимостях, и релиз уходит на доработку. Последняя требует времени, которое команда разработки планировала потратить совсем иначе, и в результате следующие релизы уезжают вправо. Возникают разные странные мысли — может быть, вообще не выпускать этот релиз, а устранить уязвимости сразу на следующем? А зачем мы тогда делали прошлый релиз? Не получится ли так, что безопасники в следующем релизе найдут еще какие-то проблемы и мы его тоже захотим пропустить, перейдя сразу к третьему?
В результате мы получаем три группы недовольных. Бизнес недоволен, что затягиваются релизы, не соблюдаются сроки, увеличивается стоимость проекта. Разработчики недовольны тем, что им мешают работать, вмешиваются в планы, портят спринты. И безопасники тоже недовольны — чем лучше они работают, тем меньше их любят, потому что их качественная работа заставляет остальных менять планы и сдвигать сроки. А если произойдет инцидент, то вся ответственность будет лежать на них — это тоже не добавляет позитива.
Неизвестные актеры в роли моих любимых коллег
Для решения проблемы всеобщего недовольства мы используем подход Shift Left — это когда про безопасность думают с самых ранних стадиях разработки. Он позволяет выявить и устранить уязвимости не тогда, когда сроки уже поджимают и руководство постоянно спрашивает статус, а когда вы еще спокойно пишете код для продукта. Безопасность становится частью жизненного цикла разработки, начиная с проектирования. Иначе говоря, DevOps превращается в DevSecOps. При этом сами безопасники подключаются к процессам не просто как контролирующий и карающий орган («релиза не будет, пока мы не позволим!»), а как активные участники рабочей группы, которые вносят свой вклад в проектирование приложения или сбор функциональных требований. Это позволяет, хотя и не в полной мере, реализовать концепт Security by Design.
Применение подхода DevSecOps позволило нам выявлять и исправлять уязвимости на ранних этапах, а также улучшило качество кода благодаря мониторингу. Бизнес видит: клиенты и пользователи больше доверяют продуктам, разработчики которых системно заботятся о безопасности. К тому же налаженное взаимодействие ускоряет time to market — исследования безопасности идут параллельно с разработкой, экономя общее время доставки готового продукта.
Всё это, конечно, не гарантирует счастье всех участников процесса разработки, но все-таки облегчает их жизнь. Опять же, руководство никогда не бывает полностью довольным, но в нашем случае (спойлер!) результат был принят.
Семь вопросов менеджеру
Как это иногда случается, то, что хорошо и складно звучит в теории, на практике получается не всегда. По крайней мере, с первого раза. У нас внедрение DevSecOps осложнялось тем, что «Базис» была образована путём объединения нескольких компаний, каждая из которых имела свои собственные процессы и подходы к разработке программного обеспечения. Нам нужно было изучить продукты и создать для всех единые правила, в том числе правила обеспечения безопасности.
Итогом мозговых штурмов и набитых шишек стал список вопросов, которые задаём перед началом работы с новым проектом:
С кем будем контактировать?
Первым делом мы находим человека, которого называем security-чемпионом. Этот человек должен хорошо разбираться в коде продукта и быть заинтересованным в улучшении его качества, поэтому обычно им становится тимлид или менеджер проекта. Security-чемпион является связующим звеном и нашим основным союзником в команде разработчиков. У нас этот человек может давать задачи разработчикам и назначается на всех задачах в трекере.
Как собирается проект?
Выясняем, как проект собирается: какими командами и на каких хостах. Это помогает нам понять инфраструктуру и определить, какие инструменты и методы мы будем использовать для интеграции безопасности.
Какие языки используются?
Зная, какие языки программирования используются в проекте, мы можем подобрать соответствующие инструменты для статического и композиционного анализа кода.
Какой гит-флоу у команды?
Изучаем гит-флоу команды, чтобы понять, как организован процесс работы с кодом. В какие ветки команды коммитят, какие ветки создают, существуют ли релизные ветки и так далее. Это помогает нам внедрить автоматизированные проверки безопасности на разных этапах разработки.
Какой регламент выпуска релизов?
Уточняем, существует ли регламент выпуска релизов и каковы точные даты релизов. Это важно для планирования проверок безопасности и того, чтобы уязвимости были устранены до нового релиза.
Кто будет участвовать в устранении уязвимостей?
Определяем тех, кто получит доступ к сканерам безопасности и инструментам управления уязвимостями.
В какие сроки нужно устранить уязвимость?
Обязательно обговариваем сроки, в которые надо закрывать уязвимости, а также периоды, в которые DevSecOps-инженеры будут приходить для проверки статуса их закрытия.
Только получив исчерпывающие ответы на эти вопросы, мы берем проект в работу.
DevSecOps-инвентарь
Теперь о том, чем мы в «Базисе», собственно, работаем (помимо головы). У нас целый зоопарк инструментов — что-то мы используем на постоянной основе, что-то ситуативно, что-то пока в далёких планах, а от чего уже отказываемся.
Примерно так и выглядит пайплайн у инженеров по безопасности
Статический анализ кода (SAST)
Статический анализ кода позволяет выявлять уязвимости на ранних этапах разработки. Раньше для анализа мы использовали SonarQube — он проверяет большое количество языков программирования, легко интегрируется с другими инструментами. Сейчас перешли на AppScreener и Svace. Оба инструмента российской сборки: первый анализирует исходный код и исполняемые файлы, второй занимается статическим анализом на этапе сборки.
Анализ зависимостей (SCA) и Proxy-репозиторий
Анализ кода на использование и зависимость от компонентов open source включает проверку их лицензий и выявление известных уязвимостей. Ранее мы использовали инструмент Dependency Check, но со временем отказались от него из-за ограниченного функционала. Затем перешли к Dependency Track — платформу с собственным интерфейсом и плагином для Jenkins (в котором мы как раз автоматизируем процессы разработки). Этот инструмент поддерживает большее количество языков программирования по сравнению с предшественником, выполняет проверку лицензий и интегрируется в сборочные конвейеры.
Однако DT не поддерживались языки C и C++, которые мы используем. Не хватало нам и автоматических политик, которые бы запрещали использование библиотеки, если в ней находятся критические уязвимости. Эти и другие проблемы привели нас к тому, что теперь мы используем CodeScoring — российское решение для композиционного анализа программного обеспечения. Оно обеспечивает безопасную работу с open source, проверку совместимости лицензий и оценку качества кода в рамках команды. У данного продукта есть OSS Firewall, который блокирует сторонние компоненты в нашем прокси-репозитории Nexus согласно настроенным политикам. Приятным бонусом стала возможность проверять здесь же докер-образы, но об этом немного позже.
Динамический анализ (DAST) и фаззинг
Для динамического анализа (то есть на работающем приложении) мы используем:
OWASP ZAP — инструмент для тестирования безопасности веб-приложений;
Nessus — сканер уязвимостей, который анализирует сетевые приложения;
Burp Suite — еще один инструмент для тестирования безопасности веб-приложений;
Crusher — российский инструмент для выявления проблем с безопасностью. На Хабре про него есть достаточно подробная статья от наших коллег.
С недавних пор мы активно развиваем фаззинг в нашей компании. Основным помощником в этом является Sydr-fuzz — российский инструмент динамического анализа программ, который реализует гибридный фаззинг с использованием Sydr и современных фаззеров (libFuzzer и AFL++), а также автоматизирует этапы сбора покрытия.
Управление уязвимостями
Управление уязвимостями — это отдельная большая тема. Поэтому не буду останавливаться на этом подробно, лишь кратко опишу алгоритм и инструменты, которые мы используем:
Сканирование и обнаружение. Проводим регулярное сканирование кода и приложений для выявления уязвимостей.
Анализ и отчетность. С помощью платформы управления уязвимостями DefectDojo анализируем результаты сканирования и формируем отчеты о найденных уязвимостях. Платформа интегрируется с различными сканерами безопасности, поэтому работать с ней удобно.
Приоритизация. Оцениваем критичность уязвимостей и расставляем приоритеты для их устранения.
Рекомендации и устранение: стандарт ASVS, разработанный OWASP для проверки технических средств безопасности веб-приложений, предоставляет рекомендации по устранению найденных уязвимостей в порядке приоритета.
Мониторинг и контроль: постоянный мониторинг состояния безопасности помогает поддерживать высокий уровень защиты и оперативно реагировать на проблемы.
Контейнеры и безопасность
Отдельно расскажу, как мы обеспечиваем безопасность контейнеров. Сборка проектов происходит по-разному, но есть у них общая черта — так или иначе они связаны с контейнерами. В проектах есть базовые образы, на основе которых собираются итоговые, а также те, в которых компилируются приложения.
Уязвимости в Docker-образах можно условно разделить на:
Уязвимости базового образа и системных пакетов, включенных в этот образ;
Уязвимости в сторонних зависимостях;
Уязвимости непосредственно в коде приложений, которые запускаются в контейнерах;
Небезопасные инструкции для сборки образа.
Чтобы выявить первые два типа уязвимостей, мы использовали Trivy — это инструмент для сканирования контейнерных образов, однако сейчас перешли на Codescoring.
В дополнение к инструментарию мы выработали следующие рекомендации:
Минимизация привилегий. Не даем контейнерам больше прав, чем необходимо. Например, ограничиваем доступ к системным ресурсам;
Безопасные базовые образы. Используем проверенные базовые образы с минимальным набором необходимых пакетов;
Сканирование. Используем инструменты вроде Hadolint для проверки Docker-файлов на наличие небезопасных инструкций и потенциальных уязвимостей;
Изоляция контейнеров. Ограничиваем взаимодействие между контейнерами и используем безопасные сетевые настройки.
Отмечу, что сейчас со всеми проблемами — в коде, в контейнерах и пр. — мы работаем по одному алгоритму:
Регулярно проводим автоматизированное сканирование кода и контейнеров с использованием различных инструментов (упомянутые выше Codescoring, AppScreener и другие).
Анализируем результаты сканирования и формируем отчеты, которые отправляются ответственным разработчикам и командам безопасности для оперативного реагирования.
Оцениваем критичность уязвимостей с учетом их потенциального влияния на систему и данные. Приоритетные уязвимости устраняются в первую очередь.
Разрабатываем рекомендации по устранению уязвимостей и предоставляем инструкции разработчикам. Это включает обновление зависимостей, исправление кода и настройку конфигураций.
В случаях, когда уязвимость невозможно быстро устранить, мы применяем меры смягчения, такие как ограничение доступа к уязвимым компонентам или использование дополнительных средств защиты.
К чему мы пришли
Нам удалось построить единые для всех команд процессы разработки и обеспечить безопасность на всех ее этапах. При этом ни одного разработчика или безопасника не пострадало, хоть иногда нам и было нелегко. Свою роль в этом сыграла и поддержка со стороны бизнес-подразделений: наши заказчики заинтересованы в продуктах, прошедших сертификацию ФСТЭК, а она требует серьезного отношения к DevSecOps. Но об этом мои коллеги расскажут отдельно. Если вы столкнулись с похожими задачами внедрения DevSecOps, расскажите, как вы их решали, поделитесь опытом и инструментами.