
Простой сервис перепривязки DNS
Простой сервис DNS Rebinding
rbndr — это очень простой, несоответствующий стандартам name server для тестирования программного обеспечения на уязвимости DNS rebinding. Сервер отвечает на запросы, случайным образом выбирая один из адресов, указанных в имени хоста, и возвращая его в качестве ответа с очень низким TTL.
https://en.wikipedia.org/wiki/DNS_rebinding
DNS rebinding — это форма уязвимости TOCTOU (проверка времени, время использования). Она используется, если у вас есть сервис, который неправильно применяет предварительные проверки («preflight») для изменения свойств безопасности. Например, рассмотрим (вымышленный) плагин браузера с таким API:
AllowUntrustedAccess("foobar.com");
SendArbitraryRequests("foobar.com");
И AllowUntrustedAccess() просто отправляет предварительный HTTP-запрос на хост:
GET /CanIDisableSecurity HTTP/1.1
Если сервис возвращает 200, плагин предоставляет хост-странице полный доступ к этому имени хоста. Это может быть уязвимостью безопасности, потому что вы можете указать имя хоста rbndr, которое будет переключаться между хостом, который вы контролируете, и хостом, который вы не контролируете. Плагин может предоставить полный доступ к произвольному IP-адресу (например, внутреннему сервису или localhost), даже если этот сервис обычно не разрешает предварительную проверку.
Это может звучать нереалистично, но именно так работали Adobe Flash, Oracle Java и многие другие продукты в прошлом, и многие продукты продолжают так работать до сих пор.
Прочитайте о том, как Adobe пыталась решить эту проблему во Flash здесь: https://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html
Для программного обеспечения, уязвимого к этому классу атак, rbndr — это простой способ тестирования без необходимости изменять /etc/hosts или настраивать собственный name server. Если программа ассоциирует результат только с именем хоста, а не с именем хоста и IP-адресом, то вы можете предоставить себе доступ к любому IP-адресу.
Формат имён хостов прост:
<ipv4 в base-16>.<ipv4 в base-16>.rbndr.us
Но вы можете использовать этот сайт для преобразования из десятично-точечной нотации, если предпочитаете:
Например, для переключения между 127.0.0.1 и 192.168.0.1 нужно закодировать их как dwords (32-битные слова) и затем использовать:
7f000001.c0a80001.rbndr.us
Давайте протестируем:
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 192.168.0.1
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 192.168.0.1
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 192.168.0.1
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 127.0.0.1
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 127.0.0.1
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 192.168.0.1
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 127.0.0.1
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 127.0.0.1
$ host 7f000001.c0a80001.rbndr.us
7f000001.c0a80001.rbndr.us has address 192.168.0.1
Как видите, сервер случайным образом возвращает один из адресов. Вы можете сделать что-то подобное (на псевдокоде):
// Продолжайте вызывать api, пока оно не разрешится в адрес, который вы контролируете, и вы не получите доступ
while (AllowUntrustedAccesss("7f000001.c0a80001.rbndr.us") != true)
;
// Доступ получен, теперь ждите повторной привязки
while (ConnectToPort("7f000001.c0a80001.rbndr.us", 123) != true)
;
// Теперь у вас есть доступ к localhost:123, даже если localhost не давал согласия на снижение безопасности.
SomethingEvil();