Если первые кирпичи здания UNIX закладывались в ту далекую эпоху, когда никакой теории безопасности еще не существовало, то Windows NT изначально проектировалась как защищенная, отказоустойчивая система.

Дейв Катлер, крестный отец Windows NT, ранее принимавший участие в создании двух «легенд» семидесятых — RSX-11M и VMS, вложил в NT весь свой талант и опыт, но... похоже, потерпел фиаско. (Кстати, позволю себе каламбур: если в аббревиатуре «VMS» все буквы сдвинуть на одну позицию вправо, то получится «WNT».) Да, Windows NT построена на передовых технологиях и основана на внутренне непротиворечивой модели безопасности, но идиллию разрушают вездесущие ошибки реализации.

Кроме досадных багов, своеобразных программистских описок, исправить которые можно с помощью очередной заплатки, множество проблем порождает несогласованная стыковка различных компонентов операционной системы друг с другом, способная значительно ослабить общий уровень защищенности системы. Но ни один человек не в состоянии удержать в голове миллионы строк исходного кода операционной системы, а с ростом количества разработчиков координировать их действия становится все сложнее и сложнее.

Неудивительно, что в Windows NT выявлены серьезные бреши в защите, причем злоумышленник может повысить уровень своих привилегий от «гостя» до администратора. Часть ошибок устраняется правильным администрированием (читай — всяческим ущемлением прав пользователей и отключением всего, что удается отключить), но сама архитектура Windows NT всегда оставляет злоумышленнику шанс проникнуть в систему.

Аналогично UNIX, операционная система Windows NT подвержена угрозе переполнения стека, а также выхода за пределы процесса, в результате чего пользователь может получить доступ к данным и коду другого приложения (включая системные сервисы). Кроме того, реализация протоколов семейства TCP/IP оставляет желать лучшего и допускает возможность удаленной атаки.

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

ПРОЩЕ ПРОСТОГО

Для проникновения в систему злоумышленнику вовсе не обязательно подбирать пароль — одна нелепая ошибка позволяет быстро, незаметно и с гарантией на успех похитить его у жертвы. На страничку Web достаточно поместить ссылку наподобие и дождаться, пока жертва не вздумает на нее зайти (или, чтобы ускорить развязку, послать жертве письмо в формате HTML). Когда это наконец произойдет, Internet Explorer или Netscape Navigator автоматически, не запрашивая подтверждения, передаст имя пользователя и хэш-значение пароля, под которым тот вошел в систему.

Впервые этот казус обнаружил Аарон Спэнглер, а вслед за ним на него обратили внимание и другие. Уязвимы оказались все версии Windows NT 3.5—4.0 вплоть до последних Service Pack, а также Windows 95 и Windows for Workgroups.

Но это не единственный способ несанкционированного вторжения. В Windows NT наличествует так называемый гостевой вход (Guest Account) с пустым паролем. На сервере он по умолчанию заблокирован, а на рабочих станциях открыт! Однако получение доступа к узлу сети, пускай на правах гостя, — это уже происшествие, а вход в систему с привилегиями администратора — настоящая катастрофа.

Разумеется, на рабочей станции пароль администратора не хранится. Собственно, в Windows NT пароли вообще нигде не хранятся. Вместо этого в базу данных SAM (Security Account Manager) заносятся хэш-значения паролей. Сама база хранится в файле %SystemRoot%SYSTEM32CONFIGSAM, доступ к которому закрыт системой. Файл SAM представляет собой ветвь реестра HKEY_LOCAL_MACHINESECURITYSAM, права на чтение которого предоставляются только администратору (и то по умолчанию они заблокированы). Функции API, манипулирующие именами пользователя и хэш-значением, недоступны непривилегированным пользователям. Словом, защита выглядит на первый взгляд безупречной и неприступной.

