Дэн Каминский, сообщивший о дыре в DNS, вызвал бурный интерес общественности,
подогреваемый замалчиванием деталей атаки. Хакеры реконструировали цепь событий,
создав боевые exploit'ы, блокируемые только самыми свежими заплатками.
Проанализировав исходный код, я обнаружил намного более серьезные дыры, чем
Каминский…

 

Хронология событий

Готовясь к очередной хакерской конференции Black Hat USA 2008, Дэн Каминский,
сотрудник компании IOActive, подготовил доклад, демонстрирующий новые атаки на
DNS-сервера. Что интересно, в презентации текст почти отсутствовал. Каминский
отказывался разглашать технические детали, нагнетая атмосферу ужаса и паники.
Компании, специализирующиеся на компьютерной безопасности, лихорадочно
анализировали заплатки, выпущенные производителями, пытаясь определить, что
именно было исправлено. Как и следовало ожидать, Каминский не откопал ничего
принципиально нового, хотя и извлек из тьмы кромешной ранее использованные, но
малоизвестные молодому хакерскому поколению атаки на DNS.

Между тем, на одном из блогов появилось достаточно полное описание
предполагаемого сценария атаки, которое, по одной версии, было выболтано
Каминским «по пьяни», по другой — независимо реконструировано хакером Халваром
Флейком на основе анонса презентации Каминского. В настоящий момент убраны и
анонс, и текст Флейка, на месте которого красуется «джентльменское» извинение.
Однако, как говорится, что в Сеть попало, то пропало, и описание атаки
немедленно расползлось по десяткам сайтов, форумов, блогов и живых журналов.

