FlawOpen

flawopen.com/Teardowns/cve-2026-87913-aws-security-agent-mcp-s3-bucket-ownership

● CVE-2026-87913 · CVSS 5.1 · Средний
Исследования · FlawOpen

CVE-2026-87913: утечка данных AWS MCP

Предсказуемый bucket мог принять закрытый архив сканирования в чужой аккаунт. Обновите сервер до 0.2.0 и проверьте владельца.[1], [2], [4]

💡 Простыми словами (ELI5)

Представьте курьера, который проверяет, есть ли здание по адресу, но не кому оно принадлежит. Другой человек может зарегистрировать адрес первым и получить посылку. S3 должен подтверждать ожидаемого владельца при проверке и загрузке.[2], [1]

Ключевые понятия и термины

MCP-сервер
Локальная служба с инструментами для ИИ-ассистента; они работают с правами серверного процесса.[3]
S3 bucket
Контейнер Amazon S3 с глобальным именем; имя не показывает аккаунт AWS-владельца.[2], [3]
ExpectedBucketOwner
Параметр S3, требующий проверить ожидаемый ID аккаунта-владельца перед операцией.[2], [8], [9]
CWE-283 и CWE-341
Слабости MITRE: непроверенное владение и предсказуемые значения; уведомление относит проблему к обеим.[8], [9]

Связи со стандартами

Анализ первопричины

MCP-сервер AWS Security Agent формирует имя bucket из ID аккаунта клиента и региона: security-agent-scans-<account-id>-<region>. AWS и сопровождающий указывают, что уязвимая версия проверяла только существование bucket, но не владение аккаунтом клиента. Имена S3 глобальны, ID аккаунтов общедоступны. Сторонняя учётная запись, первой зарегистрировавшая предсказуемое имя, могла получить закрытый архив, загруженный сервером; в нём могут быть исходники, учётные данные и состояние инфраструктуры. Это ошибка проверки владельца облачного ресурса и предсказуемого имени, а не prompt injection модели ИИ. Уязвимы версии 0.1.0–0.1.5; версия 0.2.0 добавляет ExpectedBucketOwner для S3 и останавливается при несовпадении. Обновление не освобождает уже зарегистрированное имя: проверьте владельца и не возобновляйте сканирование, если bucket чужой.

Имя бакета не подтверждает его владельца

ГраницаДокументированное условиеДействие оператора
Уязвимые версииЗатронуты awslabs.security-agent-mcp-server 0.1.0–0.1.5; в 0.2.0 добавлена проверка владельца.Обновитесь до 0.2.0 или новее и проверьте фактически запущенную версию пакета.
Предсказуемое имя бакетаИмя бакета для сканирования строится из ID аккаунта и региона; его может зарегистрировать другой аккаунт AWS.Считайте совпавшее имя адресом, а не подтверждением владения.
Межаккаунтная загрузкаУязвимый сервер мог принять бакет по имени без проверки владельца, а затем загрузить туда приватный архив сканирования.Перед сканированием или загрузкой проверьте, что бакет принадлежит ожидаемому аккаунту.
Исправленная проверка владенияExpectedBucketOwner заставляет S3 сверять владельца и при проверке, и при загрузке.Обновитесь, проверьте фактического владельца и остановите сканирование, если имя принадлежит третьей стороне; обновление не передаёт бакет.

Пошаговый сценарий атаки

Шаг 1

Запрос на сканирование получает исходный код

ИИ-клиент запрашивает сканирование; сервер архивирует проект с настроенной идентичностью AWS.[3], [2]

Шаг 2

Имя назначения предсказуемо

Имя строится из ID аккаунта и региона; ID не секрет, имена S3 глобальны.[1], [2]

Шаг 3

Проверка подтверждает только наличие

Сервер принимал bucket по имени, не подтверждая владение аккаунтом клиента.[2], [1]

Шаг 4

Архив может попасть в другой аккаунт

Если имя заранее зарегистрировал другой аккаунт, он мог получить частный архив с чувствительными данными.[2], [1]

Исходный код: Уязвимый vs Защищённый вариант

Это схема, а не дословная копия. Одного существования недостаточно: S3 должен сравнивать ожидаемый аккаунт владельца при проверке и записи. Берите его из аутентифицированной идентичности AWS и прекращайте операцию при несовпадении. После обновления отдельно проверьте владельца: оно не передаёт и не освобождает уже зарегистрированное имя. AWS указывает ExpectedBucketOwner для HeadBucket и PutObject: при несовпадении запрос завершается ошибкой 403. Используйте это как fail-closed-проверку, но прежде чем считать bucket чужим, разберите ошибки доступа через авторизованный способ проверки владельца.[2], [8], [9]

Фрагмент исходного кода: Пример AWS SDK по мотивам advisory; это не дословный diff исходного кода.

УЯЗВИМАЯ РЕАЛИЗАЦИЯ
# Упрощенная уязвимая схема: имя проверяется, но владелец — нет.
s3.head_bucket(Bucket=bucket_name)
s3.put_object(
    Bucket=bucket_name,
    Key=object_key,
    Body=archive_bytes,
)
БЕЗОПАСНЫЙ ИСПРАВЛЕННЫЙ ВАРИАНТ
# Привяжите каждую операцию к ожидаемой учетной записи владельца bucket.
expected_owner = sts.get_caller_identity()["Account"]
s3.head_bucket(
    Bucket=bucket_name,
    ExpectedBucketOwner=expected_owner,
)
s3.put_object(
    Bucket=bucket_name,
    Key=object_key,
    Body=archive_bytes,
    ExpectedBucketOwner=expected_owner,
)

Чек-лист по защите системы для инженеров

Источники