Между тем резервная копия системы, хранящаяся в каталоге %SystemRoot%Repair, в любое время доступна каждому члену группы Everyone (в Windows 2000 это упущение уже исправлено)! Резервная копия создается при установке (или переустановке) Windows NT, а также всякий раз при запуске утилиты rdisk с ключом /s. Распаковав файл с помощью команды expand sam._ sam (резервная копия хранится в упакованном виде), злоумышленник сможет извлечь из него имена пользователей и хэш-значения паролей.

Конечно, самих паролей в базе не будет, но для удаленной регистрации они и не нужны! Поэтому злоумышленнику без труда удастся подключиться к серверу. И если на нем окажется свежая резервная копия файла SAM с действующим паролем администратора, то... Вообще-то, опытный администратор заранее отключит все гостевые выходы и уничтожит резервные копии (либо лишит пользователей прав доступа к ним), но все же описанная атака достаточно часто оказывается успешной.

Но, помимо гостевого входа, отключить который очень просто, в Windows NT предусмотрена поддержка анонимного пользователя с правами на просмотр списка пользователей, разделенных ресурсов и некоторых (между прочим, достаточно многих) ветвей системного реестра. Анонимный пользователь необходим для организации нуль сеансов (NULL session), предназначенных для выполнения действий, не требующих аутентификации (или в тех случаях, когда аутентификация невозможна). Например, пусть в сети находятся два домена Windows NT, условно обозначаемых D1 и D2. Если D1 доверяет D2, а сам D2 не доверяет D1, то для получения списка пользователей и групп домена D2 приходится прибегать к анонимному подключению.

Анонимным пользователям доступен специальный ресурс IPC$ (inter-process communication), подключить который можно командой net use ameIPC$ /USER:, где name — сетевое имя компьютера или его IP-адрес. Таким образом, злоумышленник получает возможность запускать User Manager для просмотра пользователей и групп, Event Viewer — для просмотра журнала событий, а кроме того, другие средства удаленного администрирования, где используется протокол SMB.

Ветвь реестра HKLMSoftware MicrosoftWindowsCurrentVersionRun содержит имена программ, запускаемых при каждой локальной регистрации пользователя, причем она доступна анонимному пользователю как для чтения, так и для модификации. Изменяя ее по своему усмотрению, злоумышленник сможет выполнить не только одну из программ, хранящихся на сервере, но и любую программу, из установленных на его компьютере! Для этого он должен записать нечто вроде mycomputer myprog.bat, где mycomputer — имя компьютера злоумышленника или его IP-адрес. Командный файл выполняется с привилегиями локального пользователя (а локально на сервере, как правило, регистрируются администраторы). А получив права администратора, злоумышленник может сделать с сервером все что угодно (например, узнать имена и хэш-значения всех остальных пользователей).

В 1997 г. появилась программная реализация такой атаки, получившая название RedButton. Компания Microsoft выпустила «горячую» заплатку для Windows NT 3.51 и включила соответствующие исправления в Service Pack 3 для Windows NT 4.0. Одновременно в «базе знаний» Microsoft (Microsoft Knowledge Base) было опубликовано достаточно подробное техническое описание сути проблемы (документ Q143474).

Но Service Pack не устранял возможность анонимного подключения, а только ограничивал права анонимного пользователя. Компания Microsoft открыто признает (в документе Q129457), что «...в случае разрешения доступа RestrictAnonymous анонимное соединение может получить информацию о политике в отношении паролей с Windows NT Server. Данная политика определяет правила для домена Windows NT касательно минимальной длины паролей, допустимости пустых паролей, срока годности и истории паролей».

Технически регистрация в системе организована так, что проверка политики в отношении паролей осуществляется до аутентификации пользователя. Например, заведомо короткий пароль не стоит и проверять. В Windows NT правила доступны всем, в том числе и анонимному пользователю (даже после установки Service Pack 3!). В результате злоумышленник сможет узнать: минимальную длину пароля, как часто меняются пароли и какое количество неудачных попыток регистрации блокирует учетную запись (если блокировка включена). Полученная информация значительно облегчает проникновение в систему.

