Статья Полное погружение в контроль доступа к AWS S3 - получение контроля над вашими ресурсами

g00db0y

g00db0y

Red Team
11.06.2018
94
393
Статья является переводом. Оригинал находится

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:
1580399590202.png
  • DNS-вход домена может раскрыть имя бакета напрямую, но только если хост указывает непосредственно на S3.
  • Попробуйте получить доступ к root-URL. Если включен индексный список (public READ в Bucket ACL), вы сможете увидеть имя домена, определенное в <Name>-елементе.
Мы определили несколько способов, которые помогут фактически открывать S3-бакеты независимо от прокси перед ним. Мы уведомили AWS об этих способах и выбрали не упоминать их выше.

Если вы все же найдете домен, который указывает на бакет, но не можете получить его имя, попробуйте fully qualified domain name (FQDN) (на рус. «полностью доверенное доменное имя») в качестве имени бакета, это обычная установка, при которой бакет указывается как домен.

Если это не сработает, попробуйте:
  • Погуглите домен и посмотрите, не раскрывает ли что-нибудь имя бакета.
  • Посмотрите на заголовки ответов объектов в бакете, чтобы увидеть, есть ли у них какие-то данные, раскрывающие имя.
  • Просмотрите содержимое и убедитесь, может ли оно относится к какому-либо бакету. Бывали случаи, когда ресурсам присваивались метки с именами бактов и датой, когда они были развернуты.
  • Брутфорс. Будьте аккуратными здесь, не стреляй тысячами запросов только для того, чтобы найти бакет. Постарайтесь быть умнее, в зависимости от имени домена, указывающего на него, и фактической причины его существования. Если бакет содержит аудиофайлы для ACME на домене media.acme.edu, попробуйте media.acme.edu, acme-edu-media, acme-audio или acme-media.
Если ответ на $bucket.s3.amazonaws.com показывает NoSuchBucket, то бакет не существует. Существующий бакет ответит вам ListBucketResult или AccessDenied.

