Шрифт:
Видно, что в последней строчке на удаленном хосте выполнилась команда id от имени суперпользователя, это означает, что хост уязвим.
Другая уязвимость, которой подвержены версии wu-ftpd (1996–1997 гг.), состояла в том, что при определенных условиях можно переполнить список аргументов команды, а это приведет к сбросу демоном аварийного дампа памяти. Для этого нужны минимальные полномочия анонимного пользователя ftp. Самое интересное, владельцем дампа будет не root, как обычно бывает, а anonymous, и дамп будет сбрасываться в его домашний каталог. Отсюда следует, что он позже может быть прочитан удаленно. Ну а чтение аварийного дампа равносильно копанию в корзине для бумаг на секретном объекте – среди мусора находятся очень любопытные вещи, например сброшенные кэшированные пароли. Так что злоумышленнику останется только запустить взломщик паролей поновее.
В последний момент wu-ftpd вновь напомнил о себе. Оказалось, что если злоумышленник имеет право на запись в некий ftp-каталог (вполне достаточно наличия /incoming), то у wu-ftpd переполняется буфер при создании вложенных каталогов с длинными именами. Реализация этой уязвимости, опубликованная в Internet, вызвала эпидемию вскрытых хостов весной 1999 года, потому что нашлись молодые люди, умеющие запускать чужие программы и считающие себя при этом «крутыми хакерами».
Проникновение с помощью innd
Проиллюстрируем тот путь, по которому идут кракеры сегодня и рассмотрим самый популярный способ проникновения в UNIX-хосты на начало 1997 года.
В качестве «лазейки» была выбрана серверная программа, отвечающая за передачу новостей USENET по протоколу NNTP, называемая InterNet News (Inn). Такой выбор для кракеров очень удачен: во-первых, эта программа «не запятнала» себя ранее (это как раз пример новаторского подхода); во-вторых, как и любой демон, она потенциально допускает проникновение по классу 1; в-третьих, сервис передачи новостей выходит на одно из первых мест в Internet, поэтому программа достаточно распространена и существует практически на всех платформах; в-четвертых, уязвимости, если они найдутся в ней, не могут быть сведены на нет межсетевым экраном. Поясним последнее подробнее. Если вы у себя на машине ставите сервер, который должен отвечать за прием и передачу новостей по протоколу NNTP, то, естественно, обязаны разрешить этот протокол в своем межсетевом экране. Но кракер, с другой стороны, также будет работать на уровне NNTP. Иначе говоря, как и в приведенной выше уязвимости в sendmail, межсетевой экран не отличает пакеты с «хорошими» новостями от «плохих», которые посылает кракер, – Firewall может только запретить или разрешить конкретный трафик в целом.
Именно такого рода уязвимость была найдена в программе innd [17]. Среди обычных сообщений USENET встречаются так называемые управляющие типа «newgroup» или «rmgroup». Innd обрабатывает команды, расположенные в них, через команду оболочки «eval». Однако некоторая информация (иначе говоря, специальным образом разработанное фальшивое управляющее сообщение) может быть передана оболочке без надлежащего контроля. Это позволит любому, кто может присылать сообщения на ваш NNTP-сервер – иногда это чуть ли ни каждый пользователь USENET, исполнить какую угодно команду, имея привилегии демона innd, а это либо суперпользователь, либо специальный пользователь news с широкими правами. Все версии Inn, до 1.5 включительно, оказались уязвимыми.
Причины существования уязвимостей в UNIX-системах
Проанализировав большой фактический материал, коснемся причин, по которым описанные нарушения безопасности UNIX имели место, и попытаемся их классифицировать (рис. 9.4). Сразу оговоримся, что классификация ни в коей мере не претендует на новизну или полноту – кому интересна эта тема, предлагаем обратиться к более серьезным научным работам [11, 27]. Здесь же мы опишем вполне понятные читателю причины, по которым происходит до 90 % всех случаев вскрытия UNIX-хостов:
1. Наличие демонов.
2. Механизм SUID/SGID-процессов.
3. Излишнее доверие.
4. Человеческий фактор с весьма разнообразными способами его проявления – от легко вскрываемых паролей у обычных пользователей до ошибок у квалифицированных системных администраторов, многие из которых как раз и открывают путь для использования механизмов доверия.
Механизмы 1 и 2, являющиеся неотъемлемой частью идеологии UNIX, были и будут лакомым кусочком для хакеров, так как пользователь в этом случае взаимодействует с процессом, имеющим большие привилегии, и поэтому любая ошибка или недоработка в нем автоматически ведет к использованию этих привилегий.
О механизме 3 уже достаточно говорилось выше. Повторим, что в UNIX много служб, использующих доверие, и они могут тем или иным способом быть обмануты.
Итак, вот те причины, по которым демоны и SUID/SGID-процессы становятся уязвимыми:
1. Возможность возникновения непредусмотренных ситуаций, связанных с ошибками или недоработками в программировании.
2. Наличие скрытых путей взаимодействия с программой, называемых «люками».
3. Возможность подмены субъектов и объектов различным образом.
К первой можно отнести классическую ситуацию с переполнением буфера или размерности массива. Заметим сразу, что конкретные атаки, несмотря на универсальность способа, всегда будут системозависимыми и ориентированными только на конкретную платформу и версию UNIX.
Хорошим примером непредусмотренной ситуации в многозадачной операционной системе является неправильная обработка некоторого специального сигнала или прерывания. Часто хакер имеет возможность смоделировать ситуацию, в которой этот сигнал или прерывание будет послано (в UNIX посылка сигнала решается очень просто – командой kill, как в примере с sendmail).
Наконец, одна из самых распространенных ошибок программистов – неправильная обработка входных данных, что является некоторым обобщением случая переполнения буфера. А если программа неправильно обрабатывает случайные входные данные, то, очевидно, можно подобрать такие специфические входные данные, которые приведут к желаемым для хакера результатам, как случилось с innd.
Люком или «черным входом» (backdoor) часто называют оставленную разработчиком недокументированную возможность взаимодействия с системой (чаще всего – входа в нее), например, известный только разработчику универсальный «пароль». Люки оставляют в конечных программах вследствие ошибки, не убрав отладочный код, или вследствие необходимости продолжения отладки уже в реальной системе из-за ее высокой сложности, или же из корыстных интересов. Люки – это любимый путь в удаленную систему не только у хакеров, но и у журналистов, и режиссеров вместе с подбором «главного» пароля перебором за минуту до взрыва, но, в отличие от последнего способа, люки реально существуют. Классический пример люка – это, конечно, отладочный режим в sendmail.
Наконец, многие особенности UNIX, такие как асинхронное выполнение процессов, развитые командный язык и файловая система, позволяют злоумышленникам использовать механизмы подмены одного субъекта или объекта другим. Например, в рассмотренных выше примерах часто применялась замена имени файла, имени получателя и т. п. именем программы. Аналогично может быть выполнена подмена специальных переменных. Так, для некоторых версий UNIX существует атака, связанная с подменой IFS (internal field separator – символ разделителя команд или функций) на символ «/». Это приводит к следующему: когда программа вызывает /bin/ sh, вместо него вызывается файл bin с параметром sh в текущем каталоге. Похожая ситуация возникает при атаке на telnetd. Наконец, очень популярным в UNIX видом подмены является создание ссылки (link) на критичный файл. После этого файл-ссылка некоторым образом получает дополнительные права доступа, и тем самым осуществляется несанкционированный доступ к исходному файлу. Подобная ситуация с подменой файла возникает, если путь к нему определен не как абсолютный (/ bin/sh), а как относительный (../bin/sh или $(BIN)/sh). Такая ситуация также имела место в рассмотренной уязвимости telnetd.
И последнее, о чем уже подробно говорилось во второй главе, – нельзя приуменьшать роль человека в обеспечении безопасности любой системы (про необходимость выбора надежных паролей упоминалось ранее). Неправильное администрирование – тоже очень актуальная проблема, а для UNIX она особенно остра, так как сложность администрирования UNIX-систем давно стала притчей во языцех, и часто именно на это ссылаются конкуренты. Но за все надо платить, а это – обратная сторона переносимости и гибкости UNIX.
Настройки некоторых приложений, той же sendmail, настолько сложны, что для поддержания работоспособности системы требуется специальный человек – системный администратор, но даже он, мы уверены, не всегда знает о всех возможностях тех или иных приложений и о том, как правильно их настроить. Более того, если говорить о слабости человека, защищенные системы обычно отказываются и еще от одной из основных идей UNIX – наличия суперпользователя, имеющего доступ ко всей информации и никому не подконтрольного. Его права могут быть распределены среди нескольких людей: администратора персонала, администратора безопасности, администратора сети и т. п., а сам он может быть удален из системы после ее инсталляции. В результате вербовка одного из администраторов не приводит к таким катастрофическим последствиям, как вербовка суперпользователя.
Windows NT
Мы специально так подробно рассмотрели UNIX и закончили классификацией причин ее уязвимости, чтобы читателю было легче провести параллель с более молодой операционной системой – Windows NT. Сразу оговоримся, что, в отличие от UNIX, речь будет идти только об одной версии – Windows NT 4.0.
Windows NT – сильно выделяющийся продукт среди ОС, производимых фирмой Microsoft. Во-первых, это единственная система, способная работать на процессорах, отличных от Intel-совместимых, а именно на процессоре Alpha. Во-вторых, эта ОС выпускается в виде двух реализаций – как сервер (Windows NT Server) и как рабочая станция (Windows NT Workstation). В-третьих, ядро этой системы писалось с нуля, и при его разработке не требовалась 100-процентная совместимость с более ранними ОС типа MS DOS. Наконец, только в этой ОС с самого начала было уделено должное внимание требованиям безопасности, что привело к созданию собственной файловой системы, нового алгоритма аутентификации, подсистемы аудита и т. п.
Последний факт послужил поводом к возникновению нескольких мифов о защищенности Windows NT. Часто можно услышать, что Windows NT на сегодняшний день – самая защищенная сетевая ОС. На самом же деле, как подчеркивалось во введении к этой главе, пока нельзя сказать, какая из ОС является более защищенной и по каким параметрам. Этого нельзя будет сделать до тех пор, пока Windows NT не проработает хотя бы несколько лет в качестве сетевой ОС на различных аппаратных и программных конфигурациях. Ей, видимо, это не грозит в связи с выходом Windows 2000 (она же Windows NT 5.0), и процесс тестирования начнется сначала. Наконец, накопленный на сегодняшний день опыт уже не подтверждает притязаний NT на самую защищенную ОС, что и показано в данном разделе.
Второй устойчивый миф гласит, что Windows NT 4.0 якобы была сертифицирована по американскому классу защищенности С2. На самом же деле здесь ситуация почти как в анекдоте про Иванова, который выиграл в лотерею:
1. Не Windows NT 4.0, а 3.5, причем обязательно с Service Pack 3.
2. Сертификация касалась только локальной (не сетевой) версии NT, то есть с отсутствующими сетевыми адаптерами и внешними накопителями.
3. Сертификация производилась на конкретной аппаратной платформе, а именно: Compaq Proliant 2000 and 4000 (для платформы Intel/Pentium) и DECpc AXP/150 (для платформы Alpha). Если NT установлена на другую платформу, сертификат на нее не распространяется.
4. Класс С2 является одним из самых низких классов защищенности (ниже только C1 и D). Учитывая, что к классу D относятся все системы, не попадающие в другие классы, и сертифицировать по нему что-либо бессмысленно, а по классу C1 сертификация также не производится, получаем, что С2 – это низший класс защищенности, по которому вообще может производиться сертификация ОС. Отметим также, что сам процесс сертификации – достаточно формальная в плане определения уязвимостей процедура, при которой проверяется соответствие продукта всем требованиям для данного класса защищенности, и этот процесс никоим образом не гарантирует отсутствия уязвимостей.
Классификация причин уязвимости Windows NT
В отличие от описания проблем с безопасностью у UNIX, здесь мы пойдем по обратному пути: сначала классифицируем возможные способы нарушения безопасности Windows NT, а затем будем приводить примеры.
Оказывается, что классификация причин уязвимости Windows NT весьма похожа на рассмотренную аналогичную классификацию для UNIX (рис. 9.5).
Удаленное выполнение кода
Ясно, что механизм демонов, отвечающих за обработку соединений с тем или иным TCP-портом, должен был остаться и в Windows NT. Действительно, все основные службы, используемые в Internet, – ftp, WWW или e-mail – должны поддерживаться любой ОС, включающей в себя реализацию стека протоколов TCP/IP. Более того, все основные команды для работы с ними также стандартизованы. Пусть в Windows NT эти программы называются не демонами, а серверами, суть от этого не меняется, а именно: как и в случае UNIX-систем, некий неидентифицируемый пользователь (человек, сидящий за своим компьютером по другую сторону океана) тоже может давать некоторые команды серверам, подключившись на соответствующий порт. Отсюда ясно, что от классических проблем с переполнением буфера Windows NT принципиально не может быть защищена.
Получение прав другого пользователяЕстественно, что неудачного механизма SUID/SGID-программ, являющегося основным источником получения привилегированных прав в UNIX, в Windows NT нет. Тем не менее в операционной системе, где одновременно функционируют процессы с разными привилегиями, всегда потенциально можно получить права более привилегированного процесса. Этого нельзя сделать только в том случае, когда система написана так, что не содержит ошибок во внедрении и реализации не только подсистемы разграничения доступа, но и всего ядра ОС, управляющего процессами, файловой системой и т. п. Для современных ОС, объем исходного кода которых исчисляется сотнями тысяч строк (а для Windows NT 5.0 – около 5 миллионов), гарантировать отсутствие ошибок нельзя при любых технологиях написания этого кода и любом мыслимом уровне тестирования.
Windows NT содержит процессы (они называются сервисами), которые запускаются чаще всего от имени system. Это специальное имя не сильно афишируется (по крайней мере, вы не найдете его в списке имен пользователей программы User manager) и обладает полномочиями администратора на локальной машине. Таким образом, запустив программу от имени system, злоумышленник получает возможности, сравнимые с возможностями суперпользователя для UNIX-систем. Такой запуск может быть реализован как классическими методами типа переполнения буфера, так и специфичными для Windows NT способами.
Нелегальное подключение к системеКак вы помните, в некоторых случаях пользователь может подключаться к UNIX без предъявления пароля. В Windows NT такой механизм отсутствует, однако возможность нелегального (или полулегального) подключения к Windows NT все же остается. Дело в том, что в этой системе существуют некие пользователи и группы со стандартными общеизвестными именами. Один из пользователей – Guest, по умолчанию имеющий пустой пароль, – действительно хорошо известен и хакерам, и администраторам. Именно поэтому он запрещен по умолчанию, что делает его не очень ценной находкой для злоумышленников. Однако существует другой, менее известный (по крайней мере, администраторам) пользователь – анонимный (не путать с анонимным пользователем ftp или http), с пустым именем и паролем (не пытайтесь, однако, при входе в систему оставить пустыми имя и пароль пользователя – это не сработает, для анонимного подключения к компьютеру требуется другая процедура, о которой мы расскажем чуть позже), поэтому он несколько отличается от обычных пользователей, но тем не менее обладает правами, сходными с правами группы Everyone (все).
Итак, классификацию всех пользователей (субъектов) Windows NT аналогично пользователям UNIX можно представить в следующем виде:
1. Администраторы – все права на локальном компьютере или домене. Отличие от UNIX в том, что их может быть много.
2. Обычные пользователи – аналогично UNIX.
3. Специальные пользователи – предопределенные имена, как правило, использующиеся системой. Могут иметь достаточно широкие полномочия.
4. Псевдопользователи – удаленные пользователи, взаимодействующие с сетевыми серверами. Не являются пользователями как таковыми, не проходят регистрацию и не могут подключиться к компьютеру в явной форме – аналогично UNIX.
5. Анонимные пользователи – не имеют пароля, но имеют права, сходные с правами Everyone.
Человеческий факторОтметим, что ошибки администрирования, которые были неизбежны в UNIX, в Windows NT, может быть, сделать и сложнее, но здесь есть другая особенность: пусть администратор знает, что ему нужно сделать, но не может – закрытость Windows NT не предоставляет ему таких гибких механизмов настройки, как UNIX.
Совместимость с другими операционными системами Практически всегда требования совместимости или переносимости противоречат требованиям безопасности. К примеру, несмотря на то что для Windows NT была разработана специальная хэш-функция, она вынуждена поддерживать еще одну, которая берет свое начало от самых первых сетевых приложений Microsoft. Поэтому в криптографическом плане Windows NT порой оказывается слабее UNIX. И еще: довольно часто Windows NT приходится поддерживать решения, которые являются устаревшими с точки зрения безопасности.Переполнения буфера в системных сервисах
Совершенно очевидно, что аналогично UNIX-системам наличие потенциальных ошибок в программах, отвечающих за поддержку основных служб Internet, является самой серьезной уязвимостью, допускающей удаленное исполнение кода незарегистрированным пользователем.
Готовя материал для этого раздела, мы до самого последнего момента не могли найти хорошего примера. Были уязвимости, приводящие «всего лишь» к отказу в обслуживании; были переполнения буфера с возможностью исполнения кода, но для этого требовались некоторые действия от пользователя (типа «забрать почту с сервера», «прочитать письмо» и т. п.); самой нашумевшей уязвимостью оказалось переполнение буфера при чтении письма с MIME-вложением. Мы же хотели привести пример классического переполнения, при котором осуществимо удаленное вторжение без каких-либо действий с атакуемой стороны, потому что точно уверены в возможности этого из-за особенностей архитектуры Windows NT.
То, что такими примерами не изобилует история безопасности Windows, говорит вовсе не о качестве написания программного кода, а всего лишь о том, что программ, которые могут содержать бреши в безопасности, не так уж много – Microsoft Internet Information Server, реализующий http-, ftp-, gopher-серверы, и Microsoft Exchange Server, отвечающий за SMTP и POP3. Сравните это с огромным количеством демонов от разных фирм (мы не утверждаем, что это хорошо), доступных для UNIX!
Но все же в последний момент, в январе 1999 года, появилась долгожданная уязвимость в ftp-сервере, входящем в состав IIS 4.0. Оказывается, команда NLST содержала переполняемый буфер с возможностью не только отказа в обслуживании сервера, но и удаленного исполнения кода. Проверить наличие этой уязвимости можно примерно следующим набором команд:
> ftp victim.com
Connected to victim.com.
220 VICTIM Microsoft FTP Service (Version 4.0).
User (poor.victim.com:(none)): ftp
331 Anonymous access allowed, send identity (e-mail name) as password.
Password:
230 Anonymous user logged in.
ftp> ls AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
200 PORT command successful.
150 Opening ASCII mode data connection for file list.
–> ftp: get :Connection reset by peerМинимально необходимый объем данных команды NLST, который вызывает переполнение, – 316 байт, при этом возможен только отказ в обслуживании, что следует из содержимого регистров в момент аварийного останова – они равны:
EAX = 0000005C EBX = 00000001
ECX = 00D3F978 EDX = 002582DD
ESI = 00D3F978 EDI = 00000000
EIP = 710F8AA2 ESP = 00D3F644
EBP = 00D3F9F0 EFL = 00000206Как видно, ни один из регистров не содержит шестнадцатеричного кода 41, соответствующего букве «A». Со строками большей длины картина будет иной, а именно:
EAX = 00000000 EBX = 41414141
ECX = 41414141 EDX = 722C1CAC
ESI = 41414141 EDI = 41414141
EIP = 722C9262 ESP = 00D3F524
EBP = 00D3F63C EFL = 00000246Большое количество кодов (41) означает, что содержимое буфера попадает в регистры, правда, не в EIP. Следовательно, переполняемый буфер находится не в стеке, что усложняет задачу злоумышленника по удаленному выполнению кода, но отнюдь не делает его невозможным.
Данный пример заслуживает внимания еще двумя моментами. Во-первых, такая уязвимость проявляется только после установки Service Pack 4, а с предыдущим Service Pack 3 повторить ее никому не удалось. Это подтверждает очевидный факт: после любых изменений в программах (тем более после таких серьезных, как Service Pack, занимающих десятки мегабайт) всеобъемлющее тестирование должно проводиться заново, а если это невыполнимо, то никто не смеет утверждать, что в программных продуктах не возникнут новые ошибки.
Во-вторых, уязвимость была найдена с помощью автоматизированного средства для поиска переполнений буферов Retina, разрабатываемого группой eEye (www.eeye.com). Собственно идея создания такого средства для нужд компьютерной безопасности, что называется, витает в воздухе, и подобные проекты уже существовали, но на этот раз с помощью Retina удалось отловить довольно серьезную уязвимость. Кстати, вскоре она обнаружила и переполнение буфера в уже известном читателю wu-ftpd с отказом в обслуживании.
Надо отдать должное фирме Microsoft, которая всегда оперативно реагирует на сообщения о найденных уязвимостях. И на этот раз hot-fix (заплатки) появились через 10 дней после первых сообщений, при этом большая часть времени, видимо, ушла на воспроизводство условий, необходимых для переполнения буфера, то есть на подтверждение его реальности.
Получение прав администратора Из классификации уязвимостей Windows NT следует, что для получения прав привилегированных пользователей необходимо исполнить код от имени одного из системных процессов (сервисов). Первой и самой известной из программ такого рода была появившаяся в 1997 году утилита GetAdmin (кстати, разработанная российским исследователем Константином Соболевым).