А еще в правилах открыто хранятся предыдущие используемые пароли или их хэши (так называемая история паролей). С точки зрения безопасности пароли необходимо периодически менять, причем они не должны повторятся (во всяком случае, спустя короткое время). Например, в истории могут храниться пять последних паролей пользователя, и при смене пароля система проверяет, не совпадает ли новый пароль с одним из них. Конечно, это старые, уже недействительные пароли. Однако знакомство с ними позволяет понять, по какому принципу назначаются пароли: выбираются ли словарные слова, даты рождения родственников, имена любимых хомячков или абсолютно случайные последовательности. Кстати, не исключено, что рано или поздно пользователь вновь выберет один из старых паролей, возможно, несколько его видоизменив.

Microsoft подтверждает наличие этой «дыры» (подробности в документе Q129457), предостерегая пользователей и администраторов от повторного выбора паролей. Но это не решает проблемы. Если пароли выбираются не абсолютно случайно, то, изучая их последовательность, злоумышленник может угадать очередной пароль или, по крайней мере, сократить число вариантов перебора. Среди множества пользователей наверняка окажется тот, кто халатно относится к требованиям соблюдения политики безопасности и всегда выбирает короткие, запоминающиеся последовательности символов (а, следовательно, предсказуемые).

Как утверждают специалисты Microsoft, Windows NT позволяет ограничить рабочие станции, с которых пользователь может входить в систему. И это чистая правда — администратор в состоянии легко контролировать легального пользователя (в чем нетрудно убедиться каждому). Казалось бы, у злоумышленника не остается шансов проникнуть в сеть, даже если он вооружен именем и паролем пользователя. Увы! Прикладной протокол SMB реализуется поверх транспортных протоколов, совместимых с интерфейсом NetBIOS. А при установлении соединения по протоколу NetBIOS, сервер проверяет имя, сообщенное ему клиентом, а не его IP-адрес! Злоумышленнику достаточно знать или выяснить методом перебора, с каких рабочих станций разрешен вход на сервер, а подделать их имена — дело техники. Если быть совсем точным, сервер NetBIOS вообще не проверяет переданное клиентом имя — это забота сервера SMB, а до начала сеанса SMB никакого протоколирования установленных соединений не ведется!

Другую полезную для себя информацию злоумышленник может получить с помощью протокола SNMP. Данный протокол предназначен для мониторинга сети, и с его помощью администраторы могут отслеживать и оперативно реагировать на возникшие проблемы, а также настраивать сеть на максимальную производительность. Одна из задач, возлагаемых на SNMP, — поддержка распределенной базы управляющей информации (Management Information Base, MIB). На узлах сети находятся агенты — программные модули для сбора информации об управляемых объектах, сохраняющие полученную информацию в своих локальных переменных. Протокол SNMP обеспечивает обмен контрольной информацией между элементами сети и доступ к базе MIB.

При обмене сообщениями агенты используют механизмы аутентификации (часто уязвимые для взлома), а для доступа к базе MIB злоумышленнику достаточно знать так называемое имя сообщества (community name), по умолчанию public. Среди прочего в базе MIB Windows NT содержится следующая информация:

  1. таблица сервисов, выполняющихся на сервере, включая название и состояние сервиса;
  2. число зарегистрированных неудачных попыток ввода пароля на сервере;
  3. тип разграничения доступа (на уровне пользователей или на уровне ресурсов);
  4. перечень сеансов, включая имена станций клиентов и состояние сеанса;
  5. перечень учетных записей сервера;
  6. перечень разделяемых ресурсов сервера с указанием локальных путей.

Очевидно, что информация подобного рода значительно упрощает несанкционированное вторжение в систему и не должна быть доступна. Известно множество случаев, когда полученная с помощью сервиса finger информация — а этот сервис сообщает значительно меньше данных об активных пользователях — использовалась для проведения успешной удаленной атаки. В наши дни finger уже становится «экзотикой», так как обычно администраторы его отключают. Насколько же богаче информация, которую злоумышленник получает из базы MIB и с помощью нуль-сеанса! Но, в отличие от сервиса finger, их не так-то легко отключить!

