Способы обхода проверки домена и IP адреса

By 31 января 2017Blog

И снова здравствуй!

Допустим, существует приложение, которое возвращает тело страницы, если ему отправить домен или 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:80@evil.com

Для некоторых механизмов проверки — доменное имя будет соответствовать 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 адресе можно представить в восьмеричной или шестнадцатеричной системах счисления:

http://0xad.0xc2.0x2c.0x46

http://0255.0302.0054.0106

Более того, эти варианты можно смешивать:

http://173.0302.0x2c.70

http://0xad.0302.0x2c.0106

Не забываем про целочисленное представление IP адреса — Long IP, например, можно воспользоваться этим сервисом. В результате мы можем получить такую ссылку:

http://2915183686

Аналогично, Long IP можно представить в восьмеричной и шестнадцатеричной системах счисления:

http://025560426106

http://0xADC22C46

Помимо этого, внутренний адрес, такой как 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_ в ленте твиттера:

 

О, так у PortSwigger есть багбаунти? Я в последнее время отстал от bb-движухи, но было интересно посмотреть, что у них находится на периметре. Пара минут — и был найден поддомен surveys.portswigger.net, который ведет на surveygizmo.com

dig surveys.portswigger.net

Как оказалось, это популярный сервис, а пользуются им многие. После регистрации в приложении я создал свою форму и попытался добавить домен PortSwigger. Естественно вылезла ошибка — «This domain name is already in use», однако, тут я вспомнил об одной фиче с доменами.

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

Например, сайт википедии нормально работает с точкой

https://en.wikipedia.org./wiki/Main_Page

https://en.wikipedia.org/wiki/Main_Page

но как будет вести себя логика приложения — еще непонятно.

В зависимости от настроек сервера — сайт может реагировать по-разному. Кто-то будет показывать 404, кто-то invalid hostname, кто-то bad request. Но в любом случае, браузеры считают такой запрос вполне валидным.

И как ты уже догадался, я добавил домен surveys.portswigger.net. в личный кабинет. А так как сервис достаточно популярен, нашел еще десяток-другой компаний, который попали ко мне в кабинет:

surveys

В настройках была создана собственная форма с директорией /s3/, с дальнейшим редиректом.

В итоге домены имели такой вид

surveys.portswigger.net — неконтролируемый мной

surveys.portswigger.net./s3/ — домен, которым могу управлять, вел на мой контент

Ну и аналогичный конфиг на сайты microsoft, jetbrains, и ряде других.

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

Что имеем?

Мы можем представить ссылку на ресурс огромным количеством способов и различными вариантами обойти проверку на легитимность отправляемого домена/ip адреса. Возможно, есть еще какие-то способы, о которых я вовсе забыл или не знал, поэтому место для комментариев под статьей 🙂

Join the discussion 3 комментария

Leave a Reply