Привет, читатели Habr! С вами Анастасия Березовская, инженер по безопасности процессов разработки приложений в Swordfish Security. Сегодня мы вновь будем говорить об особенностях  статического сканирования, но на этот раз переключим фокус с программного кода на код инфраструктурный. 

Частично этот вопрос обсуждался в статье нашего коллеги про безопасность контейнеризированных приложений в DevSecOps. В этой статье будут рассмотрены краткие теоретические сведения о  подходе “Инфрастуркутра как кодˮ, место безопасности IaC в цикле DevSecOps, методы статического анализа конфигурационных файлов и ключевые особенности работы с инструментом KICS.

Еще раз об IaC

В этом разделе приведем краткое описание IaC. Если вы уже давно с    ним знакомы, то можете сразу переходить к части, посвященной безопасности. А для тех, кто в танке, а, вернее, не в контейнере, выделим   часть статьи под теорию.

Использованием подхода Infrastructure as Code (iaC) уже никого не увидишь: он встречается как в новых стартапах, так и в крупных компаниях. Одно из основных его преимуществ — переиспользование. Инженер вместо ручного повторения в консоли, которое идеально составлено под техническое задание и удовлетворяет всем лучшим практикам последовательности команд настройки, использует средства автоматизации управления инфраструктурой. Скрипт ‘install.shʼ можно назвать прародителем такого подхода.

В строгом же смысле системы IaC должны удовлетворять целому ряду требований.  Выделяют три наиболее важных принципа для таких систем:

  • Идемпотентность: способность операции производить один и тот же результат независимо от того, сколько раз она выполняется.

  • Воспроизводимость: одинаковый код IaC всегда создает идентичную инфраструктуру.

  •  Компонуемость: возможность создавать сложные системы из более простых, повторно используемых компонентов.

С точки зрения практики эти принципы применимы ровно как тройка «конфиденциальность, целостность и доступность» в информационной безопасности. Теоретическая база — она    такая. Мы еще вернемся к этим пунктам.

Существуют две распространенные классификации IaC: по функциональному назначению и по типу языка IaC.

По функциональному признаку, то есть относительно задач, которые решают инструменты IaC, их разделяют на две группы. К первой относятся инструменты управления инфраструктурой, или, как еще их называют, инструменты оркестровки. Они создают, изменяют и уничтожают различные компоненты инфраструктуры, такие как виртуальные машины, хранилища и сетевые компоненты. Управление может происходить на уровне машинных образов — Packer, на уровне виртуальных машин — Cloudify, Terraform, Vargant, и на уровне контейнерных технологий — Docker Swarm, Kubernetes.

Ко второй группе относят инструменты управления конфигурацией. Они устанавливают, обновляют и управляют программным обеспечением в компонентах инфраструктуры. В эту группу входят, например, Ansible, Chef, Puppet.

Вторая классификация гораздо чаще встречается в литературе. Она разделяет инструменты по основополагающей для языка описания IaC -парадигме: декларативная и императивная (иногда ее еще называют процедурной). Все наверняка уже встречали это в программировании.

? Интересная историческая справка

При описании языков программирования мы не редко употребляем слово “парадигмаˮ. Оно приобрело свой современный смысл — ведущую систему идей и понятий, исходную концептуальную схему — только в 1960-х годах вместе с работой Томаса Куна в работе “Структура научных революцийˮ. Раньше это слово означало “шаблонˮ, “примерˮ, “образецˮ и использовалось чаще в риторике, лингвистике и грамматике.

Императивный подход: как достигнуть желаемого. Пользователь определяет последовательность действий, которые система будет выполнять для достижения желаемого состояния инфраструктуры. Основное внимание уделяется тому, “какˮ это состояние достигается. Императивные языки IaC включают такие инструменты, как AWS CDK, Pulumi, Puppet, Ansible и Chef.

Декларативный подход: что должно быть достигнуто. Пользователь задает желаемое состояние системы. Определение последовательности шагов для преобразования инфраструктуры в соответствии с этим состоянием — это задача инструмента IaC. Решения Terraform, AWS CloudFormation и Azure Resource Manager используют декларативный подход.

