Supply Chain via Serverless Plugin Injection: когда плагины в безсерверных проектах становятся входной точкой

Supply Chain via Serverless Plugin Injection: когда плагины в безсерверных проектах становятся входной точкой

Безсерверные платформы ускоряют разработку, но вместе с ними мы тащим целый зоопарк плагинов: от полезных «обёрток» для деплоя до инструментов для локального запуска, упаковки слоёв и автогенерации ролей. В нормальный день они экономят часы, а в плохой — становятся идеальной площадкой для атаки на цепочку поставок. Ниже —  объяснение, как работает сценарий serverless plugin injection, почему он опасен, где именно находятся слабые места и что делать, чтобы не ловить «призраков» в продакшене.

Что такое serverless plugin injection простыми словами

Плагины для serverless-экосистемы — это расширения, которые автоматически исполняются в процессе сборки и деплоя. Они регистрируют «хуки» на этапах вроде before:package:createDeploymentArtifacts или after:deploy:deploy (терминология может отличаться, суть — одинаковая). Если в цепочку попадает вредоносный или скомпрометированный плагин, он получает доступ к переменным окружения, учётным данным CI, конфигурациям функций и может незаметно модифицировать то, что уходит в облако. Точку риска создаёт сам факт автоматического исполнения — разработчикам не нужно явно вызывать вредоносный код, он сработает «по расписанию».

Чтобы понимать механизмы, полезно держать в голове модель угроз цепочки поставок: разработчик → менеджер зависимостей → плагины/расширения → инфраструктура сборки → аккаунт облака. Этот контур разбирается многими практиками безопасной разработки, например в OWASP SAMM и NIST SSDF, которые рекомендуют формализовать контроль зависимостей и сборочных артефактов.

Где именно ломается защита: типовые точки входа

Serverless-проекты уязвимы не из-за магии, а из-за архитектуры процессов: много автоматизации, много доверия к стороннему коду и богатые разрешения у CI. Ниже — основные точки, где «впрыскивают» плагины.

  • Плагины Serverless Framework — подключаются в serverless.yml, тянутся из npm и исполняются через хуки. Официальная документация прямо описывает модель расширений и хуков, что важно для оценки рисков (справка по плагинам).
  • Lambda Layers/Extensions — слои и расширения AWS могут содержать бинарники, перехватывающие сетевые вызовы, логи и метрики. Их проще «подсунуть» через автоматическую упаковку слоёв в плагине. AWS поддерживает подписывание артефактов функций и слоёв через AWS Signer, это стоит включать в базовую гигиену (AWS Lambda Code Signing).
  • Azure Functions Extensions/NuGet — расширения подтягиваются через extensions.csproj и nuget-feed; подмена feed или зависимостей позволяет внедрить пост-build скрипты (документация по расширениям).
  • GCP Cloud Functions/Run зависимости — npm/pip/poetry/gradle, где supply chain риски аналогичны, а ci-скрипты нередко выполняют произвольные шаги до/после сборки (зависимости GCF).
  • Инструменты локального запуска — «offline»/«emulator» плагины, которые имеют доступ к .env и секретам для локальной отладки; заражение здесь часто переносится в CI через кэш и lock-файлы.

Как выглядит атака от начала до конца

Разберём правдоподобный сценарий, который встречается в разных вариациях в реальных командах.

  1. Подмена зависимостей плагина. Атакующий публикует одноимённый пакет с типографической ошибкой (typosquatting) или компрометирует аккаунт автора. Новый релиз выходит «минорным» обновлением, чтобы автоматом подтянулся в CI.
  2. Автовыполнение в хук. Вредонос добавляет хук before:deploy:deploy и незаметно внедряет дополнительный Lambda Layer, меняет переменные окружения, включает сетевой прокси или загружает секреты (AWS_ACCESS_KEY_ID, SLACK_WEBHOOK и т.д.).
  3. Закрепление. Плагин прописывает невидимый ресурс (например, отдельную роль/политику IAM или «временную» функцию-ретранслятор), чтобы вы пережили откат версии.
  4. Экфильтрация и lateral movement. Через расширение/слой проксируется трафик, собираются токены сервисов и метаданные, а затем злоумышленник двигается к соседним аккаунтам, бакетам и очередям.

