Перейти к содержимому

Уязвимости S3-интеграций: 10 ошибок веб-приложений и способы защиты

Начинаем в багбаунти: 10 неочевидных уязвимостей S3-интеграций в веб-приложениях

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

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

Что такое S3 и почему он опасен при неправильной настройке

S3 - это интерфейс взаимодействия с объектным хранилищем. Изначально технологию разработала Amazon, но со временем S3 API стал фактическим отраслевым стандартом. Сегодня похожие интерфейсы поддерживают многие облачные и локальные решения.

К базовым операциям относятся:

- PUT - создание или изменение объекта;
- GET - получение файла;
- DELETE - удаление объекта;
- GET для корня бакета - получение списка объектов.

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

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

Авторизация и подпись запросов

Для защищенных операций используются ключ доступа и секретный ключ. Клиент формирует подпись на основе метода, пути, заголовков и других параметров запроса. В старом варианте Signature Version 2 применялся HMAC-SHA1, после чего результат кодировался в Base64. В современной схеме Signature Version 4 процесс сложнее и включает регион, дату, область действия ключа и несколько этапов вычисления подписи.

Отдельный механизм - временные подписанные URL. Они позволяют выдать доступ к конкретному объекту на ограниченный срок без передачи пользователю постоянных учетных данных.

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

Два распространенных варианта интеграции

Доступ через S3-клиент в коде

В этом случае приложение самостоятельно обращается к хранилищу. В коде указываются endpoint, учетные данные, имя бакета и параметры операции. Пользователь обычно влияет только на ограниченный набор значений: имя файла, содержимое, MIME-тип или путь объекта.

Такой вариант относительно проще контролировать, если применяются строгая валидация, отдельные роли и минимальные права.

Доступ через прокси-сервер

Другой подход - публикация хранилища через nginx или аналогичный прокси. Запрос пользователя передается дальше почти без изменений. Если прокси разрешает все HTTP-методы, заголовки и варианты путей, наружу могут выйти штатные возможности S3, которые разработчик не планировал предоставлять.

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

10 типовых уязвимостей S3-интеграций

1. Публичный листинг бакета

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

Безопасная конфигурация должна запрещать листинг, если он не нужен бизнес-логике. Доступ к объектам следует выдавать по конкретным ключам или временным ссылкам.

2. Ошибочное использование AuthenticatedUsers

В ACL группа `AuthenticatedUsers` нередко понимается как "пользователи моего аккаунта". На практике она может означать всех пользователей, прошедших аутентификацию в соответствующей S3-системе.

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

3. Загрузка исполняемого HTML или SVG

Разрешение загружать файлы без проверки типа и содержимого создает риск хранимой XSS. Особенно опасны HTML, SVG, XML и некоторые форматы офисных документов.

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

4. Подмена содержимого через повторный PUT

Если пользователь может предсказать имя объекта, а сервер не контролирует право перезаписи, один клиент способен заменить файл другого. Это критично для аватаров, документов, JavaScript-ресурсов и публичных изображений.

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

5. Удаление объектов через прокси

Прокси иногда передает DELETE так же, как GET. Если авторизация проверяется только на уровне веб-приложения, а сам S3 endpoint доступен напрямую, пользователь может удалить чужие данные.

Необходимо явно разрешать методы, которые действительно используются. На публичном маршруте чаще всего достаточно GET и HEAD, а PUT, POST и DELETE следует вынести на отдельные защищенные endpoints.

6. Обход правил rewrite

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

Особое внимание требуется уделять нормализации URL, обработке `%2F`, двойных слэшей, точек и различий между `proxy_pass` со слэшем и без него. Маршрут нужно проверять после декодирования и до передачи в S3.

7. Манипуляции с Host и виртуальным хостом

S3-совместимые системы могут выбирать бакет по значению Host, пути или комбинации этих параметров. Если прокси без проверки передает пользовательский Host, запрос способен попасть не в тот контейнер.

Следует жестко фиксировать допустимые домены, не доверять входному Host и явно задавать upstream. Нельзя строить адрес backend на основе пользовательского значения без белого списка.

8. Отравление кэша

Неправильное сочетание прокси-кэша, заголовков и параметров запроса может привести к тому, что один пользовательский ответ будет показан другим. Риск возрастает при кэшировании объектов с персонализированным содержимым, нестандартными Content-Type или влияющими на ответ заголовками.

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

9. Утечка метаданных и служебных заголовков

S3-объект может содержать пользовательские метаданные: имя владельца, внутренний идентификатор, путь на сервере, временные токены и диагностическую информацию. При проксировании эти значения иногда становятся доступны клиенту.

Перед публикацией объекта необходимо удалять внутренние метаданные и проверять, какие заголовки возвращаются наружу. Отдельно контролируются `Content-Disposition`, `Content-Type`, `Cache-Control` и пользовательские `x-amz-meta-*`.

10. Неправильные временные URL

Подписанные ссылки часто создаются "на всякий случай" с длительным сроком действия. Если URL утечет через историю браузера, журналы, Referer или мессенджер, доступ сохранится до завершения срока.

Срок действия должен соответствовать реальной задаче: минуты для загрузки, короткий интервал для скачивания, одноразовый токен для чувствительных документов. Желательно ограничивать метод, объект, размер и тип операции.

Как строится цепочка атаки

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

Поэтому аудит нельзя сводить к проверке одного флага "public". Нужно анализировать весь путь запроса: браузер, приложение, nginx, балансировщик, S3-шлюз и политику доступа.

Практический чек-лист защиты

- запретить публичный листинг без явной необходимости;
- использовать отдельные роли для чтения, загрузки и удаления;
- не хранить постоянные секретные ключи в клиентском коде;
- выдавать временные URL с минимальным сроком действия;
- проверять расширение, MIME-тип и содержимое файлов;
- размещать пользовательские файлы на отдельном домене;
- ограничивать HTTP-методы на прокси;
- фиксировать допустимые Host и upstream;
- тестировать URL после декодирования и нормализации;
- отключать кэширование приватных объектов;
- удалять служебные метаданные;
- вести журнал загрузок, удалений и выдачи подписанных ссылок;
- регулярно проверять ACL и bucket policy автоматически.

S3 сам по себе не является небезопасной технологией. Большинство проблем появляется на стыке трех компонентов: модели доступа, веб-приложения и прокси-сервера. Чем меньше возможностей передается наружу, тем ниже риск. Правильная архитектура должна разрешать только те операции, которые необходимы конкретному сценарию, а все остальные методы, заголовки и пути - блокировать по умолчанию.

Прокрутить вверх