Второй подход на первый взгляд кажется лучше. Во-первых, конфигурационные файлы отображают текущее состояние инфраструктуры. Во-вторых, он менее трудоемкий, ведь большая часть работы делается автоматически. Однако второй подход дает большую управляемость и гибкость. Детальный контроль над процессом позволяет достичь более точных и специфичных результатов. Именно поэтому императивный подход не вытеснил полностью первый.

Немного душноты: вводя такую классификацию, корректнее говорить о парадигме именно языка описания, а не о самой системе. Это различие связано с тем, как сам язык описывает и управляет инфраструктурой.

Относительно использования языков устоялось две тенденции. Первая — это применение языков программирования общего назначения (GPL) для управления инфраструктурой. Примерами этого являются Pulumi и AWS CDK, которые поддерживают такие языки, как Java, JavaScript и Go. Другой тенденцией являются доменно-ориентированные языки (DSL), которые предназначены для моделирования определенной области, в данном случае —инфраструктуры. К ним относятся Terraform с HCL, CloudFormation и Openstack, использующие YAML или JSON.

Найденная нами статистика по распространенности различных типов IaC датируется 2019 годом, а с тех пор много воды утекло. Тогда наиболее популярным инструментом был Docker с 59,0% использованием среди разработчиков. Наиболее популярными облачными инструментами IaC были Ansible (52,2%), Chef (36,3%) и Terraform(34,1%). Само исследование весьма интересно к прочтению. Оно основано на 44 интервью с DevOps-инженерами, которые поделились, как они создают и поддерживают IaC-код, какие практики считают успешными и проблемными, а также какие плюсы и минусы видят в существующих инструментах.

? Безопасность & IaC

Общие советы по безопасности не сильно отличаются от любой другой сферы. Дабы обеспечить полноту исследования нашей статье, вкратце перечислим их:

  • Необходимо вовремя обновлять соответствующее ПО (в текущих реалиях, с  поправкой на подобающее поведение некоторых зарубежных вендоров ?).

  • Нужно следить за использованием внешних компонент (тренд докладов  прошлых лет).

  • Важно грамотно управлять учетными записями (разделение аккаунтов, минимизация    привилегий — куда же без строгой аутентификации).

  • Необходимо проводить логирование и мониторинг.

— Скучно! Я это уже всё видел(а)! ?

Действительно, верхнеуровневые абстракции. Да и где здесь особенности подхода “как кодˮ? Давайте переключимся на императивный язык описания. Концепции IaC отлично ложатся на DevOps. Поэтому для каждого из этапа всем известной восьмерки можно выделить пункты, которые характерны непосредственно для IaC. Подробно об этом написано в статье Best Practices for Securing Infrastructure as Code IaC in the DevOps SDLC.

В блоге Gaurdian рекомендуется руководствоваться фреймворками по обеспечению безопасности.

Автоматизация дошла и до этапа планирования угроз! Здесь можно упомянуть такой инструмент, как IaCAssist от ThreatModeler. Он интегрируется как плагин в среду разработки и преобразует конфигурационные файлы в полноценные модели угроз. Анализирует их, выдает потенциальные и предлагает рекомендации по улучшению безопасности.

ThreatCanvas — аналогичный инструмент для облачных приложений, в частности, для AWS, Azure и Google Cloud Platform (GCP). У него есть бесплатная версия ThreatCanvas Lite. Более функциональный и приятный по дизайну — инструмент IriusRisk, который уже лежит на территории подхода Security as Code. У него также есть бесплатная версия iriusRisk Community Edition. В обоих инструментах встроен ИИ-ассистент, который помогает построить схему по словесному описанию. Во второй можно экспортировать схему формата draw.io. В них есть интеграция с Jira. Оба приложения нам показались отличным вариантам для быстрого наброска по моделированию угроз. Однако обе бесплатные версии доступны только онлайн, что может идти в противоречие с внутренней политикой безопасности вашей компании.

К сожалению, платные версии в наших руки не успели попасть, а Open Source  аналогов на глаза не попадалось. Если вы имели опыт работы с подобными инструментами или знаете хорошие открытые аналоги, расскажите о них в комментариях. ✍