Снаружи вы видите «зелёный» деплой. Внутри — изменённые артефакты и тихая телеметрия наружу. Именно поэтому в безсерверных проектах важно не только тестировать код функций, но и контролировать «мета-код» — плагины, шаблоны, слои и CI-шаги.

Признаки компрометации: на что смотреть в первую очередь

Хорошая новость: многие следы можно заметить, если знать, где искать. Ниже — список индикаторов и мест проверки.

  • Drift в IaC/конфигурации: в serverless.yml появились новые плагины или «опциональные» настройки, которых не было в MR/PR.
  • Неожиданные Layers/Extensions: у функций стали появляться дополнительные слои, изменились handler’ы, появились сторонние «observability» расширения без тикетов.
  • Сетевые аномалии: лямбды, у которых раньше не было исходящего трафика в Интернет (VPC egress=0), внезапно «стучатся» на домены, не связанные с бекендом.
  • Дрейф прав: у IAM-ролей функций возникают новые iam:PassRole, lambda:UpdateFunctionCode или доступы к KMS, которых не согласовывали.
  • CI-логи: в логах сборки и деплоя появились дополнительные шаги/скрипты («postinstall», «prepare», «prepack»), которых нет в репозитории.

Практика: демонстрационный «ловкий» плагин

Чтобы понимать механику, достаточно взглянуть на упрощённый пример. Пусть у нас есть проект на Serverless Framework с таким фрагментом конфигурации:

plugins:
   - serverless-offline
   - serverless-layer-packer
   - serverless-my-helper   # выглядит как мелочь
 

Внутри serverless-my-helper разработчик (или злоумышленник) регистрирует хук:

// index.js плагина
 class MyHelper {
   hooks = {
     'before:deploy:deploy': this.injectLayer.bind(this)
   };
   async injectLayer() {
     const env = process.env;
     // доступ к токенам, переменным окружения CI и т.п. 
     // изменение serverless.service.provider.layers, добавление env
   }
 }
 module.exports = MyHelper;
 

Если этот пакет прилетит из внешнего реестра без закреплённых версий и без аудита, вы получите «неучтённый код», который выполнится в самом центре жизненного цикла деплоя. Именно на это и рассчитан plugin injection.

Профилактика: базовый технический минимум

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

  • Жёсткие версии и lock-файлы. Включите «fail-on-update» при дрейфе package-lock.json/pnpm-lock.yaml, используйте разрешённые диапазоны версий только через ревью.
  • Частные прокси-реестры. Проксируйте npm/pip/nuget через приватный кэш (Verdaccio, Nexus, Artifactory) с allow-list для плагинов и автозапретом «неизвестных» пакетов.
  • Подпись и верификация артефактов. Для функций/слоёв включите подпись (AWS Signer для Lambda) и верификацию на стороне деплоя; для контейнеров и ZIP используйте Sigstore/cosign.
  • Происхождение билдов (SLSA). Опишите минимальный целевой уровень SLSA и храните provenance; это не бюрократия, а способ быстро отследить, откуда взялся артефакт.
  • SBOM и политика зависимостей. Генерируйте SBOM (CycloneDX, SPDX), фиксируйте её рядом с артефактом, блокируйте деплой при неожиданном появлении новых пакетных имён.
  • Чистый CI. Запрещайте сетевой egress step’ам, где он не нужен; используйте ephemeral runners; исключите npm install --no-frozen-lockfile в продакшн-пайплайне.
  • Минимальные права ролей. IAM-ролям функций не нужны права на управление самими функциями. Разделите «роль выполнения» и «роль деплоя».
  • Изоляция исходящего трафика в рантайме. Для AWS Lambda — VPC-изоляция и egress через контролируемый NAT/прокси, для Cloud Functions/Run — Cloud NAT/Serverless VPC Access с egress-политиками.

Политики и процессы: как не утонуть в исключениях