Все просчеты в системе безопасности, описанные выше, в той или иной мере устраняются правильным администрированием сети и не гарантируют злоумышленнику проникновения в систему. Часто атакующий действует наугад, отыскивая наименее защищенный узел, а не пытается получить доступ к какой-то одной, конкретной машине.

РАСПАД ЯДРА

Если в коде ядра присутствуют ошибки, позволяющие пользователю вмешиваться в работу системных процессов, то он сможет получить любые привилегии, в том числе и администратора! Изучая работу модуля ntoskrnl.exe, Константин Соболев обратил внимание на то, что функция NtAddAtom не контролирует значение аргумента, указывающего адрес для записи результатов своей работы. Поскольку функция NtAddAtom выполняется ядром и имеет привилегии System, она может писать, что ей вздумается и куда вздумается. Между тем функция win32 API AddAtom содержит переходной код, который сохраняет результат работы NtAddAtom в локальной переменной, откуда и возвращает значение пользователю. Однако через прерывание 0x2E можно получить доступ непосредственно к функциям ядра, минуя высокоуровневые оболочки.

Вообще же, если у пользователя есть право отладки приложений, то ему доступны функции WriteProcessMemory и CreateRemoteThread, с помощью которых он может как угодно манипулировать системой по своему усмотрению. Поскольку ни один здравомыслящий администратор потенциальному злоумышленнику такого права не даст, тому приходится присваивать его самостоятельно. Описание алгоритма подобной атаки выходит за рамки данной статьи, мы же лишь отметим, что утилита Sechole, авторами которой являются Прасад Дэбак, Сандип Фадке и Милинд Борейт, позволяет заменить код функции OpenProcess (проверяющей наличие прав отладки приложений перед открытием процесса) и затем, пользуясь отладочными функциями, включить текущего пользователя в группу администраторов.

Служба редиректора также имеет ошибки реализации, позволяющие любому пользователю получить права администратора или нарушить нормальную работу сервера, поэтому на ней имеет смысл остановиться подробнее.

ЛЮКИ В КАНАЛАХ

Именованные каналы представляют собой механизм межсетевой передачи данных по виртуальному каналу, гарантирующему доставку сообщений. (Почтовые ящики не гарантируют доставку сообщений, и процесс-отправитель не получает уведомления о доставке адресату сообщения.) Каналы реализованы в виде псевдофайловой системы именованных каналов (Named Pipes File System, NPFS), которая хранит все сообщения в памяти и выдает их по запросу. Имена сообщений представляются в виде pipepipaname и доступны для тех же функций, что и обыкновенные файлы (например, CreateFile, ReadFile, WriteFile).

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

Создать экземпляр уже существующего канала может любой процесс, независимо от его привилегий и прав доступа. Система примет новый экземпляр канала на равных правах со старым. И, когда все созданные ранее экземпляры окажутся занятыми, очередной клиент, желающий установить соединение, будет связан с подложным каналом. При этом функции интерфейса приложений не позволяют клиенту узнать, какой процесс обрабатывает канал, с которым клиент установил соединение!

Это дает возможность внедрять в вычислительную систему ложные объекты и перехватывать входящий трафик. Более того, у злоумышленника появляется возможность унаследовать права клиента! Процессу, породившему экземпляр канала, достаточно вызвать функцию ImpersonateNamedPipeClient, выполняющую олицетворение клиента. Вообще-то, эта функция задумывалась как раз с обратной целью — понижения привилегий потока, выполняющего олицетворение.

Стремясь сделать систему более защищенной, разработчики предложили временно назначать потоку, обрабатывающему подключение, права клиента, установившего соединение. Пока привилегии клиента не превышают привилегий сервера (а обычно это так и есть), ничего интересного не происходит. Но как только пользователь из группы guest (или Everyone) создаст подложный экземпляр потока и дождется подключения привилегированного клиента (или администратора!), у него появится возможность увеличить свои права (иногда весьма значительно)!

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