Далее переходим по восьмерке к более технической части. Но сначала, для лучшего понимания, опишем, как выглядит типичный день из жизни DevOps- специалиста.

  • Инженер DevOps пишет сценарий IaC.

  • Инженер DevOps фиксирует изменения сценария IaC в системе контроля версий (VCS).

  • Изменения запускают статические тесты в инструменте CI.

  • Инструмент CI включает изменения сценария IaC, если тесты дают положительный результат (и отклоняет изменения в противном случае).

  • Инструмент CI развертывает обновленный сценарий в sandbox и/или тестовом окружении.

  • Инструмент CI развертывает обновленный сценарий IaC на целевых серверах.

Рисунок 1. Один день из жизни DevOps'а
Рисунок 1. Один день из жизни DevOps'а

На этом этапе мы наконец можем начать использовать давно знакомые разработчику приложений преимущества, такие как повторное использование кода, совместная работа, тестирование и статический анализ кода.

По схеме 1 можно выделить первую сущность для анализа — шаблон. Для приведения его в порядок мы применяем уже известные нам методы: линтеры и статические анализаторы. Как отдельные подсущности некоторые авторы выделяют секреты в шаблонах, для которых могут быть использованы отдельные инструменты поиска секретов.

На этапе разработки эти проверки вначале локально достигаются с помощью плагинов для IDE и Pre-commits hooks. В CI/CD тестирование повторяется.

Рассмотрение дальнейших этапов восьмерки на сегодня мы опустим и перейдем к более подробному рассмотрению методов статического анализа.

? Статический анализ шаблонов

Здесь поговорим об основных методах статического анализа инфраструктурного кода. Эти методы частично перешли из статического анализа кода.

Запахи кода (ориг. Code Smells) в контексте IaC — это части кода, которые могут сигнализировать о потенциальных проблемах с качеством, безопасностью или удобством поддержки вашей инфраструктуры. Они бывают нескольких типов.

Запахи реализации — конкретные практики кодирования в скриптах. Они могут влиять на читаемость и удобство работы с кодом. Например, длинные скрипты или неправильное форматирование.

Запахи дизайна — проблемы в архитектуре или структуре скриптов. Они могут затруднить поддержку и масштабирование инфраструктуры. Примеры включают дублирование кода или слишком сложные конфигурации, которые трудно понять.

Если прошлые два типа были скорее задачей линтера, то запахи безопасности — паттерны, которые ведут к уязвимостям в архитектуре. Секреты или использование пустых значений для учетных записей — это классические примеры.

Поиск “запаховˮ является одной из наиболее популярных, а вместе с тем и изученных тем в области анализа IaC-скриптов в академическом сообществе. Исследователи отмечают, что последний тип встречается довольно часто: в некоторых проектах до 32.9% IaC-скриптов могут содержать хотя бы один из них.

Запахи кода могут быть как специфичными для определенных фреймворках (например, Puppet или Chef), так и общими для всех инструментов IaC. Здесь примерами могут быть инструменты Puppeteer-Link и FoodCritic соответственно. Существуют же инструменты, такие как IaCSec и  GLITCH, которые направлены на поиск недостатков в нескольких языках.

Волна популярности машинного обучения и LLM в частности не прошла стороной и затронула рассматриваемую нами сегодня тему. Так, например, инструмент DeepIaC использует глубокое обучение (сверточные нейронные сети) для обнаружения анти-шаблонов в скриптах Ansible. Как утверждают создатели, DeepIaC показал высокую точность при тестировании на выборке из более чем 18,000 скриптов, извлечённых из репозиториев GitHub, с точностью от 79% до 92%. Для обнаружения дефектов также применяются метрики кода и процесса, которые используются в алгоритмах машинного обучения. Они помогают создать «профиль» кода, который можно использовать для предсказания наличия дефектов. Здесь могут встретиться такие методы, как Bag of Words (BOW)и TF-IDF. Random Forest. Их обсуждение далеко выходит за рамки нашей статьи, но, если вам интересно, подробности есть в статье.

Интересным также может быть SecGuru — это инструмент, разработанный для анализа политик безопасности в облачных инфраструктурах Azure. В его основе лежит модельная проверка, то есть метод формальной верификации, который позволяет автоматически проверять соответствие системы заданным свойствам. SecGuru использует эту технологию для анализа политик контроля доступа (ACL) в облачных инфраструктурах Azure.