Технологии работают только при поддержке процессов. Ниже — набор простых правил, которые помогут команде не спорить каждый раз с нуля.

  • Реестр разрешённых плагинов. Ведение списка «approved plugins» с указанием версии, владельца и обоснования. Любое новое имя — только через тикет и ревью.
  • Регулярный «паспорт» функций. Раз в две недели формируйте отчёт: «какие слои/расширения/переменные у каких функций» и подписывайте его ответственным.
  • Правило «одно изменение — один MR». Обновление плагина не должно ехать вместе с бизнес-логикой. Так легче откатывать и анализировать риск.
  • Блокировка прод-среды по времени. Деплои в рабочее время и только при доступности всей дежурной цепочки (Dev, Sec, Ops), чтобы не обсуждать критичное в одиночку ночью.

Быстрый план внедрения контроля (пошагово)

Если хочется начать «с понедельника», берём следующий маршрут — он реалистичен для типичного проекта.

  1. Неделя 1: включить «frozen lockfile» во всех прод-пайплайнах; настроить приватный прокси-реестр; собрать список текущих плагинов и слоёв.
  2. Неделя 2: добавить генерацию SBOM (CycloneDX для npm/poetry/maven) и простое правило: если SBOM поменялась — деплой требует ручного подтверждения.
  3. Неделя 3: включить подпись артефактов (AWS Signer или cosign для контейнеров/ZIP) и валидацию на этапе деплоя.
  4. Неделя 4: обрезать egress в CI и у функций, которым он не нужен; внедрить отчёт по изменившимся слоям/расширениям.
  5. Неделя 5+: внедрить политику «approved plugins», проиграть tabletop-учения: как команда реагирует на компрометацию плагина.

Инструменты и сервисы, которые реально помогают

Выбор зависит от стека, но уместно упомянуть несколько полезных направлений.

  • Управление зависимостями: приватный npm-прокси (Verdaccio/Nexus/Artifactory), политика «only approved scopes».
  • Анализ SBOM: CycloneDX CLI, Syft/Grype, Dependency-Track — автоматическая проверка дрейфа и уязвимостей.
  • Подпись и provenance: Sigstore/cosign, in-toto, policy-enforcement в CI и на стадии деплоя.
  • Автообновления под контролем: Renovate/Dependabot с правилами «no auto-merge for plugins», отчётами и батчингом патч-обновлений.
  • Контроль рантайма: egress-контроль (NAT + egress-ACL), логирование DNS, alert на «новые» домены из функций.

Как проверить себя: мини-чек-лист

Если времени мало, пройдитесь по этому списку — он помогает быстро понять, насколько вы близки к «взрослой» модели управления плагинами.

  • Lock-файлы обязательны, сборка падает при несоответствии.
  • Плагины/слои идут только из приватного прокси-реестра.
  • Есть список «approved plugins» и процесс добавления новых.
  • Каждый деплой сопровождается SBOM и подписью артефакта.
  • CI не имеет исходящего трафика без явной необходимости.
  • Функции без интернет-нужды — без egress в Интернет.
  • Срабатывает алерт при появлении нового слоя/расширения у функции.

FAQ: коротко о типичных возражениях

«Но у нас быстрый релизный цикл, мы не можем тормозить деплой на каждой обнове плагина».
Ответ: батчите обновления, держите два окна в неделю для «поставки пакетов», используйте «canary-проект» для теста обновлений плагинов до продакшена.

«Подпись артефактов — это слишком сложно».
Ответ: начните с минимальной схемы — подпись только прод-артефактов и валидация на деплое. AWS Lambda поддерживает встроенную проверку подписей (док-во).

«Вредоносный плагин всё равно сможет уйти в сеть».
Ответ: не сможет, если у CI нет egress, а функции — в приватных подсетях с управляемым NAT и egress-ACL. Делайте сеть «по умолчанию закрытой».

Итоги

Serverless plugin injection — не экзотика, а закономерный эффект нашей любви к автоматизации. Хорошая новость в том, что защита укладывается в понятные шаги: фиксируйте происхождение артефактов, ограничивайте источники зависимостей, режьте исходящий трафик там, где он не нужен, и относитесь к плагинам как к коду с тем же уровнем недоверия, что и к любому внешнему компоненту. Тогда плагины снова станут тем, чем должны быть — ускорителями, а не «тайными дверями» в продакшен.

Полезные ссылки

AWS Lambda Azure Functions GCP plugin injection serverless Serverless Framework supply chain безопасность цепочки поставок
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.

Эксплойт без патча? Узнай первым

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