Рубрика:
Администрирование /
Администрирование
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
Вадим Андросов
Реализуем нестандартные правила управления доступом на основе архитектуры организации в Windows Server 2003
Как создать надстройку для Windows 2003 Server, управляющую допуском на компьютеры на основе модели архитектуры организации.
Подготовка к созданию надстройки
Операционная система Windows 2003 Server поддерживает широкий набор настроек безопасности, в том числе и на основе информационно-управленческой архитектуры (ИУА) организации. Так, с помощью оснастки «Active Directory Users and Computers» возможно создание структурной модели предприятия. Далее с помощью групповых политик безопасности настраиваются необходимые параметры защиты, привязанные к структурным единицам организации.
Данная тема подробно освещена в литературе, посвященной администрированию серверных операционных систем Microsof [1-5], в статье же будут рассмотрены возможности расширения средств управления доступом к рабочим станциям для реализации особых правил, не предусмотренных в стандартных утилитах.
Существуют различные механизмы добавления новой функциональности. Остановимся на самом простом методе с использованием сценариев. Этот подход не требует наличия никаких специальных инструментальных средств, тем не менее позволяя полноценно реализовать задуманное.
В рамках статьи будет продемонстрировано создание механизма разграничения доступа пользователей на компьютеры. Рассмотрим следующий пример (см. рис. 1).
Рисунок 1. Модель архитектуры организации
Часто на предприятиях существуют отделы с особой пропускной системой сотрудников. Причем это не обязательно секретные военные организации. В коммерческой фирме также может существовать информация, оберегаемая от конкурентов (списки контрагентов, рецептуры продукции, способы производства и т. п.).
Распространена практика изоляции работы с закрываемой информацией в рамках специальных отделов. Здесь обычно применяется более тщательный подбор кадров, особая пропускная система. Конечно, стандартные средства разграничения доступа Windows 2003 позволяют защитить основные ресурсы. Однако в случае высокой сложности архитектуры организации и тем более ее динамичности (например, отдел, работающий со скрываемой информацией, может быть перенесен в другое подразделение) уследить за всем становится невозможно.
Сегодня мы рассмотрим пример обеспечения автоматического контроля за доступом к рабочим станциям на основе модели архитектуры организации. Конечно, это не законченный механизм, который позволит искоренить промышленный шпионаж. Скорее, речь идет о демонстрации возможностей внедрения удобных и прозрачных механизмов контроля доступа на основе модели предприятия.
Создаваемая надстройка носит на данный момент экспериментальный характер, поскольку достаточного опыта использования архитектуры организации для контроля доступа к объектам информационной подсистемы нет. Пока речь идет только о полнофункциональном макете, который хоть и обеспечивает дополнительные возможности разграничения доступа, но не претендует на звание законченного продукта.
Только после достаточно продолжительного полноценного использования можно будет говорить о конкретных результатах, пока же приводятся выводы, сделанные на основе нескольких тестовых внедрений.
Управление доступом к рабочим станциям на базе архитектуры организации позволит более эффективно обеспечивать и защиту секретной информации. Как уже говорилось, работа с этими данными часто сосредоточена в рамках определенных отделов с особым режимом допуска. Однако широкое применение информационных технологий заметно скомпрометировало этот отработанный в течение многих лет механизм. То, что раньше нужно было как-то вынести, теперь можно передать по сети. Это привело к ослаблению физического контроля над допуском на территорию закрытых отделов и смещению акцентов защиты данных к программным средствам. Но упрощенный доступ к рабочим станциям тут же понизил эффективность информационной защиты.
Да, получить физический доступ к базе данных на сервере практически невозможно (если злоумышленник – не администратор системы). Однако очень много информации хранится на локальных компьютерах: файл-серверные базы данных (а это не редкость даже на сегодняшний день), таблицы Excel, документы Word и тому подобное. Если же с данными работает несколько человек в разные смены, то общие файлы почти наверняка окажутся в доступном для всех месте…
Конечно, почти все это – вопросы культуры работы со скрываемой информацией. Но если бы эта культура существовала в реальной жизни, то не было бы систем типа Windows 2003 Server.
Так что важно иметь возможность управлять доступом к рабочим станциям на основе их принадлежности не только конкретному домену, но и подразделению. Таким образом, мы защитим локальную свободно доступную информацию. Так что именно повышение эффективности защиты информации – конечная цель предлагаемой надстройки, хоть непосредственно с секретными объектами работа и не ведется.
Постановка задачи
Для начала реализуем максимально простое правило – на компьютеры отдела должны иметь возможность входа только пользователи того же отдела. Так, для приведенной модели пользоваться компьютером CCLI должны иметь возможность только сотрудники организационной единицы «Accounting». При этом решение хотелось бы сделать устойчивым к изменениям в архитектуре. То есть при добавлении пользователя в этот отдел он автоматически должен допускаться к соответствующим компьютерам. Также удаление пользователя должно влечь за собой потерю им прав использования рабочими станциями отдела. Это можно сделать с использованием простого стартового сценария (на языке VBScript).
Set objSysInfo = CreateObject("ADSystemInfo")
userOU = getOU(objSysInfo.UserName)
compOU = getOU(objSysInfo.ComputerName)
if compOU <> userOU then
set shellObj = CreateObject("WScript.Shell")
shellObj.exec "shutdown /l"
end if
function getOU(dn)
getOU = right(dn, len(dn) - instr(1, dn, ",", vbTextCompare))
end function
Сценарий основан на использовании отличительных имен объектов (distinguished name или DN) пользователей и компьютеров. Эти имена содержат не только название объекта, но и его положение в архитектуре организации. Например, для пользователя «John Zoidberg», работающего в отделе «Aid post» предприятия «Planet Express», компьютеры которого объединены в домен «futurama.mult», полное имя будет выглядеть следующим образом:
CN=John Zoidberg,OU=Aid post,OU= Planet Express,DC=futurama,DC=mult
Здесь CN обозначает «common name» (общее имя), OU – «Organizational unit» (организационная единица, структурное подразделение предприятия), DC – «Domain Component» (доменный компонент). Программа определяет контейнеры, в которых расположены учетные записи пользователя и компьютера, и, если они не совпадают, завершает сеанс пользователя.
На организацию (в нашем примере – на организационную единицу «Предприятие») накладывается групповая политика безопасности, в соответствии с которой созданный сценарий должен запускаться при каждой попытке входа пользователя на рабочую станцию (logon script).
Однако подобное решение недостаточно жизнеспособно. Случаи, когда на компьютерах отдела могут работать только его сотрудники, не так уж сильно распространены. Гораздо чаще требуется ограничить использование рабочих станций в пределах целого подразделения, объединяющего в себе ряд отделов.
Кроме того, попытка входа на запрещенный компьютер является опасной ситуацией (особенно для предприятий, работающих со скрываемой информацией), которая требует принятия немедленных мер. Будет хорошо, если наша настройка сможет не просто регулировать доступ, но и выполнять действия, лишающие предполагаемого злоумышленника возможности дальнейшей работы.
Расширим надстройку, приведя ее к более реалистичному виду. Для начала сформулируем правила доступа на компьютеры:
- Существует ряд отделов, доступ на компьютеры которых предоставляется только сотрудникам подразделения.
- В некоторых отделах доступ к рабочим станциям имеют сотрудники самого подразделения и всех дочерних. То есть компьютеры доступны в рамках поддерева.
- Администратор должен иметь возможность блокировки, как конкретного отдела, так и поддерева подразделений. В заблокированных подразделениях полностью запрещается вход на компьютеры.
- При попытке несанкционированного доступа к компьютеру сессия должна быть завершена, руководитель подразделения поставлен в известность. Если текущей организационной единице глава не назначен – уведомляется руководитель родительского подразделения. Профиль пользователя должен быть заблокирован, в свойствах сохранена информация о причине блокировки. Таким образом, о запрещенной попытке входа уведомляются сразу два человека: руководитель подразделения и администратор (к которому пользователь должен будет обратиться для разблокирования своего профиля).
Расширение схемы Active Directory
Непосредственных средств поддержки приведенных правил в операционной системе нет. Первым этапом их разработки должно стать расширение схемы Active Directory. Для наших правил потребуется добавить в стандартные объекты ряд атрибутов.
Для пользователя ограничимся существующими атрибутами, причину блокировки будем сохранять в поле «description».
Для организационных единиц введем несколько новых атрибутов:
- Статус. Будет обозначать тип подразделения: со свободным доступом к компьютерам, с доступом только своих сотрудников, с доступом своих сотрудников и сотрудников дочерних подразделений. Тип можно использовать как числовой (будет занимать меньше места, однако придется помнить соответствие числа и типа отдела), так и строковый (занимает много места, но более информативен). Поскольку для эффективного администрирования наглядность играет большую роль, чем экономия места, остановимся на строковом типе данных.
- Заблокирован. Признак блокировки отдела. Логическое поле.
Для реализации приведенных правил будет достаточно этих двух атрибутов.
В статье рассматривается создание только работоспособного макета механизма управления доступом на основе архитектуры организации. Концепция конечного варианта будет окончательно сформулирована только после испытаний макета. Так, с большой уверенностью можно говорить о том, что появится необходимость в других атрибутах и правилах.
Наиболее вероятные кандидаты в этом смысле – различные счетчики попыток несанкционированного доступа. Так, счетчик, привязанный к объекту пользователя, позволит знать, насколько часто профиль использовался для недопустимого входа на рабочую станцию. Но пока предполагается, что подобное происшествие приводит к блокировке профиля, решение о снятии которой принимается только после принятия каких-то мер.
Более полезным видится счетчик несанкционированных попыток входа на определенную рабочую станцию. На основе его анализа можно эффективно обнаруживать дыры в организационных методах защиты (недобросовестный охранник, открытое окно на улицу).
Пока эти свойства не были добавлены потому, что они только усложнили бы надстройку, не добавляя в нее принципиально новой функциональности. Кроме того, не был окончательно решен вопрос их хранения. Здесь для упрощения доступа и анализа, возможно, лучше будет сохранять информацию не в Active Directory, а во внешней СУБД.
Добавление новых свойств в объекты Active Directory осуществляется с помощью специальной оснастки «Active Directory Schema». Об опасности ее применения свидетельствуют средства защиты, беспрецедентные для операционных систем Windows:
- Оснастка не устанавливается вместе с операционной системой. Вместо этого в папке System32 расположен дистрибутив (adminpak.msi), который нужно отдельно установить.
- После установки оснастка не появляется в меню «Пуск», ее нужно вручную добавлять в консоль MMC.
- По умолчанию можно только просматривать элементы схемы – для возможности изменения нужно создать запись в реестре (HKEY_LOCAL_MACHINE\ System\ Current Control Set\ Services \NTDS\ Parameters) типа DWORD с именем «Schema update allowed» и значением 1 (0 отключает режим редактирования – рекомендуется установить это значение после завершения изменения схемы).
Это объясняется тем, что ошибки в схеме могут привести к некорректной работе всего домена. Кроме того, все изменения схемы необратимы, другими словами, добавив атрибут, его уже невозможно удалить или изменить (но можно отключить). Присутствует и более привычный механизм защиты: чтобы получить право модифицировать схему, пользователь должен входить в группу Schema Admins.
Сначала создаются атрибуты: OULocked (признак блокировки организационной единицы), OUState (состояние) (см. рис. 2).
Рисунок 2. Новые атрибуты схемы
Непосредственное добавление атрибутов во встроенные классы операционной системы возможно, но делать это настоятельно не рекомендуется. Поэтому создадим специальный дополнительный (auxiliary) класс OURulesEx, в который и добавим новые атрибуты (см. рис. 3).
Рисунок 3. Класс с дополнительными свойствами
Затем он будет присоединен к существующему классу (в нашем случае – к классу организационной единицы). Новые атрибуты сделаем необязательными (чтобы упростить внедрение в случаях, когда требуется добавить правило к действующей модели организации). Таким образом, теперь мы сможем использовать для организационных единиц созданные атрибуты. Несмотря на высокую защиту, процесс добавления пользовательских свойств в системные классы (как и создание пользовательских) можно считать удобным и прозрачным.
Изменения, сделанные в процессе разработки текущей надстройки, не привели к некорректной работе операционной системы. Но если вы планируете добавить свои атрибуты и тем более классы, сделайте это сначала на тестовой конфигурации, которую в случае чего можно будет безболезненно переустановить.
После модификации схемы организационные единицы поддерживают необходимые свойства, далее требуется создать механизмы их использования. Для начала реализуем функции доступа к новым свойствам. Приведем пример реализации только для свойства UOLocked, поскольку доступ к свойству OUState происходит аналогичным образом.
function isOULocked(dn)
Set objOU = GetObject("LDAP://" & dn)
isOULocked = objOU.OULocked
if isEmpty(isOULocked) then isOULocked = false
end function
function setOULocked(dn, lock)
Set objOU = GetObject("LDAP://" & dn)
objOU.OULocked = lock
objOU.setInfo
end function
Приведена пара функций для проверки и установки значения свойства блокировки организационной единицы. Для доступа к объектам используется привязка с помощью протокола LDAP. Как можно видеть, после привязки к объекту мы можем сразу использовать введенные свойства. Случаи, когда значение свойства не определено, можно отследить с помощью функции isEmpty. Так, после добавления новых свойств для всех организационных единиц значение isEmpty(objOU.OULocked) будет истинно. Функция isOULocked в этом случае сообщает о незаблокированной организационной единице.
Подробнее остановимся на особенности добавления новых полей в стандартные классы операционной системы. После добавления поля в схему оно становится доступным для использования во всех новых объектах измененного класса. Однако что происходит с объектами, существующими на момент добавления нового свойства? Как выяснилось, в них новые свойства также появляются (по крайней мере, необязательные (optional)), проанализированные пустым значением. Скорее всего, необязательные параметры физически хранятся в списке в виде пар «название, значение», неинициализированные свойства отсутствуют в списке, а их пустое значение моделируется в процессе доступа. Подобный подход позволяет хранить объекты классов с очень большим возможным количеством редко используемых атрибутов, избегая лишних расходов на хранение. Поэтому специальной инициализации новых свойств для существующих объектов не требуется – достаточно проверки с помощью функции isEmpty в функциях доступа и возврата удобного значения по умолчанию.
Приступим к практической реализации.
Разработка необходимых функций
Windows 2003 уже содержит средства, позволяющие задавать руководителей подразделений. Это можно сделать с помощью окна свойств организационной единицы (см. рис. 4).
Рисунок 4. Задание руководителя отдела
Рассмотрим вспомогательную функцию для определения, в каком отделе находится объект (пользователь, компьютер или организационная единица).
function getParent(dn)
if UCase(Left(dn, 2))="DC" then
getParent = ""
else
getParent = right(dn, len(dn) - instr(1, dn, ",", vbTextCompare))
end if
end function
Функция getParent отбрасывает общее имя (первый элемент – CN) с помощью функций обработки строк. Таким образом, остается подстрока, описывающая положение объекта (пользователя, компьютера или организационной единицы) в архитектуре организации. Если достигнут корень иерархии (родительского элемента нет), функция возвращает пустую строку. В нашем случае корневым элементом является первый доменный компонент (DC). Например, для имени пользователя «CN=Gomer, OU=Security, OU=aes, DC=simpsons, DC=ua» корневым элементом является «DC=simpsons, DC=ua».
Напишем сценарий, реализующий усложненные правила входа на компьютеры на основе ИУА организации. Так будет выглядеть тело основной функции проверки допустимости входа на рабочую станцию.
function isAllowed(userDN, compDN)
Функция принимает два параметра: полные имена пользователя и компьютера, на который осуществляется вход. Как уже говорилось, полное имя компьютера содержит информацию о положении объекта в ИУА предприятия.
isAllowed = STATE_ALLOWED
Изначально считается, что вход на компьютер разрешен (возврат константы STATE_ALLOWED означает, что пользователь имеет право доступа на компьютер).
dim compOU, userOU
compOU = getParent(compDN)
userOU = getParent(userDN)
Затем для каждого объекта определяется имя контейнера (организационной единицы), которому они принадлежат.
if isOuLocked(compOU) then
isAllowed = STATE_LOCKED
exit function
end if
Первая проверка – не заблокирована ли текущая организационная единица. Если заблокирована, функция возвращает признак недопустимости входа. Далее мы увидим, что функция может возвращать несколько значений. Но только STATE_ALLOWED разрешает пользователю зайти на компьютер, остальные значения представляют собой запреты (такой подход был использован, чтобы зависимые от этой функции подпрограммы могли узнать причину запрета). В рассматриваемом макете эта дополнительная информация нигде не используется, однако она наверняка понадобится при расширении функциональности надстройки.
if userOU = compOU then
exit function
end if
Если пользователь и компьютер находятся в одной незаблокированной организационной единице, то доступ разрешается.
if getOUState(compOU) = STATE_EXPLICIT then
isAllowed = STATE_EXPLICIT
exit function
end if
Если же они принадлежат различным контейнерам и при этом организационная единица, в которой расположен компьютер, помечена как STATE_EXPLICIT, то вход запрещается. STATE_EXPLICIT обозначает подразделение, где пользоваться компьютерами могут только свои сотрудники (такое правило было реализовано в начале статьи).
dim compTreeRoot
compTreeRoot = getTreeRoot(compOU)
if compTreeRoot <> getTreeRoot(userOU) then
if compTreeRoot <> EMPTY_STR then isAllowed = STATE_TREE
exit function
end if
end function
И последним проверяется правило для организационных единиц, допускающих к работе также сотрудников дочерних отделов. Функция getTreeRoot поднимается вверх по дереву структуры предприятия до тех пор, пока не встретит первое подразделение, помеченное как STATE_TREE. В случае если таких организационных единиц найдено не было, возвращается пустая строка.
function getTreeRoot(dn)
if (dn=EMPTY_STR) then
getTreeRoot = dn
exit function
end if
if (getOUState(dn)=STATE_TREE) then
getTreeRoot = dn
exit function
end if
getTreeRoot = getTreeRoot(getParent(dn))
end function
Для реализации правила достаточно провести такой поиск дважды: начиная от пользователя и от компьютера. И если в результате будет получен один и тот же корень, доступ разрешается. Отмечу особенность реализации последнего правила. В случае наличия вложенных организационных единиц с общим доступом к компьютерам сотрудников дочерних подразделений разрешение доступа через нашу функцию передано не будет. При такой реализации сотрудники подструктур с отличными настройками безопасности не могут использовать рабочие станции из родительских подразделений.
Рассмотрим пример (см. рис. 5). Допустим, для архитектуры, приведенной на рис. 2, для организационной единицы «Производство» установлено свойство STATE_TREE (т.е. разрешение общего использования компьютеров в рамках всего поддерева). В этом случае пользователь, принадлежащий подразделению «Цех», может пользоваться компьютерами, установленными в «Производство». Однако если установить такой атрибут еще и для подразделения «Учет», то пользователи могут работать только с компьютерами своего поддерева. Другими словами, пользователь из отдела «Бухгалтерия» сможет воспользоваться компьютером в архиве, но не сможет в цехе. Правила доступа поддерева перекрывают правила родительских единиц.
Рисунок 5. Пример архитектуры предприятия
Такое решение представляется более защищенным, хотя может и не удовлетворять политике разрешения доступа некоторых организаций. Для реализации альтернативных правил потребуется незначительная модификация приведенной функции.
Перейдем к реализации функций реакции на запрещенные попытки входа. Во-первых, профиль пользователя должен быть автоматически заблокирован. Это достаточно простая операция, однако нужно помнить, что сценарии входа выполняются от имени пользователя, осуществляющего вход на компьютер. То есть для отключения профиля у каждого пользователя должны быть права на эту операцию. В то же время передача пользователям даже части административных функций крайне нежелательна. Поэтому для отключения профилей создадим специального пользователя (punisher), от имени которого и будем выполнять отключение, с помощью следующей функции.
Function disableUser(userDN, compDN)
Set dso = GetObject("LDAP:")
Set userObj = dso.OpenDSObject("LDAP://" & userDN, "punisher@complex.ua", "P@ssw0rd", ADS_SECURE_AUTHENTICATION + ADS_SERVER_BIND)
userObj.accountDisabled = true
userObj.description = "Unallowed access on " & compDN
userObj.SetInfo
end function
Здесь для привязки к объекту мы используем метод OpenDSObject вместо функции GetObject, поскольку он позволяет обращаться к объектам домена от имени заданного пользователя.
Пароль пользователя содержится в открытом виде, поэтому исходный код сценария целесообразно зашифровать. Кроме того, пользователю punisher нужно предоставить только необходимый набор полномочий, чтобы минимизировать потери, связанные со взломом профиля. Для нашего случая будет достаточно прав на запись ограничений объектов пользователей в рамках закрытых подразделений. И поскольку было запланировано сохранение информации о причине отключения пользователя в его свойствах, нужно разрешить еще и эту операцию. Так что, кроме отключения пользователя, функция сохраняет в его профиле информацию о причине блокировки (в виде «Несанкционированный доступ на компьютер…»).
Обладая правами, отмеченными на рис. 6, punisher сможет только задавать ограничения для других пользователей в рамках заданной части архитектуры (на рис. 6 – для подразделения «Management» и дочерних). Также целесообразно поместить пользователя punisher в специальную организационную единицу, для которой с помощью групповых политик безопасности запрещен запуск любых программ. Таким образом, используя этот профиль, нельзя будет ни воспользоваться каким-либо приложением, ни даже войти на компьютер (при входе от имени пользователя запускаются системные программы).
Рисунок 6. Разрешения, необходимые и достаточные для отключения пользователей
Тем не менее наличие учетной записи, с помощью которой можно заблокировать всех пользователей предприятия, является неприятным побочным эффектом. Да и распространение пароля по сети, пусть даже в зашифрованном виде, опасно. Поэтому функции, требующие специальных прав, возможно, стоит перенести на сервер. Рассмотрим альтернативный вариант «наказания» пользователей. При успешной аутентификации пользователя сервер получает ряд уведомлений (событий). Рассмотрим способ их обработки. Но сначала определимся, на какое событие реагировать.
События будет получать от подсистемы ведения логов (объект «Win32_NTLogEvent»). Нас интересуют события категории «Account Logon». «Полевые» испытания показали появление нескольких видов таких событий при успешной аутентификации доменного пользователя:
- 672: Authentication Ticket Granted
- 673: Service Ticket Granted
Выбор был сделан в пользу первого, поскольку оно приходило в единственном экземпляре. С объектом каждого события связан так называемый отчет: массив строк с дополнительной информацией о событии. Именно из него можно получить имя пользователя и рабочей станции, на которую производится вход. Таким образом, мы можем контролировать процедуру авторизации на сервере с помощью сценария, запущенного от имени пользователя, достаточно привилегированного для внесения изменений в профили, не распространяя его пароль. Итак, для подписки на выбранное событие нужно выполнить следующий код (должен выполняться на контроллере домена, в противном случае точку в следующей строке следует заменить именем контроллера):
set objwmiservice=getobject("winmgmts://./root/cimv2")
strwql="select * " & "from __instancecreationevent " & "where targetinstance isa 'Win32_NTLogEvent' " & "and targetinstance.EventIdentifier = 672"
set objeventsource=objwmiservice.execnotificationquery(strwql)
То есть на самом деле мы получаем уведомление о создании экземпляра объекта типа Win32_NTLogEvent. Это те самые объекты, которые можно просмотреть, используя оснастку EventViewer. Далее сценарий переходит в режим ожидания событий.
While True
set objeventobject=objeventsource.nextevent()
domain = getDomain
user = objEventobject.TargetInstance.InsertionStrings(0)
comp = getCompName(objEventobject.TargetInstance.InsertionStrings(9))
check user, comp, domain
Wend
Такой способ подписки крайне ненадежен – при завершении работы сценария (из-за ошибки в нем, например), обработка событий полностью прекратится. Существуют более надежные варианты (когда операционная система вызывает нужные подпрограммы), но они не доступны для сценариев. Так что такое решение пригодно в основном для иллюстрации способа реализации.
Свойство InsertionStrings – отчет о событии, описанный выше. Он состоит из 10 строк. Нам для дальнейшей работы требуется первая строка (нумерация начинается с 0), которая содержит имя пользователя и последняя строка с IP-адресом компьютера. Функция check выполняет всю полезную деятельность.
Но сначала рассмотрим вспомогательные функции. Во-первых, в нашем распоряжении будут только названия пользователя и компьютера. Для функции же проверки требуются их отличительные имена (DN). Для этого придется произвести поиск в модели архитектуры предприятия с помощью следующей функции:
getUserADsPath = EMPTY_STR
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Рассмотрим параметры:
- Name – это искомое имя объекта;
- className – имя класса (в нашем случае функция будет использоваться как для поиска компьютеров, так и пользователей);
- nameField – какое поле объекта считать его именем при поиске (для компьютера это «cn», а для пользователя – «SamAccountName»);
- domain – домен, в котором будем производить поиск.
Set objCOmmand.ActiveConnection = objConnection
objCommand.CommandText = "Select ADsPath from 'LDAP://" & domain & "' " & "Where objectClass='" & className & "' and " & nameField & "='" & name & "'"
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
if not objRecordSet.EOF then getObjectADsPath = objRecordSet.Fields(0).value
end function
При поиске снова воспользуемся провайдером «Active Directory Provider», поскольку он предоставляет удобную возможность использования SQL-подобного языка. Домен в данном случае играет роль контейнера, с которого начинается поиск.
function getCompName(ip)
set info = createObject("ADSystemInfo")
Set objWMIService = GetObject("winmgmts:\\.\root\MicrosoftDNS")
Set colItems = objWMIService.ExecQuery("SELECT * FROM MicrosoftDNS_AType WHERE IPAddress = '" & ip & "'")
For Each objItem in colItems
fullName = objItem.OwnerName
getCompName = left(fullName, len(fullName) - len(info.domainDNSName) - 1)
next
end function
Следующий вопрос, который необходимо решить, – получение имени компьютера на основе его IP-адреса. Для этого воспользуемся сценарием, использующим WMI. С помощью данного инструментария можно обращаться ко многим объектам операционной системы как к таблицам базы данных. На компьютере под управлением Windows 2003, исполняющей роль DNS-сервера, есть таблица MicrosoftDNS_AType, записи которой и определяют соответствие адреса и имени рабочей станции.
Следующий сценарий извлекает из таблицы имя нужного компьютера. В качестве параметра он получает IP-адрес.
function getCompName(ip)
set info = createObject("ADSystemInfo")
Set objWMIService = GetObject("winmgmts:\\.\root\MicrosoftDNS")
Set colItems = objWMIService.ExecQuery("SELECT * FROM MicrosoftDNS_AType WHERE IPAddress = '" & ip & "'")
For Each objItem in colItems
fullName = objItem.OwnerName
getCompName = left(fullName, len(fullName) - len(info.domainDNSName) - 1)
next
end function
Имя компьютера представлено в этой таблице в виде «compName.domainName», поэтому в конце функции мы отбрасываем часть строки, чтобы осталось только имя компьютера, по которому его можно будет найти в базе данных LDAP.
Поскольку сценарий проверки теперь выполняется на сервере от имени привилегированного пользователя, функция отключения профиля максимально упрощается.
Function disableUser(userPath, compPath)
Set userObj = GetObject(userPath)
userObj.accountDisabled = true
userObj.description = " Unallowed access on " & compPath
userObj.SetInfo
end function
Ну и, наконец, приведу основную функцию проверки пользователя:
function check(user, computer, domain)
set info = createObject("ADSystemInfo")
userPath = getObjectADsPath(user, "user", "SAMAccountName", domain)
if userPath = EMPTY_STR then exit function
compPath = getObjectADsPath(computer, "computer", "cn", domain)
if isAllowed(userPath, compPath) <> STATE_ALLOWED then disableUser userPath, compPath
end function
Здесь хотелось бы обратить ваше внимание на условный оператор «if userPath = EMPTY_STR then …». Дело в том, что сообщение с кодом 672, как оказалось, приходит еще в одном случае – когда включается компьютер, входящий в домен. Тогда в первой строке отчета содержится имя не пользователя, а рабочей станции. В этом случае пользователь найден не будет, и функция завершит работу.
Итак, описанный альтернативный подход позволит производить проверку доступа на рабочие станции с помощью серверного сценария. Однако такое решение стоит рассматривать как дополнение предыдущего, а не его альтернативу. Основной недостаток: невозможно гарантировать, что сообщение придет за определенное время, тем более при большой частоте операций входа на рабочие станции. События обрабатываются последовательно.
Рассмотрим особенности выполнения основных действий в серверном (постоянно работающем на сервере) и клиентском (распространяемом в рамках глобальной политики безопасности) сценариях. Операции проверки допустимости входа и отправки сообщения руководителя рассматривать не станем, так как их реализация не зависит от вида сценария.
Как уже говорилось, операция отключения пользователя из клиентского сценария выглядит достаточно опасной. Поэтому данную функцию лучше перенести на сервер. В то же время первый вариант гораздо проще и надежнее в работе, что позволяет оставить его в качестве возможной альтернативы. Завершение пользовательского сеанса целесообразно оставить в ведении клиентского сценария. Может пройти большой промежуток времени от входа злоумышленника на рабочую станцию до обработки на сервере этого события. Теоретически можно дождаться загрузки профиля и, выдернув сетевой шнур, начать спокойно работать с локальной информацией, которую мы собственно и стараемся защитить.
Перейдем к вопросу информирования глав подразделений. Рассмотрим вспомогательные функции. Следующая подпрограмма определяет руководителя заданного подразделения.
function findManager(startOU)
findManager = ""
if startOU = "" then exit function
В качестве параметра передается полное имя организационной единицы, руководителя которой нужно определить. Если имя подразделения – пустая строка, то функция завершает работу.
set ou = getObject("LDAP://" & startOU)
manDN = ou.managedBy
Далее проверяем свойство «Руководитель» текущего подразделения. Если его значение – пустая строка, то данной организационной единице не сопоставлен руководитель, и поиск продолжается вверх по дереву с помощью рекурсивного вызова этой же функции (т.е. делается попытка найти учетную запись руководителя подразделения более высокого уровня).
if manDN <> "" then
findManager = manDN
exit function
else
findManager = findManager(getParent(startOU))
end if
end function
Функция возвращает полное имя первого руководителя подходящего подразделения или пустую строку, если ни у текущей, ни у родительских организационных единиц руководители не определены.
Адрес электронной почты пользователя определяет следующая функция. В качестве параметра ей также передается полное имя объекта.
function getMail(dn)
set userObj = getObject("LDAP://" & dn)
getMail = userObj.get("mail")
end function
Чтобы отправить сообщение руководителю подразделения, на компьютер которого была попытка несанкционированного доступа, нужно выполнить следующий сценарий:
function informManager(manDN, userDN, compDN)
Функция получает три параметра: полные имена руководителя подразделения, пользователя, осуществляющего недопустимый вход, и компьютера.
Set objEmail = CreateObject("CDO.Message")
objEmail.From = getMail(userDN)
objEmail.To = getMail(manDN)
objEmail.Subject = "Unallowed login"
objEmail.Textbody = "User: " & userDN & chr(10) & "Computer: " & compDN & chr(10) & "When: " & date & " " & time
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp_server "
objEmail.Configuration.Fields.Update
objEmail.Send
end function
Затем настраиваются почтовые параметры (SMTP-сервер в данном примере функционировал на компьютере с именем «smtp_server») и формируется текст письма. Задача данной статьи – показать способы использования архитектуры предприятия для эффективной защиты объектов информационной подсистемы, поэтому основное внимание мы уделяем способу определения руководителя подразделения и его информирования. Текст же письма сделан максимально простым (содержит имя пользователя, компьютера, а также дату и время несанкционированной попытки входа в компьютер), т.к. задача составления более информативного послания может быть при необходимости легко решена. Теперь руководитель (manager@complex.ua) при попытках несанкционированного доступа будет получать письма следующего вида (см. рис. 7).
Рисунок 7. Сообщение руководителю подразделения о недопустимом входе
Остается написать результирующий сценарий, который использует все описанные в статье подпрограммы.
Set objSysInfo = CreateObject("ADSystemInfo")
userDN = objSysInfo.UserName
compDN = objSysInfo.ComputerName
Сначала определяется характеристики пользователя и компьютера.
if isAllowed(userDN, compDN) = STATE_ALLOWED then WScript.Quit
Затем вызывается функция проверки доступа. Если доступ разрешен – сценарий завершается. В противном случае принимаются карательные меры: отключается профиль, информируется руководитель, а сеанс прекращается. Если было принято решение перенести функцию отключения пользователя на серверный сценарий, следующую строку необходимо удалить.
disableUser userDN, compDN
informManager findManager(getParent(compDN)), userDN, compDN
set shellObj = CreateObject("WScript.Shell")
shellObj.exec "shutdown /l"
Установка надстройки
Приведенная программа, будучи установленной в качестве стартового сценария пользователей, позволит реализовать все требования к безопасности предприятия, сформулированные в начале статьи. При этом для ее корректной работы в будущем достаточно поддерживать актуальность модели информационно-управленческой архитектуры предприятия (используя стандартную оснастку Active Directory Users and Computers). Например, нужно назначить руководителя подразделения с помощью процедуры на рис. 4, чтобы этот пользователь начал получать уведомления по электронной почте о несанкционированных попытках захода на компьютеры своего отдела. Также, переместив компьютер из одной организационной единицы в другую, администратор автоматически сделает его доступным для сотрудников нового и запрещает доступ бывшего подразделения.
Предложенной модификацией уже можно эффективно пользоваться, однако остается неудобство установки статуса организационных единиц. Пока эту процедуру можно осуществить путем ручного запуска сценариев. Такое решение нельзя назвать приемлемым, в особенности для случаев сложных моделей информационно-управленческих архитектур. Поэтому нужно подключить сценарии к визуальным инструментам моделирования.
Создать новый пункт меню для оснастки «Active Directory Users And Computers» можно с помощью следующей функции:
function installOUMenu(id, name, scriptPath)
Set root= GetObject("LDAP://rootDSE")
sConfig = root.Get("configurationNamingContext")
sPath = "LDAP://cn=organizationalUnit-Display,cn=409,cn=DisplaySpecifiers," & sConfig
Set obj= GetObject(sPath)
sValue = id & "," & name & "," & scriptPath
vValue = Array(sValue)
obj.PutEx 3, "adminContextMenu", vValue
obj.SetInfo
end function
Ей требуется передать три параметра: номер пункта (используется для определения позиции пункта меню), название команды и путь к файлу сценария, который должен быть выполнен при выборе пункта меню.
После выполнения приведенной функции в оснастках управления объектами Active Directory для организационных единиц появится новый пункт контекстного меню, вызывающий заданный сценарий. Сначала приведем пример вывода на экран информации о дополнительных параметрах организационных единиц (тех, которые были добавлены в схему в начале статьи).
Set oArgs = WScript.Arguments
dim lock, state
Set ouObj = getObject(oArgs.item(0))
if isOULocked(ouObj) then
lock = "yes"
else
lock = "no"
end if
state = getOUState(ouObj)
msgbox "Name: " & ouObj.ou & chr(10) & "Locked: " & lock & chr(10) & "State: " & state, vbInformation, "Additional attributes"
При вызове сценария первым параметром ему передается полное имя (DN) той организационной единицы, для которой выбрана команда контекстного меню. Вся остальная функциональность программы заключается в выводе на экран нужной информации с помощью диалогового окна (см. рис. 8).
Рисунок 8. Информация о дополнительных параметрах
Для установки пункта меню нужно сохранить программу вывода информации (в нашем примере – «c:\ou_info.vbs») и один раз выполнить сценарий со следующей командой:
installOUMenu 100, "ArchitectureEx: OU Info", "c:\ou_info.vbs"
Аналогичным образом добавим сценарии для выполнения всех запланированных действий:
- ArchitectureEx: Lock Single. Блокировка одного подразделения.
- ArchitectureEx: Lock Cascade. Блокировка всех подразделений поддерева, начиная с текущего.
- ArchitectureEx: Unlock Single / Cascade. Разблокировка одного подразделения или поддерева.
- ArchitectureEx: Set Explicit State. Установка для подразделения режима разрешения доступа только для своих сотрудников.
- ArchitectureEx: Set Tree State. Установка для подразделения разрешения доступа ко всем компьютерам поддерева.
- ArchitectureEx: Set Free State. Свободный доступ к компьютерам подразделения для зарегистрированных пользователей.
Все функции модификации свойств уже определены, поэтому ограничимся примером только одного сценария выполнения команды. Рассмотрим самый сложный сценарий – каскадную блокировку отделов (все остальные сводятся к вызову одной функции). Сначала определим функцию каскадного обновления свойства «Заблокировано» подразделений.
function setSubtreeLock(startFromOU, lock)
В качестве параметров функция получает путь к корню поддерева, начиная с которого нужно заблокировать или разблокировать организационные единицы (конкретное действие зависит от второго параметра).
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Данное действие удобнее выполнить, снова воспользовавшись провайдером «Active Directory Provider». С его помощью можно выполнять запросы к модели ИУА организации, используя встроенные средства для выборки поддеревьев (для включения этого режима в программе используется константа ADS_SCOPE_SUBTREE).
Set objCOmmand.ActiveConnection = objConnection
objCommand.CommandText = _
"Select ADsPath from '" & startFromOU & "' " & "Where objectClass='organizationalUnit'"
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
После выполнения запроса мы получаем набор записей, содержащих пути ко всем организационным единицам, принадлежащих заданному поддереву. Остается только обойти эту выборку и назначить каждой единице требуемые настройки блокировки.
Do Until objRecordSet.EOF
ouPath = objRecordSet.Fields(0).value
set ouObj = getObject(ouPath)
ouObj.OULocked = lock
ouObj.setInfo
objRecordSet.MoveNext
Loop
end function
Сценарий для обработки меню будет выглядеть так:
Set oArgs = WScript.Arguments
setSubtreeLock oArgs.item(0), true
Аналогичную структуру имеют и остальные сценарии расширения: первая строка получает в качестве параметра путь к выбранной организационной единице, а вторая выполняет необходимую функцию. Ввиду однотипности полученных сценариев их исходный код приводиться не будет. После завершения настроек в оснастке «Active Directory Users And Computers» появятся дополнительные пункты меню со всеми новыми операциями. Приставка «ArchitectureEx» используется для того, чтобы отличить встроенные команды от добавленных в ходе данной работы (см. рис. 9).
Рисунок 9. Расширенное контекстное меню управления организационными единицами
Заключение
В статье приводится пример надстройки над стандартной системой управления доступом операционной системы Windows 2003 Server. Можно сделать вывод о наличии мощных встроенных средств моделирования информационно-управленческих архитектур организаций. Однако этот механизм ограниченно используется при настройке правил безопасности. Основная причина ограничений – подобные правила практически невозможно обобщить, сделав их удобными для большинства организаций. Поэтому в самой операционной системе реализован лишь общий каркас системы безопасности на основе архитектуры. Его дополняют развитые средства расширения функциональности, с помощью которых можно, приложив относительно небольшие усилия (по сравнению с разработкой подобной системы с нуля), реализовать нестандартные средства защиты объектов ИУА.
Конечно, решения на основе сценариев являются, скорее, макетом реальной надстройки. Так, даже поддержка базовых свойств потребовала создания восьми пунктов меню. Для более удобного использования их понадобится еще больше. Более логичным будет конфигурирование надстроек с помощью специальных закладок в свойствах объектов Active Directory, которые реализуются в виде библиотек, написанных на компилируемых языках (C++, Visual Basic и т. п.). Однако это относится уже к улучшению пользовательского интерфейса, основные методы реализации надстройки не изменятся (в случае же использования для создания надстройки среды Visual Basic все основные функции из этой статьи можно будет использовать без изменений).
- Рассел Ч., Кроуфорд Ш., Джеренд Д. Windows Server 2003 + SP1 и R2. Справочник администратора. – М.: Издательство «ЭКОМ», 2006. – 1424 с.
- Дженнингс Р. Admin 911. Групповые политики Windows 2000./Пер. с англ. – М.: издательство «СП ЭКОМ», 2003. – 480 с.
- Зубаков Ф. Active Directory: подход профессионала. – 2-е изд., испр. – М.: Издательско-торговый дом «Русская Редакция», 2003. – 544 с.: ил.
- Реймер С., Малкер М. Active Directory для Windows Server 2003. Справочник администратора/Пер. с англ. – М.: «СП ЭКОМ», 2004. – 512 с.
- Чекмарев А. Windows 2000 Active Directory. – СПб.: БХВ-Петербург, 2001. – 400 с.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|