19 смертных грехов, угрожающих безопасности программ
Шрифт:
Проблема же в том, что многие разработчики не понимают, насколько уязвима система разрешения имен и как ее легко атаковать. Хотя для большинства приложений основной службой разрешения имен является DNS, но в больших сетях из Windows–машин применяется также служба WINS (Windows Internet Name Service). У разных служб есть некоторые специфические особенности, но все они страдают общим недостатком: им нельзя доверять полностью.
Подверженные греху языки
В отличие от многих других грехов степень доверия к службе разрешения имен совершенно не зависит от языка программирования. Проблема в изъянах самой инфраструктуры, которой мы пользуемся, и если
Вместо того чтобы рассматривать ситуацию с точки зрения греховных языков программирования, мы поговорим о том, какие приложения уязвимы. Основной вопрос: должно ли приложение знать, какая машина соединилась с вашей или с какой системой соединились вы.
Если в приложении применяется какой–нибудь вид аутентификации, особенно ее слабые формы, или по сети передаются зашифрованные данные, то, наверное, нужен надежный способ идентифицировать сервера, а в некоторых случаях и клиента.
Если же приложение принимает только анонимные соединения и возвращает данные в открытом виде, то сведения об адресе клиента нужны разве что для протоколирования. Но даже в этом случае принимать дополнительные меры для аутентификации клиента не всегда практично.
Как происходит грехопадение
Мы рассмотрим принципы работы DNS, а затем попробуем смоделировать угрозу. Клиент хочет найти некий сервер, скажем, www.example.com. Он посылает запрос DNS–серверу с просьбой сообщить IP–адрес (или несколько адресов), соответствующий доменному имени www.example.com. Важно отметить, что служба DNS работает по протоколу UDP, так что вы лишены даже той эфемерной защиты, которую предоставляет протокол TCP. Получив запрос, DNS–сервер смотрит, есть ли у него готовый ответ. Ответ имеется двух случаях: если данный сервер является руководящим (authoritative) для домена example.com или сохранил в кэше ответ на вопрос о том же имени, поступивший от какого–то другого компьютера. Если ответа нет, сервер запросит у одного из корневых серверов, где найти руководящий сервер имен для домена example.com (это может повлечь за собой еще один запрос к серверу домена .com, если example.com отсутствует в кэше). Узнав адрес руководящего сервера, первоначальный сервер пошлет ему еще один запрос и на этот раз получит окончательный ответ. К счастью, в систему DNS встроена избыточность: на каждом уровне работает несколько серверов, что позволяет защититься от случайных сбоев, не связанных с атаками. Но, как мы видели, шагов много, так что злоумышленник может нанести удар в разные места.
Во–первых, откуда вы знаете, что ответил действительно ваш сервер имен? Вы послали запрос на некоторый IP–адрес с определенного порта в вашей системе. Вы знаете, какое имя указали в запросе. Если бы все было хорошо, то, получив в ответ на запрос об адресе сервера www.example.com адрес сервера evilattackers.org, ответ следовало бы отбросить. Да еще с запросом связан 16–разрядный идентификатор – но предназначен он вовсе не для защиты, а чтобы не путать запросы от нескольких приложений, работающих на одной и той же машине.
Теперь посмотрим, что может пойти не так. Прежде всего, адрес настоящего сервера имен. Противнику нетрудно узнать этот адрес, особенно если он находится в той же сети, что и вы; почти наверняка в этом случае вы используете один и тот же DNS–сервер. Другой способ заключается в том, чтобы заставить систему запрашивать IP–адрес у DNS–сервера, контролируемого противником. Возможно, вам кажется, что это условие трудновыполнимо, но, принимая во внимание историю некоторых реализаций DNS–серверов, приходится с сожалением признать, что перспектива напороться на контролируемый противником сервер имен реальна. Итак, предположим, что противнику известен IP–адрес вашего DNS–сервера.
Далее, ответ должен прийти на тот же порт, с которого был отправлен запрос. Теоретически существует 64К портов, но на практике их меньше. В большинстве операционных систем динамические порты выделяются из ограниченного диапазона, в случае Windows это номера от 1024 до 5000, так что область поиска ограничена 12 битами вместо 16. Хуже того, номера портов обычно начинаются с 1024 и возрастают на единицу. Поэтому можно считать, что противник без особого труда сможет угадать номер порта.
Есть еще идентификатор запроса, но во многих реализациях он тоже возрастает монотонно, так что и его угадать несложно. Если противник находится в той же подсети, что и клиент, то атака становится тривиальной. Даже при наличии в сети коммутатора противник может увидеть запрос и получить всю информацию, необходимую для изготовления подложного ответа.
Но – полагаете вы – если мы просили адрес одной системы, а получили адрес совсем другой, то определитель должен проигнорировать непрошеную информацию. Увы, в большинстве случаев это не так. Но если мы просили IP–адрес одной системы, а получили ответ для другой, но с затребованным нами IP–адресом, то уж тогда–то клиент точно отбросит лишние данные, ведь так? И снова ответ отрицательный: может и принять.
Сейчас вы, наверное, недоумеваете, как же при таких условиях Интернет вообще умудряется работать, и думаете, что хуже уже и быть не может. Разочаруем вас. Следующая проблема в том, что в каждом DNS–ответе есть время кэширования. И угадайте, кто контролирует время, в течение которого мы можем доверять результату? В пакете, содержащем ответ, эта информация хранится в поле TTL (time–to–live – время жизни), и клиенты обычно слепо ему доверяют.
Далее, можно задаться вопросом, откуда DNS–сервер знает, что получает ответы на свои запросы именно от руководящего сервера. В этом случае DNS–сервер выступает в роли клиента, а стало быть, уязвим для всех описанных выше атак против клиента. Впрочем, есть все–таки хорошая новость – обычно DNS–серверы более тщательно проверяют непротиворечивость ответов, среди современных серверов вряд ли хоть один «поведется» на подлог.
Возможно, вы слыхали о DNSSEC, то есть безопасном DNS, и думаете, что с его помощью сможете решить все проблемы. Только беда в том, что он обещает эти проблемы решить вот уже десять лет, так что уж извините наш скептицизм. Прекрасное обсуждение этой проблемы имеется на странице www.watersprings.org/ pub/id/draft–itf–dnsext–dns–threats–07.txt. Вот выдержка из реферата:
Хотя система DNS Security Extensions (DNSSEC) разрабатывается уже десять лет, IETF так и не сформулировал конкретные угрозы, от которых DNSSEC должен защитить. Не говоря уже о прочих недостатках, эта ситуация с «телегой впереди лошади» затрудняет оценку того, достиг ли DNSSEC заявленных при проектировании целей, поскольку эти цели не были явно специфицированы.
Что еще плохого может случиться? Примите во внимание, что в наши дни большая часть клиентов пользуется протоколом динамического конфигурирования хостов (DHCP – Dynamic Host Configuration Protocol) для получения своего IP–адреса и адреса обслуживающего DNS–сервера. Часто по тому же протоколу они извещают DNS–сервер о своем имени. По сравнению с DHCP система DNS выглядит неприступной крепостью. Не будем вдаваться в детали, отметим лишь, что имя клиентской системы можно принять лишь условно, но считать эту информацию надежной было бы опрометчиво.