К сожалению, несмотря на строгое обоснование принципов работы этих инструментов, они не вышли за пределы научных статей и почти не встречаются в промышленном использовании. Какими же инструментами пользуются крупные компании?

KICS для безопасности IaC

Наиболее популярными инструментами являются KICS от Checkmarx, Trivy  от Aqua Security и Checkov от Bridge. По принципу работы они весьма похожи друг на друга. Однако наиболее выгодным к использованию нам показался именно KICS. Он использует библиотеку правил, написанных на Rego. Правила можно добавлять и изменять. Более того, эта библиотека оказалась наиболее полной — она включает в себя основные best practice, рекомендованные для Docker, Kubernetes и др. Кроме того, инструмент активно поддерживается   сообществом (в отличии от озвученных ранее проектов).

Рисунок 2. Возможности интеграции KICS в процесс разработки
Рисунок 2. Возможности интеграции KICS в процесс разработки

Согласно схеме на рисунке 1, KICS можно использовать в трех обозначенных нами местах:

  • IDE Plugin: KICS предоставляет плагин для VS Code.

  • Pre-commit Hooks: его можно без труда включить в уже существующие проверки.

  •  CI/CD: инструмент предлагает большой список интеграции — Azure Pipelines, Bamboo, Bitbucket Pipelines, CircleCI, Github Actions, GitLab CI, Jenkins, TeamCity, Travis, AWS CodeBuild — вы здесь, наверняка, нашли тот, что используется у вас в компании.

Локальный запуск KICS выполняется простой командой:

docker run -t -v {path_to_scan}:/path checkmarx/kics scan -p /path

В качестве небольшого тестового примера напишем Dockerfile:

FROM python:3.11-slim

WORKDIR /app

COPY . .

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 8000

CMD ["python", "app.py"]

А так будут выглядеть результаты работы:

Результаты работы
Scanning with Keeping Infrastructure as Code Secure v2.1.3


Preparing Scan Assets: Done                                                     
Executing queries: [---------------------------------------------------] 100.00%



Healthcheck Instruction Missing, Severity: LOW, Results: 1
Description: Ensure that HEALTHCHECK is being used. The HEALTHCHECK instruction tells Docker how to test a container to check that it is still working
Platform: Dockerfile
CWE: 710
Learn more about this vulnerability: https://docs.kics.io/latest/queries/dockerfile-queries/b03a748a-542d-44f4-bb86-9199ab4fd2d5

	[1]: ../../path/Dockerfile:1

		001: FROM python:3.11-slim
		002: 
		003: WORKDIR /app


Missing User Instruction, Severity: HIGH, Results: 1
Description: A user should be specified in the dockerfile, otherwise the image will run as root
Platform: Dockerfile
CWE: 250
Learn more about this vulnerability: https://docs.kics.io/latest/queries/dockerfile-queries/fd54f200-402c-4333-a5a4-36ef6709af2f

	[1]: ../../path/Dockerfile:1

		001: FROM python:3.11-slim
		002: 
		003: WORKDIR /app



Results Summary:
CRITICAL: 0
HIGH: 1
MEDIUM: 0
LOW: 1
INFO: 0
TOTAL: 2

Как мы видим, он указывает на два явных недостатка файла образа: отсутсвие проверки успешности запуска (healthcheck) и отсутствие переназначения пользователя.

Заключение

Согласно статистике, собранной организацией Snyk в 2021 году, 40% компаний не используют тестирование IaC в пайплайнах. При этом 32% организаций считают, что это практика способна значительно улучшить состояние безопасности инфраструктуры в компании. Отсюда следует очевидная рекомендация использовать преимущества IaC и в безопасности, важную роль в которой играют линтеры и инструменты статического анализа кода. Они позволяют автоматически выявлять потенциальные проблемы безопасности, несоответствие лучшим практикам и ошибки конфигурации еще на этапе разработки. Согласно исследованиям, использование линтеров и статического анализа может снизить количество уязвимостей в IaC на 70- 80%.

Использование инструментов вроде KICS в сочетании с другими практиками безопасности IaC может значительно повысить уровень защищенности инфраструктуры и снизить риски, связанные с неправильной конфигурацией.

Комментарии (0)