И снова здравствуй!
Допустим, существует приложение, которое возвращает тело страницы, если ему отправить домен или IP адрес. Но наша цель — отправить пакет на адрес внутренней инфраструктуры и проэксплуатировать такую атаку, как SSRF.
Некорректная логика работы проверки адреса
Проверка вхождения строки
Порой, обход проверки домена бывает совсем простым. Если приложение ожидает, что будет указан адрес сайта — vulnsite.com, то иногда достаточно указать его в поддомене. Вот попробуй указать vulnsite.com.evil.com — и если веб-приложение проверяет вхождение строки в домене — мы проходим эту проверку.
Ошибка в регулярном выражении
Другой способ чуть посложнее, но также встречался на реальных проектах — это проверка домена по регулярному выражению. Однако, все мы люди, а людям свойственно ошибаться. И были такие случаи, когда происходит проверка, что домен соответствует регулярному выражению, допустим
(.*)mail.vulnsite.com$
А что тут не так? А то, что точка в регулярном выражении — это любой символ, поэтому отправив ссылку на mail-vulnsite.com (который можно зарегистрировать) — проверка будет пройдена.
Отсутствие проверки перенаправления
Другие способы — это перенаправление, когда указанная ссылка перенаправляет на внутренний адрес (обычный 302 редирект). Проверку, что домен принадлежит внутренней сети — прошли, но и редирект обработали. Забавно, что редирект может быть и на file:///etc/passwd 🙂
Отсутствие проверки адреса во время запроса
Другая ошибка логики — это разделение проверки на соответствие внешнему адресу и на непосредственно сам запрос.
Приложение делает резолв доменного имени и убеждается, что ip адрес evil.com не принадлежит адресу внутренней инфраструктуры.
Потом происходит сам запрос, и утилита (или библиотека) берет адрес не из кэша, а заново получает IP адрес домена.
Для эксплуатации уязвимости необходимо настроить свой DNS сервер таким образом, что на первый запрос DNS вернул внешний IP адрес, а на последующие — внутренний.
«Отрезание» части домена
В ссылке может быть передан логин и пароль (до символа @), данные которого в HTTP-запросе уйдут в заголовок, такая ссылка имеет подобный вид:
http://google.com:[email protected]
Для некоторых механизмов проверки — доменное имя будет соответствовать google.com, а по факту — домену, указанному через символ «@».
Некоторые символы позволяют «отрезать» хвост у домена, и если парсер пропускает их:
- Символ решетки (hash — #).
http://evil.com#vulnsite.com
Символ используется для hash-навигации или передачи информации без участия сервера. Открыв эту ссылку в браузере, браузер отправит GET запрос только на evil.com, а обработка информации после символа происходит на стороне клиента.
- Знак вопроса (?)
http://evil.com?vulnsite.com
Аналогичная ситуация, только строка после знака вопроса уйдет в параметр, точно так же, если открыть страницу evil.com/?vulnsite.com
- Нулевой байт (%00)
http://evil.com%00vulnsite.com
По большей части это касается сайтов на PHP, ибо работал он с nullbyte не всегда хорошо.
- Отдельно стоит отметить символ 💩 (U+1F4A9)
http://evil.com💩vulnsite.com
Веселый emoji «PILE OF POO» — альтернатива nullbyte для таких СУБД как MySQL с кодировкой utf8. И эта уязвимость встречается на многих проектах.
Варианты представления IP адреса
IP адрес может быть представлен различными способами. Думаю, удобнее показывать на живом сайте, а не на локальном. Берем IP адрес google.com — у меня это — 173.194.44.70.
Если мы сделаем urlencode — ссылка будет оставаться валидной:
http://%31%37%33%2E%31%39%34%2E%34%34%2E%37%30
Это применимо и к обычным доменным именам.
Каждое число в IP адресе можно представить в восьмеричной или шестнадцатеричной системах счисления:
Более того, эти варианты можно смешивать:
Не забываем про целочисленное представление IP адреса — Long IP, например, можно воспользоваться этим сервисом. В результате мы можем получить такую ссылку:
Аналогично, Long IP можно представить в восьмеричной и шестнадцатеричной системах счисления:
Помимо этого, внутренний адрес, такой как localhost (127.0.0.1) может быть представлен как 0.0.0.0, что является исходным адресом для этого хоста в сети.
Еще один забавный лайфхак — символы нуля можно опускать.
Таким образом, появляются еще варианты:
- 0
- 0.0
- 0.0.0
Это же правило применимо для других ip адресов:
- 127.1
- 127.0.1
А теперь применяя предыдущие методы, тот же 0x7f.0.0×01 — точно такой же адрес, как и 127.0.0.1 (попробуй пингануть, например, 0x7f.1).
Точка, точка, запятая
А закончу материал примером, который произошел совсем недавно. Все началось с того, что я увидел @_Abr1k0s_ в ленте твиттера:
Q&A With @Burp_Suite’s James Kettle: Bug bounties, exploit stories, and more! https://t.co/5rR4Mke48Y pic.twitter.com/hyuZz1DhuP
— HackerOne (@Hacker0x01) 19 января 2017 г.
О, так у PortSwigger есть багбаунти? Я в последнее время отстал от bb-движухи, но было интересно посмотреть, что у них находится на периметре. Пара минут — и был найден поддомен surveys.portswigger.net, который ведет на surveygizmo.com
Как оказалось, это популярный сервис, а пользуются им многие. После регистрации в приложении я создал свою форму и попытался добавить домен PortSwigger. Естественно вылезла ошибка — «
Существует такая штука, как домен нулевого уровня. В конце домена должна стоять точка, но она упускается.
Например, сайт википедии нормально работает с точкой
https://en.wikipedia.org./wiki/Main_Page
https://en.wikipedia.org/wiki/Main_Page
но как будет вести себя логика приложения — еще непонятно.
В зависимости от настроек сервера — сайт может реагировать по-разному. Кто-то будет показывать 404, кто-то invalid hostname, кто-то bad request. Но в любом случае, браузеры считают такой запрос вполне валидным.
И как ты уже догадался, я добавил домен surveys.portswigger.net. в личный кабинет. А так как сервис достаточно популярен, нашел еще десяток-другой компаний, который попали ко мне в кабинет:
В настройках была создана собственная форма с директорией /s3/, с дальнейшим редиректом.
В итоге домены имели такой вид
surveys.portswigger.net
— неконтролируемый мной
surveys.portswigger.net./s3/
— домен, которым могу управлять, вел на мой контент
Ну и аналогичный конфиг на сайты microsoft, jetbrains, и ряде других.
Так как настоящий хозяин домена уже прикрепил домен к сервису, мы можем свободно использовать его домен, но уже с точкой. Если мы можем управлять контентом — можем эксплуатировать такие штуки как фиксация сессии, да и раздолье для строительства фейков.
Что имеем?
Мы можем представить ссылку на ресурс огромным количеством способов и различными вариантами обойти проверку на легитимность отправляемого домена/ip адреса. Возможно, есть еще какие-то способы, о которых я вовсе забыл или не знал, поэтому место для комментариев под статьей 🙂
то что нужно. один только вопрос, как ты сделал urlencode на ip? какой алгоритм для этого действия, где почитать? в гугле нигде не нашел.
Просто перевел цифры и точки в urlencode. Гуглить urlencode 🙂
Чёрт, этот блог реально бомбезный!
Извините,
есть сайта, но при подключение на него выдаёт ошибку авторизации. Стоит фильтр по ip-адресам. Как ее обойти?
Спасибо