tgoop.com/poxek/4773
Create:
Last Update:
Last Update:
Небольшая заметка про уязвимую конфигурацию nginx при проксировании запросов на S3, которое позволило в том году налутать немного уязвимостей на BugBounty.
Объектные хранилища, совместимые с S3 API, используют два варианта указания имени бакета в запросе.
Virtual-hosted–style
GET /object-name HTTP/1.1
Host: bucket-name.s3endpoint
Path-style
GET /bucket-name/objectname HTTP/1.1
Host: s3endpoint
При использовании path-style варианта может возникнуть довольно неочевидная проблема с конфигурацией nginx.
Рассмотрим на примере сайта, который проксирует запросы подставляя имя бакета в путь с помощью следующего rewrite правила.
location / {
set $s3_name "company-bucket";
set $s3_host "storage.yandexcloud.net";
rewrite ^(.*)$ /$s3_name$1 break;
proxy_pass https://$s3_host;
В nginx rewrite применяется к нормализованному пути и если в нем присутствует символ переноса строки %0A, то данное регулярное выражение не сработает, поскольку в нем используются якоря начала и конца строки.
http://example.tld/test/test.html
=
https://storage.yandexcloud.net/company-bucket/test/test.html
http://example.tld/test/foo%0Abar
=
https://storage.yandexcloud.net/test/foo%0Abar
Что в результате приведет к возможности указать любое имя бакета в запросе. Причем декодированный символ %0A в имени объекта не помешает, так как S3 это не файловая система и такие имена разрешены.
Таким образом, если используется публичное объектное хранилище, атакующий может создать в нем свой бакет с произвольным именем и загрузить на него файл foo%0Abar с XSS. Символ %0A в имени объекта должен быть декодированным, поэтому проще всего загрузить объект на него с помощью PUT запроса.
В данном запросе подпись формируется с помощью Hackvertor тегов расширения для Burp Suite.
PUT /bucket-name/foo%0Abar HTTP/2
Host: storage.yandexcloud.net
Content-Type: text/html
Authorization: AWS ##ACCESS_KEY##:<@base64><@hex2ascii><@hmac_sha1('##SECRET-KEY##')><@d_burp_url>PUT%0A%0Atext/html%0A<@date("EEE, dd MMM yyyy HH:mm:ss z","GMT")/>%0A/bucket-name/foo%250Abar<@/d_burp_url><@/hmac_sha1><@/hex2ascii><@/base64>
Date: <@date("EEE, dd MMM yyyy HH:mm:ss z","GMT")/>
Content-Length: 25
<script>alert(1)</script>
Если же запрос попадает во внутреннее объектное хранилище, то атакующий может перебирать существующие в системе бакеты, часть из которых может разрешать создание объектов PUT запросом без авторизации. Что в результате также приведет к возможности проэксплуатировать XSS.
Но чаще встречается ситуация, когда проксирование запросов производится только из одной папки, например:
location /static/ {
set $s3_name "company-bucket";
set $s3_host "storage.yandexcloud.net";
rewrite ^(.*)$ /$s3_name$1 break;
proxy_pass https://$s3_host;
Но даже в данном случае конфигурация будет уязвима из-за разницы обработок переданного пути. Правило location и rewrite работают с нормализованным путем, а proxy_pass, в котором указан URI без пути, отправит ненормализованное значение.
Таким образом для эксплуатации уязвимости необходимо отправить запрос, который в нормализованном виде попадет в location /static/, но будет начинаться с бакета, который контролирует атакующий.
http://example.tld/attacker-bucket/..%2Fstatic/foo%0Abar
=
https://storage.yandexcloud.net/attacker-bucket/..%2Fstatic/foo%0Abar
Как и в прошлом примере наличие в имени объекта символов %0A и /../ не помешают эксплуатации, так как это не файловая система и такой объект можно создать PUT запросом.
Также, если вы планируете искать подобные мисконфиги блэкбоксом, то нужно учитывать, что ошибки NoSuchObject и NoSuchBucket часто заменяют на дефолтную страницу 404, что может помешать.
Обойти это можно вызывая ошибки с кодом, отличным от 404, например отправляя PUT запрос без указания Content-Length.
PUT /attacker-bucket/..%2Fstatic/foo%0Abar HTTP/1.1
Host: example.tld
Connection: close
BY Похек
Share with your friend now:
tgoop.com/poxek/4773