(Вы также можете наткнуться на 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:

1580400336440.png


Мы все еще можем прочитать конкретный объект:
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 может быть разной для каждого объекта, независимо от настроек на бакете.

READ_ACP

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

READ_ACP все равно будет работать на определенных объектах внутри бакета, даже если Object Access READ_ACP не установлен на complete-бакете.

Это означает, что READ_ACP может быть разным для каждого объекта, независимо от настроек на самом бакете.

1580400288188.png

Bash:
$ aws s3api get-object-acl --bucket test-bucket --key read-acp.txt      
{
    "Owner": {
        "DisplayName": "fransrosen",
        ...
WRITE

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

Запись не будет работать на определенных объектах внутри бакета, если Object Access WRITE не установлен на complete-бакете:

1580400507845.png

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
Однако, если WRITE установлен на бакет, то все объекты будут подчиняться и не смогут решить, должны ли они быть доступны для записи или нет:

1580400255668.png

Bash:
$ aws s3api put-object --bucket test-bucket --key write.txt --body write.txt
{
    "ETag": "\"1398e667c7ebaa95284d4efa2987c1c0\""
}
Это означает, что WRITE может быть проверено на бакете двумя способами: либо загрузив случайный файл, либо изменив существующий. Изменение существующего файла – деструктивний вариант, и не стоит его использовать вообще. Ниже мы объясним, как это проверить, не делая деструктивного вызова, вызвав ошибку в промежутке между проверкой контроля доступа и фактической модификацией файла.

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
Затем мы пытаемся изменить бакет ACL:
Bash:
$ aws s3api put-bucket-acl --bucket test-bucket --grant-full-control emailaddress=frans@example.com && echo "success"
success
Первоначальный владелец ведра теперь увидит это:

1580400665850.png

(Будучи владельцем, они все равно смогут изменить политику бакета, но это странный действие в любом случае).

Теперь мы можем контролировать все:
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\""
}
Крайне интересно, что WRITE_ACP на самом деле все еще будет работать на определенных объектах внутри бакета, даже если Object Access WRITE_ACP не установлен на complete-бакете:

1580400744748.png

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
Кроме того, здесь применяется противоположность WRITE, наличие WRITE_ACP в конфигурации бакета не означает, что вы непосредственно имеете WRITE_ACP на объекте:

1580400772616.png

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
Однако, выполняя следующие шаги при наличии WRITE_ACP на бакете, вы все равно получите полный доступ к информации любого объекта, заменив новым содержимым:
  • Изменение бакета 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
Так как WRITE все еще должен быть установлен на бакет, то вы не сможете обновить WRITE_ACP на объекте, чтобы дать себе WRITE на том же объекте:
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
1580402544310.png


Поэтому, это все равно даст вам:
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
Однако, вы все еще можете удалить все права ACP на объекте, сделав объект полностью приватным, что остановит его обслуживание, дав 403 Forbidden.

WRITE_ACP, к сожалению, можно проверить, только протестировав написание новых ACP на бакете или объекте. Изменение существующего файла – деструктивний вариант, и не стоит его использовать вообще. Мы не смогли найти более лучшего способа для проверки этих ACP.

FULL_CONTROL

Это политика, которая сочетает в себе различные правила. Однако, WRITE все равно не будет работать на объекте, пока на бакете это все еще установлено, даже если эти разрешения установлены на объекте.

Уязвимые сценарии

Следующие сценарии являются случаями, когда компания может пострадать.

1. Бакет, используемое на домене, принадлежащем компании.

Вы нашли бакет, которое обслуживается субдоменом или доменом компании.

Вам следует проверить:
  • BUCKET READ
Список файлов в ведре. Таким способом может быть раскрыта конфиденциальная информация.
  • BUCKET READ-ACP
Давайте взглянем на ACP и подумаем, сможем ли мы определить, что бакет является уязвимым, без каких-либо действий. Если мы увидим, что у AllUsers или AuthenticatedUsers есть набор WRITE_ACP, то мы знаем, что можем получить полный контроль над бакетом, ничего больше не делая.
  • BUCKET WRITE (Симуляция использования invalid-MD5 hack)
Если мы сможем загрузить новый файл на баке, это также говорит нам о том, что мы можем перезаписать любой объект на бакете. Однако, если мы хотим избежать загрузки чего-либо, мы можем попробовать следующее, не загружая ничего, но все равно увидеть, что мы можем это сделать:

При выполнении подписанного PUT-запроса к бакету, у нас появляется возможность добавить Content-MD5, сообщающий AWS контрольную сумму загружаемого файла. Оказывается, что эта проверка происходит следующим образом:
  1. Убедитесь, что у пользователя есть доступ к записи файла.
  2. Убедитесь, что контрольная сумма MD5 соответствует содержимому.
  3. Загрузите файл.
Так как контроль checksum (контрольной суммы) происходит после того, как мы знаем, что у нас есть доступ к файлу. Поэтому, перед тем, как на самом деле изменить его, нам не нужно записывать что-то в файл, чтобы знать, что у нас есть право на это.

Следующий 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>
Таким образом, мы не изменим содержимое, и убедимся, что можем это сделать. К сожалению, это работает только на WRITE, а не на WRITE_ACP, насколько нам известно.
  • BUCKET WRITE-ACP
Самый опасный. Полностью модернизируемый до полного доступа к ведру. Разрушительный вызов. Будьте осторожны. Единственный способ сделать это правильно - сначала выяснить, как бакет ведет себя, чтобы не сломать ни одного текущего ACP. Помните, что вы все еще можете иметь доступ к WRITE_ACP, даже если у вас нет доступа к READ_ACP.

  • OBJECT READ
Мы можем попробовать прочитать содержание интересующих нас файлов, найденных с помощью BUCKET READ.
  • OBJECT WRITE
Нет необходимости тестировать это, так как BUCKET WRITE передает нам достаточно информации. Если BUCKET WRITE выдаст ошибку, то объект не будет доступен для записи, и если BUCKET WRITE не выдаст ошибку, то объект, соответственно, будет доступен для записи.

Однако, если в компании, использующей BUCKET WRITE, есть приложение, куда пользователи могут загружать файлы, посмотрите на реализацию того, как они делают фактическую загрузку файла в S3. Если компания использует выгрузку с помощью , обратите особое внимание на политику Condition Matching $key и Content-type. В зависимости от того, используют ли они start-with, вы можете изменять тип содержимого на HTML/XML/SVG/и т.д., или изменять местоположение загружаемого файла.
  • OBJECT WRITE-ACP
Мы можем попробовать модифицировать 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) в зависимости от того, где используются исполняемые файлы и если/кем они загружаются.
2. Активы из бакета, используемые компанией

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

Существуют проекты такие как , которые пытающиеся автоматизировать поиск этих активов. Однако, 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);
Который выдаст нам все активы на странице, которые мы можем использовать, чтобы выяснить, обслуживаются-ли они со стороны S3, или нет:

1580403102206.png


Для этого, вы должны проверить:
  • 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) в зависимости от того, где используются исполняемые файлы и если/кем они загружаются.
3. Bucket randomly found (или на рус. бакет найден случайно), и признаки того, что оно принадлежит компании.

Этот пункт немного сложнее. Вам нужны основательные доказательства того, что бакет действительно принадлежит компании. Попробуйте найти ссылки компании, указывающие на этот бакет, например, ссылки на их сайте, логи 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
  • Хранение файлов
  • Игры
  • Провайдеры потокового аудио и видео
  • Отслеживание состояния здоровья
1580403220636.png


Также, мы выявили уязвимые активы, размещенные на страницах регистрации некоторых компаний.

В некоторых случаях, уязвимые активы загружались с помощью 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, изменение контроля доступа к файлу выглядит следующим образом:

Довольно легко случайно выбрать там не тот, который нужно.
 
T

tri3r

Green Team
10.10.2019
3
0
Спасибо! А что еще можно почитать по AWS security?
 
Bokucha

Bokucha

New member
18.02.2020
3
1
Спасибо за перевод, было интересно почитать.
 
  • Нравится
Реакции: g00db0y
Мы в соцсетях: