Шрифт:
Интервал:
Закладка:
Переполнения буфера в системных сервисах
Совершенно очевидно, что аналогично 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 (кстати, разработанная российским исследователем Константином Соболевым)....Несмотря на подчеркнутые нами отличия хакера от кракера, не хотим писать здесь слово «хакер», так как при цитировании в соответствующем контексте цель этого исследования может быть неверно истолкована.
Чтобы исполнить код, разработчик применил интересный механизм, называемый внедрением в процесс (а не стандартное переполнение буфера, как это можно было ожидать). Для внедрения в процесс используются функции OpenProcess, WriteProcessMemory, CreateRemoteThread, а самое главное – при этом необходимы привилегии SeDebugPrivilege – отладка объектов низкого уровня, в том числе потоков (threads), которые по умолчанию даются только группе администраторов. Вот как описывает автор дальнейший принцип работы своей утилиты [8]:
«Получается, что пользователь, который имеет привилегию «отладка программ», может получить права администратора на локальной машине. Но как же обойти необходимость в специальных привилегиях? Решение было найдено мной несколько позже – в июне 1997 года. Заняло примерно одну неделю.
Изучая работу ntoskrnl.exe (ядро Windows NT), я обнаружил (далеко не случайно, в ntoskrnl сотни функций), что функция NtAddAtom не проверяет адрес своего второго аргумента. Иначе говоря, если передать в качестве параметра любой адрес, туда будет записано некое число (результат выполнения NtAddAtom).
Функция NtAddAtom в WIN32 API вызывается функцией AddAtom, которая используется достаточно часто. Но функция AddAtom принимает только один параметр (адрес строки), поэтому вызов ее не приводил к катастрофическим последствиям.
Итак, получается, мы можем писать в любую область адресного пространства Windows NT… В системе Windows NT есть некий глобальный флаг NtGlobalFlag, имеющий адрес примерно 0x801XXXXX. Изменением одного из битов этого флага мы можем превратить Windows NT в Windows NT Checked Build, и право SeDebugPrivilege не будет необходимо для внедрения в системные процессы».
Дальнейшее уже зависит от стремлений хакера – имея привилегии system, можно сделать с системой все, что угодно. Программа GetAdmin внедряла в процесс WinLogon код, добавляющий текущего пользователя в группу администраторов.
Как говорится, трудно только в первый раз. Вскоре последовали различные способы получения прав администратора в Windows NT, либо развивающие идею внедрения в процессы (например, Sechole), либо использующие другие пути. Одним из самых оригинальных и в то же время очевидных оказался способ подмены программы, вызываемой при сбое другого процесса. По умолчанию в Windows NT это программа Dr. Watson, вызов которой располагается в каталоге реестра HKLMSoftwareMicrosoftWindows NT CurrentVersionAeDebug. Если же прописать туда вызов не Dr. Watson, а, скажем, User Manager, то последний будет запускаться при каждом аварийном завершении некоторого процесса. Право на чтение и запись в этот каталог реестра имеет любой член группы Everyone. Итак, злоумышленнику осталось только найти подходящий системный процесс, который он смог бы «подвесить». Учитывая стиль программирования от Microsoft, сделать это не так трудно.
Не правда ли, все это чрезвычайно похоже на получение прав суперпользователя через SUID/SGID-программы? Совершенно очевидно, что никто уже не верит в непогрешимость модели разграничения полномочий в Windows NT и вскоре появятся новые способы несанкционированного присвоения дополнительных прав.
...Уже сдавая рукопись в редакцию, мы обнаружили такой способ, опубликованный известной хакерской группой L0pht. См. бюллетень безопасности Microsoft MS006-99 «KnownDLLs List Vulnerability».
При обсуждении SUID/SGID-механизма мы подчеркивали, что он сам по себе позволяет строить только локальные атаки, которые легко превращаются в «удаленные», если злоумышленник подключается к компьютеру по протоколу TELNET. В Windows NT дело обстоит примерно так же: программы получения прав администратора могут быть запущены удаленно, например через механизм CGI или при использовании TELNET, поставляемого третьими фирмами (так как в стандартной конфигурации он не предусмотрен).
Итак, повторим основные уязвимости Windows NT, делающие возможными атаки типа GetAdmin (первые два пункта могут быть отнесены к люкам):
• возможность отлаживать потоки;
• наличие NtGlobalFlag;