Впрочем, возможности у злоумышленника, к счастью, далеко не безграничны. Дело в том, что олицетворяется не пользователь, а поток, и по наследству полученные привилегии не передаются. Это происходит потому, что в Windows NT новому процессу назначается маркер доступа процесса-родителя, а не маркер доступа потока, вызывающего CreateProcess. Поэтому злоумышленник не сможет запустить ни одну программу, требующую прав администратора. Впрочем, ему не нужно этого делать — достаточно воспользоваться соответствующими системными функциями (а они доступны, включая те, выполнение которых требует наличия прав администратора).

Программная реализация такой атаки осуществлена В. Проскуриным совместно с П. Девяниным и С. Заливакиным. Программа AdminTrap (http://hackzone.ru/articles/AdmTrap.zip) создает «троянский» экземпляр одного из системных каналов и ждет подключения клиента. Если получение прав администратора проходит успешно, то, демонстрируя описанную выше «слабость», программа создает нового пользователя в группе «Администраторы», но для предотвращения несанкционированного доступа в систему вновь созданная учетная запись тут же блокируется. Очевидно, разработчики не ставили перед собой цель вторгнуться в чужие системы, а стремились показать наличие такой уязвимости.

Здесь необходимо привести одно незначительное техническое уточнение. Поскольку системные сервисы заранее создают несколько экземпляров каналов, то, скорее всего, подложный экземпляр канала никогда не дождется клиента (в самом деле, в какой системе наберется десяток одновременно работающих администраторов?). Поэтому все существующие каналы необходимо занять работой, и заблокировать сервер, чтобы он не мог создавать новые экземпляры.

И такая возможность есть! Системные сервисы в Windows NT не ограничивают максимальное количество создаваемых экземпляров канала, а каждый канал, как правило, обрабатывается отдельным потоком (т. е. происходит классическое, популярное со времен UNIX, расщепление процесса-обработчика при запросе на очередное подключение). Все потоки и каждый экземпляр канала требуют некоторого количества оперативной памяти, и, если злоумышленник вздумает в бесконечном цикле устанавливать все новые и новые соединения, оперативной памяти может попросту не хватить!

На первый взгляд никакой опасности нет, — Windows NT поддерживает виртуальную память и при необходимости умеет выгружать наименее нужные страницы на диск. Злоумышленник же физически не сможет работать со всеми установленными соединениями одновременно (памяти на его компьютере будет, скорее всего, меньше, чем у сервера), и неактивные потоки без ущерба для производительности могут быть переведены в файл подкачки. Кажется, все определяется лишь количеством свободного места на диске.

Но при создании канала система размещает входящий и исходящий буферы в неоткачиваемой памяти (non-paged pool). Поэтому максимальное количество экземпляров канала определяется объемом неоткачиваемой памяти, выделенной процессу. Таким образом, существует возможность как заблокировать создание новых экземпляров канала, так и замедлить работу системы, отобрав у системных процессов всю свободную оперативную память и заставляя их за каждой страницей обращаться к диску.

Идея подобной атаки, которую окрестили PipeBomb, принадлежит П. Девянину, а С. Заливакиным создана ее программная реализация.

Комбинируя AdminTrap со строго дозированным воздействием на систему посредством PipeBomb, они смогли перехватить два соединения: winreg, управляющее удаленным доступом к реестру, и spoolss, отвечающее за удаленное управление принтером. Однако не исключено, что таким способом удастся перехватить и другие соединения, в том числе служебные, выполняемые системой без непосредственного участия администратора. Например, каналы lsass и LANMAN используются для передачи по сети имени пользователя и хэш-значения пароля во время сеанса аутентификации, а механизм удаленного вызова процедур (RCP) задействует канал lsarpc.

Обе атаки успешно реализуются в среде Windows NT 4.0 со всеми установленными Service Pack как в отношении рабочей станции, так и сервера. Они осуществимы как из локальной сети, так и из Internet, поскольку основаны на прикладном протоколе SMB, а он, как известно, может быть реализован поверх транспортного протокола TCP. Трафик Internet можно перекрыть административными средствами, установив фильтр, отсекающий все пакеты, содержащие заголовки SMB, но такая мера неэффективна против злоумышленников, находящихся внутри локальной сети.

Компания Microsoft устранила эту проблему в Windows 2000, выпустив 2 августа 2000 г. заплату Service Control Manager Named Pipe Impersonation, получить которую можно, обратившись по адресу: http://www.microsoft.com/Downloads/ Release.asp?ReleaseID=23432. Данная заплата необходима для всех трех платформ — Microsoft Windows 2000 Professional, Microsoft Windows 2000 Server и Microsoft Windows 2000 Advanced Server, а это значит, что нерасторопные администраторы рискуют подвергнуться атаке. Подробнее об этом можно прочитать в технической заметке Microsoft Security Bulletin (MS00-053).

Вообще же отсутствие ограничений на количество создаваемых объектов в NT носит повсеместный характер. Наиболее известный и характерный пример — атакующая программа, создающая в бесконечном цикле огромное количество окон. Когда же отведенный системой лимит исчерпывается (все на свете рано или поздно кончается), никто, даже ядро системы, не может создать новое окно. Ни работать на компьютере, ни удалить процесс, ни даже завершить работу системы уже нельзя, потому что для этого необходимо вызвать либо «Менеджер задач», либо диалог «Завершение работы», между тем новые окна создать невозможно! Все, что остается, — это нажать «заветную» клавишу Reset или выдернуть шнур из сети. Насколько мне известно, Microsoft ограничилась паллиативным решением — окно Менеджера задач создавалось сразу же после старта системы, но не отображалось на экране, пока в нем не было необходимости, а вызов Менеджера задач только менял атрибуты уже существующего окна, чтобы он мог быть доступен в любой критической ситуации.

Спустя некоторое время появилась простая программа, вместо окон в бесконечном цикле порождающая потоки (а количество потоков, принадлежащих процессу, не ограничено, независимо от его привилегий). Потоки же способны «съесть» все процессорное время; остальные процессы с равным (или низшим) приоритетом практически «замрут». Впрочем, если у злоумышленника нет права выполнять процессы с приоритетом выше среднего, т. е. Normal (как правило, она у него имеется), то злонамеренную программу можно удалить с помощью Менеджера задач, но, увы, не автоматически. Если же атака будет осуществлена на сервер, то многие приложения окажутся парализованными до вмешательства администратора.

Итак, ситуацию с каналами нельзя отнести в разряд непредвиденных, однако — это первая реализация удаленного перехвата, устранить которую не позволяет даже правильное администрирование. И никто не гарантирует, что завтра не обнаружатся новые серьезные «дыры» в системе безопасности. Даже наверняка обнаружатся. Только вот где, как и когда?

Крис Касперски — независимый автор. С ним можно связаться по адресу: kpnc@sendmail.ru.


Среди грязного белья

Мусорные баки и корзины издавна служили источником ценной информации. И, копаясь в корзине для мусора Windows NT, злоумышленник также может извлечь на свет документ, содержащий конфиденциальные данные.

Поэтому в Windows NT существует возможность предоставления каждому пользователю своей собственной корзины. В обычной ситуации никакой пользователь не может получить доступ к чужой корзине, если он не обладает правами администратора. Но друг от друга корзины отличаются всего лишь идентификатором пользователя SID, который злоумышленник может легко выяснить (с помощью специальных функций API идентификатор пользователя можно установить по его имени). Если злоумышленник изменит идентификатор своей корзины на идентификатор корзины жертвы, то удаляемые жертвой файлы попадут в руки злоумышленника.

Впрочем, если существуют две корзины с одинаковыми идентификаторами, система будет вести себя непредсказуемо. Поэтому стабильная работа обеспечивается лишь в том случае, когда злоумышленник подделывает свою корзину до создания корзины жертвы, что маловероятно, так как обычно корзина создается сразу же после регистрации нового пользователя системы. Но до регистрации пользователя его SID не известен.

Таким образом, подобная уязвимость, достаточно любопытная сама по себе, не представляет большой опасности.