А за две недели до презентации на metasploit'е появилась пара свеженьких
exploit'ов, один из которых предназначен для атак на DNS-сервера, другой — на
рабочие станции. Анализ обоих (выполненный мной «по долгу службы») не выявил
ничего принципиально нового. Подобные трюки я использовал и сам (не для реальных
атак, а для pen-testing'а, но что это меняет?).

Самое интересное — реальные дыры (о которых Каминский не имел ни малейшего
представления) остались не заткнутыми. Я сходу предложил два сценария внедрения
в уже пропатченные системы. Не придав им, впрочем, большого значения, поскольку
Endeavor Security Inc (где сейчас работаю) в основном занимается разработкой и
лицензированием сигнатур для различных систем обнаружения вторжения, многие из
которых не имеют даже пороговых датчиков. В рамках «чистых» сигнатур (без
привлечения специальных модулей) описать атаку на DNS практически невозможно в
силу природы самой атаки. Но мне все-таки удалось это сделать, после чего я
связался с разработчиками осей и всех популярных реализаций DNS-серверов на
предмет: «так когда же будут готовы нормальные патчи?!».

И вот тут началось… Разработчики быстро въехали в ситуацию и попросили меня
отложить публикацию до тех пор, пока лекарство не будет готово. В смысле,
английскую публикацию. За русскую никакого договора не было, так что читатели ][акера
имеют возможность получить эксклюзивную информацию из первых рук.

 

Восход солнца над Сан-Франциско, или как это работает

DNS-протокол может работать как поверх TCP, так и поверх UDP, причем в 99%
случаев используется именно UDP – как более быстрый, менее ресурсоемкий, но, в
тоже время, и менее защищенный. Чтобы послать подложный пакет, который будет
воспринят жертвой как правильный, достаточно угадать (подобрать) идентификатор
последовательности (TXID) и номер порта-отправителя (SP#). На этом заканчивается
первая фаза атаки и начинается вторая.

В простейшем случае злоумышленник может отправить подложный DNS-ответ с
подложным IP-адресом некоторого узла, на который ломится жертва. Например,
хорошая идея — навязать ложный IP сервера обновлений и заманить жертву на
хакерский узел, где лежат «хакнутые» заплатки, начиненные червями или прочей
заразой.

Сложность реализации атак подобного рода в том, что рабочие станции кэшируют
DNS запросы. Более того, система не принимает DNS-ответов, которые не
запрашивались – хакер должен дождаться момента, когда жертва пошлет DNS-запрос,
и сгенерировать подложный ответ прежде, чем это сделает настоящий DNS-сервер! На
самом деле, обе проблемы имеют весьма элегантное решение. DNS-кэш обычно
невелик, а потому, послав жертве HTML-письмо с кучей картинок, лежащих на
внешних серверах с разными доменными именами, хакер может вытеснить из кэша все
старые записи. После чего последняя ссылка в письме, ведущая на сервер
обновлений, гарантированно пошлет обозначенный запрос в Сеть. Предшествующая ей
ссылка на Web-сервер, подконтрольный хакеру, подскажет точное время, когда
следует начинать генерацию подложных пакетов. Если хотя бы один из них будет
воспринят как правильный, в DNS-кэш попадет «левый» адрес сервера с апдейтами,
имеющий все шансы «дожить» до очередной сессии обновлений.

Атака на DNS-сервер сулит еще большие перспективы. Допустим, мы отправляем
серверу запрос на разрешение доменного имени xxx.abcdomain.com, заведомо
отсутствующего в его кэше, поскольку такого имени вообще нет. Атакуемый
DNS-сервер обращается к вышестоящим серверам за помощью. Если хакер успеет
возвратить подложный пакет быстрее всех, и этот пакет будет воспринят жертвой
как правильный, атакуемый DNS-сервер запомнит хакерский IP. Теперь он будет
направлять ему все последующие доменные имена *.abcdomain.com для преобразования
их в IP, считая его наиболее компетентным DNS-сервером, лучше других
разбирающимся в домене abcdomain.com. Хакер одним махом захватывает целый домен
со всеми поддоменнами! Именно этот сценарий и предложил Каминский для атак.

На первый взгляд, ситуация близка к критической, ведь захватывая домены один
за другим, атакующий может манипулировать траекторией сетевого трафика по своему
усмотрению, воровать конфиденциальную информацию, троянизировать исполняемые
файлы и вытворять кучу других фокусов. Однако при ближайшем рассмотрении все
видится в ином свете. Сценарий Каминского известен со времен первой молодости
интернет, и его эффективность преувеличена. Чтобы захватить домен, нужно послать
подложный DNS-пакет, угадав TXID/SP#, что в общем случае требует посылки
большого количества пакетов, легко засекаемых даже самой примитивной системой
обнаружения вторжения. Во-вторых, информация о кредитках обычно передается через
SSL (соединение, заведомо устойчивое к перехвату), а исполняемые файлы (особенно
системные) снабжены цифровыми подписями, которые не подделаешь. Даже в случае
успешного исхода атаки возможности хакера весьма ограничены, особенно учитывая
существование дополнительных защитных комплексов, тех же антивирусов, например.

 

О чем молчат заплатки

Латать DNS-сервера и DNS-резолверы (входящие в состав всех операционных
систем) начали задолго до «дыры» Каминского. Древние системы использовали
инкрементный TXID (увеличивающийся на единицу с каждым DNS-запросом) и
фиксированный порт источника, что делало DNS-атаки чрезвычайно простым занятием.
Не нужно быть пророком, чтобы угадать заранее известную пару 16-битных чисел,
варьирующуюся в очень узких пределах.

После первой волны атак разработчики, почесав в затылке, написали несложную
функцию, генерирующую TXID на основе системных часов, значение которых
удаленному атакующему неизвестно (во всяком случае, так принято считать). Однако
это не сильно смутило хакеров (пионеров, пользующихся готовыми exploit'ами, мы в
расчет не берем). Во-первых, энтропия (то есть мера беспорядка) в этом случае
намного ниже 16-бит. Младшие биты системных часов обычно представляют собой
константу, поскольку аппаратный таймер не обеспечивает заданного временного
разрешения. Старшие же биты обычно также представляют собой константу, и на
достаточно коротком временном отрезке меняется только середина 16-битового поля
TXID.

Во-вторых, посылая запросы DNS-серверу и получая от него пакеты, хакер
«вытягивает» оттуда TXID, которые в подавляющем большинстве случаев ложатся на
тривиальную прямую арифметической прогрессии с минимальным разбросом. Он тем
меньше, чем ниже загруженность сервера и канала, связывающего его с атакующим.
Атаки вспыхнули с новой силой. Разработчики плюнули и сделали то, что им
полагалась сделать с самого начала — полную рандомизацию TXID, что, кстати,
проще сказать, чем запрограммировать. Ведь TXID должны представлять собой
уникальные идентификаторы и не повторяться дважды в течение короткого интервала
времени. Алгоритмы, основанные на системных часах, обеспечивают такое
распределение в силу «стрелы времени», а вот функции типа rand() требуют
специальной доработки «напильником». Реализация усложняется, повышая вероятность
косяков, но… чего не сделаешь ради безопасности?

Порт источника долго не хотели рандомизировать, оставляя его как последний
бастион. Но 16-битное поле TXID даже при 100% рандомизации (не достижимой на
практике) – не слишком-то хорошая защита, и для успешной атаки хакеру достаточно
в среднем послать 2^16/2 = 32768 пакетов. Учитывая пропускные способности
современных сетей, плюс наличие распределенных ботнетов, атака займет считанные
минуты! Система обнаружения вторжений, конечно, среагирует, но противостоять
атаке не сможет, так как неизвестно, с какого узла ботнета придет следующий
подложный пакет (а вот если хакер не меняет своего IP, то его легко
заблокировать).

До Каминского большинство систем использовало простой инкрементный алгоритм
(номер порта источника увеличивается на единицу до тех пор, пока не встретится
первый свободный порт), но это касается исключительно рабочих станций с
DNS-резолверами. У DNS-серверов порт-источника обычно фиксирован и по умолчанию
равен 53, хотя разработчики BIND 8 и 9 заблаговременно предоставили опциональную
возможность его рандомизации. Когда владельцы других систем лихорадочно качают
патчи, пользователи последних версий BIND просто комментируют одну строчку в
конфиге named.conf (Крис имеет в виду директиву «query-source address * port
53;», предписывающую серверу BIND использовать 53-тий порт в качестве порта для
запросов, посылаемых через все локальные сетевые интерфейсы - Прим. ред.),
продолжая пить пиво. А потом включают ее обратно, поскольку рандомный порт на
сервере – не есть хорошо, так как возникают проблемы с брандмауэрами,
трансляторами сетевых адресов и прочие конфикты.

Заплатки, выпущенные для предотвращения (читай: затруднения) атак на
DNS-сервера и рабочие станции, рандомизовали TXID вместе с портом-источника и
изменили политику кэширования DNS-ответов. Казалось бы: теперь мы, наконец,
защищены. Как бы ни так! Существует, по меньшей мере, два сценария эффективных
атак, которые пробивают полностью пропатченные BIND 9, DJBDNS, а также,
частично, PowerDNS. И сейчас я их продемонстрирую.

 

Задыхаясь от жажды

ОК, порт источника рандомизирован и выбирается наугад из широкого пула
(точные цифры варьируются от одной системы к другой и в грубом приближении
составляют 16384, то есть 12 бит, хотя тот же PowerDNS использует всего 1024
порта, что при большом количестве запросов ведет к банальному DoS'у). Допустим,
что сервер (или рабочая станция) использует криптостойкую функцию рандомизации,
угадать следующее значение которой невозможно. Означает ли это, что атакующему
необходимо перебирать 16 бит TXID вместе с 12 битами порта источника?

Конечно, нет! Порты — расходные материалы, и они используется не только
DNS'ом, но и многими другими службами, реализованными поверх UDP. Это позволяет
атакующему вполне легальными средствами захватить большое количество портов,
просто посылая пакеты соответствующим службам и ожидая от них ответа. Как раз
при генерации ответа и происходит «заем» порта, освобождаемого только после
завершения отправки исходящего пакета. Даже если на сервере нет никаких других
UDP-служб, атакующий просто обрушивает на DNS шквал легальных запросов,
опустошая пул доступных портов, что, в конечном счете, может привести к отказу в
обслуживании. Раньше такой проблемы не возникало, поскольку один и тот же порт
использовался для всех DNS-ответов, а теперь, с рандомизацией, DNS может брать
только свободные порты, количество которых тает буквально на глазах.
Псевдослучайная функция назначения порта превращается во вполне предсказуемую.
От 12-ти обозначенных бит не остается и следа! А потому рандомизацией портов
можно смело пренебречь, сфокусировавшись на предсказании TXID.

 

Гадание на кофейной гуще с хронометром в руках

В идеале, для выбора TXID следует использовать абсолютно криптостойкую
функцию, генерирующую настоящий белый шум. Однако без привлечения специального
оборудования осуществить подобную затею невозможно, не говоря уже о том, что к
выбору TXID предъявляются достаточно жесткие требования — они не должны
повторяться на коротком временном участке, иначе возникнет путаница, чей это
пакет, и кому он адресован.
PowerDNS использует достаточно качественные функции для генерации TXID, и атака
на него – тема отдельного разговора. Вообще говоря, PowerDNS и сам не знает, что
использует, читая псевдослучайные числа из псевдоустройства /dev/urandom,
которое может выдавать, что угодно. Системную дату использует DJBDNS, остальные
же системы задействуют довольно простые и вполне предсказуемые алгоритмы — зная
предыдущие члены псевдослучайной последовательности, мы можем с высокой степенью
вероятности вычислить следующие (вероятность тем выше, чем больше у нас членов).

В случае DNS-сервера никаких проблем у атакующего не возникает — он просто
посылает ему легитимные запросы, получая ответы с TXID в заголовке. Зная
алгоритм, используемый для рандомизации (а он известен с точностью до системы,
версию которой определить не так уж и сложно), хакеру остается всего лишь… Хм.
Даже без всякой математики тривиальный brute-force (осуществляемый на локальной
машине без обращения к серверу) находит возможные варианты быстрее, чем хакер
пьет кофе.

С рабочими станциями ситуация обстоит чуть-чуть сложнее. Ведь им DNS-запросы
не пошлешь и DNS-ответов не словишь. Нам известен алгоритм, используемый для
генерации TXID, известно даже, что для его «затравки» используется системный
таймер, но вот значение самого таймера… Прочитать его удаленно? Да без проблем!
При желании можно обойтись даже без Java-скриптов. Ведь тот же самый таймер
используется не только в UDP, но и в TCP (для генерации начального номера
последовательности), а потому, если машина способна отправлять хоть какие-то
пакеты во внешнюю сеть, то значение таймера восстанавливается без труда, а по
нему уже вычисляется «затравка».

Главным образом, это относится к BIND 9 и DJBDNS, использующим
некриптостойкие функции. PowerDNS стоит особняком, однако поскольку он также
подвержен захвату UDP-портов, то 16-битный TXID, пусть он хоть 100 раз
криптостойкий и ни разу не предсказуемый, — плохое средство защиты от хакеров.

 

Как от этого защищаются

Установка свежих заплаток однозначно не решает проблему, и угроза атаки
слишком велика, чтобы позволить себе ее игнорировать. Мелкие ISP и офисные
сервера достаточно легко перевести на DNS over TCP. А еще есть TSIG, позволяющий
в пределах небольшой локальной сети организовывать безопасные взаимодействия
серверов за счет использования сигнатур транзакций, и DNSSEC, обеспечивающий
проверку подлинности серверов и целостности зонных данных.

Все эти решения работают лишь на узлах с небольшой нагрузкой. В промышленных
масштабах такие варианты обсуждать глупо. И что остается? Самое простое —
использовать PowerDNS. Он действительно намного надежнее, да и работает быстрее
стандартного BIND 9.

Также не помешает установить качественную IDS/IDP. Как она работает, зависит
от реализации. Например, садится на интерфейс и ловит все входящие/исходящие
DNS-пакеты, и если обнаруживает достаточно большое количество входящих
DNS-ответов, которым не соответствовали DNS-запросы, – сразу поднимает тревогу.
Слабость такого решения в том, что «левые» пакеты могут сыпаться и без всякой
атаки, а количество подложных DNS-ответов при целевой атаке много ниже порога
чувствительности сенсора. Именно так подавляющее большинство IDS/IPS и работает.

Более сложные системы защиты парсят трафик на сетевом уровне, «выдергивают»
оттуда DNS-ответы и, обращаясь к корневым серверам через TCP, определяют
достоверность предоставленной информации. Решение, конечно, надежное, но…
пропускная способность при этом находится на уровне трубки от ниппеля.

Мы с Алиской (замечательной девушкой из Endeavor Security) разработали
скоростной потоковый алгоритм, реализуемый на основе чистого сигнатурного
анализа проходящего трафика. Руководящая идея заключается в том, что нормальный
DNS-сервер не отвечает дважды в течение короткого времени, поскольку первый
ответ будет скэширован, и второго запроса просто не последует. А вот хакер,
пусть и располагающий определенной информацией о TXID/SP#, вынужден посылать
намного больше одного DNS-ответа, содержащего тот же самый отрезолвенный IP, —
явный симптом атаки.

 

Дыры еще будут

Сейчас, когда пишутся эти строки, разработчики DNS-серверов и операционных
систем совместно с компанией Endeavor Security разрабатывают стратегический план
ликвидации обнаруженных мной дыр. К моменту выхода журнала из печати лекарство
(в виде очередной порции свежих заплаток) уже появится в аптеках. Но не стоит
отчаиваться (или обольщаться). Это не первая и далеко не последняя дыра в DNS.
Так что – время покажет.



Полную версию статьи
читай в сентябрьском номере
Хакера!

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии