Управляем доступом к ресурсам домена на основе Windows Server::Журнал СА 9.2009
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Наука и технологии
Подписка
Где купить
Авторам
Рекламодателям
Архив номеров
Контакты
   

  Опросы
  Статьи

Электронный документооборот  

5 способов повысить безопасность электронной подписи

Область применения технологий электронной подписи с каждым годом расширяется. Все больше задач

 Читать далее...

Рынок труда  

Системные администраторы по-прежнему востребованы и незаменимы

Системные администраторы, практически, есть везде. Порой их не видно и не слышно,

 Читать далее...

Учебные центры  

Карьерные мечты нужно воплощать! А мы поможем

Школа Bell Integrator открывает свои двери для всех, кто хочет освоить перспективную

 Читать далее...

Гость номера  

Дмитрий Галов: «Нельзя сказать, что люди становятся доверчивее, скорее эволюционирует ландшафт киберугроз»

Использование мобильных устройств растет. А вместе с ними быстро растет количество мобильных

 Читать далее...

Прошу слова  

Твердая рука в бархатной перчатке: принципы soft skills

Лауреат Нобелевской премии, специалист по рынку труда, профессор Лондонской школы экономики Кристофер

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 9928
Комментарии: 0
Потоковая обработка данных

 Читать далее...

19.03.2018г.
Просмотров: 8137
Комментарии: 0
Релевантный поиск с использованием Elasticsearch и Solr

 Читать далее...

19.03.2018г.
Просмотров: 8244
Комментарии: 0
Конкурентное программирование на SCALA

 Читать далее...

19.03.2018г.
Просмотров: 5221
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 5905
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

Друзья сайта  

 Управляем доступом к ресурсам домена на основе Windows Server

Архив номеров / 2009 / Выпуск №9 (82) / Управляем доступом к ресурсам домена на основе Windows Server

Рубрика: Администрирование /  Администрирование

ВАДИМ АНДРОСОВ, ассистент ВНУ, специалист MCP. Занимается анализом архитектур организаций с защищаемыми бизнес-процессами

Управляем доступом
к ресурсам домена на основе Windows Server

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

Общее описание концепции

Сегодня я хотел бы показать реализацию не вполне обычного подхода к управлению доступом к файловым ресурсам домена на основе Windows Server. Обычно администратор разрешает или запрещает операции с файлами и папками, используя объекты пользователей и групп. Это стандартный подход, который прекрасно себя зарекомендовал. Однако иногда права удобно предоставить рабочей станции.

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

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

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

Интересно, что у администратора есть возможность с помощью штатных средств запретить доступ для объекта компьютера к определенному ресурсу (см. рис. 1).

Рисунок 1. Запрет всех операций для рабочей станцииРисунок 1. Запрет всех операций для рабочей станции

Рисунок 1. Запрет всех операций для рабочей станции

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

Здесь будет рассмотрена простейшая работоспособная реализация механизма распределения прав доступа к ресурсам домена, когда полномочия предоставляются не пользователю или группе, а рабочей станции. Для расширения функциональности решения придется модифицировать схему AD, добавлять новую функциональность в оснастки оснасток, как это делалось в [1-3]. Однако мне хотелось бы показать саму суть подхода, не загромождая его посторонними деталями, которые к тому же были подробно рассмотрены ранее. Предлагаемое решение вполне применимо в реальных ситуациях. Не стоит забывать, что чем проще, тем надежнее.

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

Сделать прикрепление группы к рабочей станции можно разными способами. Наиболее универсальный – с помощью создания специального свойства класса (этот подход использовался, например, в [2]). Однако сегодня я остановлюсь на связывании на основе имени объекта. Прикрепленная группа будет называться <<имя_компьютера>>_cg (сокращение от Computer Group). Храниться эти группы будут в том же контейнере Active Directory, что и компьютеры. Как будет видно в дальнейшем, реализация позволяет хранить привязанные группы в дочернем контейнере по отношению к тому, в котором находится компьютер. Правила именования соблюдать все равно нужно, поскольку это единственный механизм связывания объектов в предлагаемом решении. Итак, все, что нужно сделать, это обработать событие входа пользователя на компьютер, удалить его из прошлой группы, если он в какую-либо входил, и добавить в новую.

Реализация

Приступим. В [1] я описывал обработку события входа пользователя на рабочую станцию, отслеживая процесс появления экземпляров класса Win32_NTLogEvent. Что они собой представляют, вы можете увидеть, открыв оснастку Event Viewer (см. рис. 2).

Рисунок 2. Оснастка Event Viewer

Рисунок 2. Оснастка Event Viewer

Событий происходит огромное количество, нас же интересует лишь одно с кодом 672 и названием Authentication Ticket Granted. Это и есть аутентификация нового пользователя. Установим обработчик события. Этот процесс описан в [2, 3], поэтому ограничусь лишь кратким описанием.

Нужно создать экземпляры трех классов. Сначала подключаемся к пространству имен, где расположен класс Win32_NTLogEvent. Это root\CIMv2.

Set objSWbemServices = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\CIMv2")

Затем создаем первый класс обработчика. Это фильтр событий. С его помощью система получает информацию, что мы хотим обрабатывать. Интересующее нас событие описывается с помощью запроса на языке WQL (WMI Query Language, является упрощенной версией SQL). Здесь используется запрос вида:

select * from __instanceCreationevent where targetinstance isa 'Win32_NTLogEvent' and targetinstance.EventIdentifier = 672

Так мы сообщаем системе, что собираемся обрабатывать события создания экземпляра (__instance Creationevent) класса Win32_NTLogEvent. Причем интересны не все объекты (которых создается довольно большое количество), а лишь те, идентификатор (EventIdentifier) которых 672. В листинге 1 создается объект класса фильтр событий (__EventFilter), инициализируются его поля (имя объекта, язык запроса, текст запроса и пространство имен). Затем с помощью метода Put_ класс помещается в постоянное хранилище.

Листинг 1. Создание фильтра событий

Set eventFilterClass = objSWbemServices.Get("__EventFilter")

set userFilter = eventFilterClass.SpawnInstance_()

userFilter.Name = "SecureCompFilter"

userFilter.QueryLanguage = "WQL"

userFilter.Query = "select * from __instancecreationevent " & /

    "where targetinstance isa 'Win32_NTLogEvent' " & "and targetinstance.EventIdentifier = 672"

userFilter.EventNamespace = "root\CIMv2"

userFilter.Put_()

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

mofcomp %SYSTEMROOT%\system32\wbem\scrcons.mof

После этого переходим к созданию объектов класса:

Листинг 2. Создание объекта реакции на событие

Set consumerClass = objSWbemServices.Get("ActiveScriptEventConsumer")

set userConsumer = consumerClass.SpawnInstance_()

userConsumer.Name = "RunSecureCompScript"

userConsumer.ScriptText = "createObject("& chr(34) & "SecureComputer.EventHandler" & /

    chr(34) & ").handle(targetEvent.targetInstance)"

userConsumer.ScriptingEngine = "VBScript"

userConsumer.Put_()

В качестве исполняемого сценария передается строчка:

createObject(SecureComputer.EventHandler).handle(targetEvent.targetInstance)

Здесь создается объект класса SecureComputer.Event Handler, и сразу же вызывается его метод handle, в качестве параметра которому передается объект типа Win32_NTLogEvent, вызвавший событие.

Листинг 3. Объект для связи фильтра события с его обработчиком

Set bindingClass = objSWbemServices.Get("__FilterToConsumerBinding")

set userBinder = bindingClass.SpawnInstance_()

userBinder.Filter = "__EventFilter.Name=" & chr(34) & "SecureCompFilter" & chr(34)

  userBinder.Consumer = "ActiveScriptEventConsumer.Name=" & chr(34) & "RunSecureCompScript" & chr(34)

userBinder.Put_()

Как только последний объект помещается в хранилище (см. листинг 3), события начинают обрабатываться. Причем проделывается эта операция один раз. При перезагрузках системы ничего не отключается. Если же все-таки нужно отменить обработку, для этого нужно выполнить сценарий из листинга 4. В нем находятся объекты, созданные в листингах 1-3, и удаляются из хранилища.

Листинг 4. Отключение прослушивания событий

Set objWIMService = GetObject("winmgmts:\\.\root\CIMv2")

Set objList = objWIMService.ExecQuery("references of {__EventFilter.Name='SecureCompFilter'}")

For each objInst in objList

  objInst.Delete_

Next

Set obj = GetObject("winmgmts:\\.\root\CIMv2:" & "ActiveScriptEventConsumer='RunSecureCompScript'")

obj.Delete_

Set obj = GetObject("winmgmts:\\.\root\CIMv2:" & "__EventFilter='SecureCompFilter'")

obj.Delete_

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

Используя WSC (Windows Script Component), мы можем свободно перемещать файл, заново регистрируя его в системе. На способе его использования это не отразится. Создание классов подробно рассматривалось в [3], поэтому здесь ограничимся поверхностным описанием.

Это обычный текстовый файл с расширением wsc, в котором в нашем случае будет содержаться следующий код:

Листинг 5. Заготовка класса SecureComputer.EventHandler

<?xml version="1.0"?>

<component>

<registration

    description="SecureComputer.EventHandler"

    progid="SecureComputer.EventHandler"

    version="1.00"

    classid=

      "{5599b415-12e5-4d68-bee5-0746988c4140}"

>

</registration>

<public>

    <method name="handle">

           <PARAMETER name="eventInstance"/>

    </method>

</public>

<script language="VBScript">

<![CDATA[

Const ADS_SCOPE_SUBTREE = 2

function handle(eventInstance)

    bindUserComp _

      eventInstance.InsertionStrings(9), _

      eventInstance.InsertionStrings(0)

end function

Function bindUserComp(ip, userName)

‘…

End Function

]]>

</script>

</component>

Это XML-документ. В разделе registration содержится информация, необходимая для регистрации компонента (класса) в системе: название (progid), описание, версия, идентификатор. Лучше создавать заготовку класса с помощью специальных утилит (например, Windows Script Component Wizard), которые сами генерируют корректный уникальный идентификатор (classid).

Раздел public содержит открытые методы класса, т.е. те, которыми могут пользоваться внешние программы. В нашем случае это единственный метод handle, который и вызывается в обработчике события. В качестве параметра ему передается объект события.

Дальше идет реализация метода. Метод handle достаточно прост – он сводится к вызову подпрограммы bindUserComp, которая и делает всю необходимую работу. У объекта события есть свойство InsertionStrings, которое представляет собой массив строк отчета. В строке с индексом 0 содержится имя пользователя (samAccountName), с индексом 9 – IP‑адрес компьютера, с которого осуществляется вход. Остальная информация для этой задачи несущественна.

Рассмотрим подробно функцию прикрепления пользователя к компьютеру. Фактически она заносит объект user в группу безопасности, соответствующую определенной рабочей станции, и удаляет его из предыдущей, если он в таковой находится. Если прикрепленной группы не существует – ничего не происходит. Таким образом, нет необходимости создавать отдельные группы для каждого компьютера – только для тех, для которых это действительно нужно.

Function bindUserComp(ip, userName)

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

if ip = "127.0.0.1" then exit function

 Далее создаются необходимые объекты.

ADSystemInfo. Информация о системе. С его помощью получим название нашего домена.

ADODB.Connection. Имени пользователя и IP-адреса компьютера недостаточно, требуется привязаться к соответствующим объектам Active Directory. Для поиска удобно использовать Active Directory Provider, который позволяет делать запросы к службе каталогов, используя SQL-подобный язык. Объект соединения инициализируется для работы именно с этим средством.

ADODB.Command. Представляет собой запрос. Инициализируется текстом запроса и областью поиска. Здесь поиск производится в поддереве, начиная с заданного корневого элемента, для этого используется константа ADS_SCOPE_SUBTREE. Ее нужно определить выше или просто использовать цифру 2.

RootDSE. Заранее неизвестно, какой организационной единице принадлежит пользователь, поэтому искать нужно, начиная с общего корневого элемента. В Active Directory он называется так:

set info = createObject("ADSystemInfo")

Set objConnection = CreateObject("ADODB.Connection")

Set objCommand = CreateObject("ADODB.Command")

objConnection.Provider = "ADsDSOObject"

objConnection.Open "Active Directory Provider"

Set objCOmmand.ActiveConnection = objConnection

objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE

Set rootDSE = GetObject("LDAP://RootDSE")

Вспомогательные объекты созданы, переходим к непосредственной работе. Сначала нужно отыскать объект пользователя по известному имени. Для этого используется запрос поиска объектов класса user, со свойством samAccountName, равным искомому. Если по каким-то причинам пользователь не найден (свойство EOF команды истинно), функция завершает работу. В рамках домена свойство samAccountName уникально (в отличие от cn (Common Name), которое у разных учетных записей может совпадать), поэтому в результате будет получена только одна запись, к которой программа и переходит посредством вызова метода MoveFirst результата запроса.

Выбирается свойство ADSPath (полный путь к объекту), на основе которого сразу же выполняется непосредственное подключение с помощью метода getObject. После этого объект user для манипуляций готов. После ключевого слова select указывается контейнер, с которого нужно начать поиск. В нашем случае это корневой элемент Active Directory.

objCommand.CommandText = "Select ADsPath from 'LDAP://" & rootDSE.Get("defaultNamingContext") & /

    "' " & "Where objectClass='user' and " & "samAccountName ='" & userName & "'"

Set objRecordSet = objCommand.Execute

if objRecordSet.EOF then exit function

objRecordSet.MoveFirst

Set user = getObject(objRecordSet.Fields(0).value)

Дальше нужно найти компьютер. Здесь используется другой подход, потому что IP-адрес не является свойством объекта computer. Адрес нужно сначала разрешить (resolve), обратившись к DNS-серверу. Для этого существует специальный объект WMI MicrosoftDNS_AType, который находится в пространстве имен root\MicrosoftDNS. Здесь также поддерживается SQL-подобный язык запросов (тот самый WQL, который использовался для подписки на события).

В таблице IP-адрес может встречаться несколько раз, поэтому уточним, что искать нужно только для текущего домена (info.domainDNSName). В поле OwnerName результата будет содержаться доменное имя компьютера в виде computer.domain. Оно уникально для каждой рабочей станции, поэтому, зная его, можно искать объект в AD.

Обратите внимание на дополнительную проверку при анализе результатов выборки. Дело в том, что существует DNS-запись для самого домена, которая соответствует адресу одного из контроллеров, ее нужно проигнорировать.

Set objWMIService = GetObject("winmgmts:\\.\root\MicrosoftDNS")

Set colItems = objWMIService.ExecQuery("SELECT * FROM MicrosoftDNS_AType " & "WHERE IPAddress = '" & ip & /

    "' and domainName = '" & info.domainDNSName & "'")

For Each objItem in colItems

  if objItem.OwnerName <> info.domainDNSName then DNSHostName = objItem.OwnerName

next

Теперь, зная имя компьютера, ищем его в каталоге так же, как искали пользователя. Класс объекта теперь выставляем computer, а поле, по которому осуществляется поиск, – DNSHostName.

objCommand.CommandText = "Select ADsPath from 'LDAP://" & rootDSE.Get("defaultNamingContext") & "' " & /

    "Where objectClass='computer' and " & "DNSHostName ='" & DNSHostName & "'"

Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst

Set computer = getObject(objRecordSet.Fields(0).value)

Остается найти группу, привязанную к компьютеру. Используем нашу договоренность об именовании – группа должна называться так же, как рабочая станция, с суффиксом _cg и находиться в той же организационной единице (или дочерней, поскольку область поиска запросов – поддерево).

Такой группы может и не быть. Поэтому после выполнения запроса проверяем свойство EOF, результирующей выборки (objRecordSet).

group = null

objCommand.CommandText = "select ADSPath from '" & computer.parent & "' /

    where objectClass = 'group' and cn = '" & computer.cn & "_cg'"

Set objRecordSet = objCommand.Execute

if not objRecordSet.EOF then

  objRecordSet.MoveFirst

  set group = getObject(objRecordSet.Fields(0).value)

end if

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

if not isNull(group) then

  if group.isMember(user.ADSPath) then exit function

end if

Затем вне зависимости от того, была найдена присоединенная группа или нет, требуется удалить пользователя из всех групп других рабочих станций. Здесь он удаляется из групп, имя которых оканчивается на _cg.

for each ug in user.groups

  if len(ug.cn)>3 then

    if right(ug.cn,3) = "_cg" then

      ug.remove user.ADSPath

    end if

  end if

next

Если группа была найдена, пользователь в нее добавляется.

if not isNull(group) then group.add(user.ADSPath)

End Function

Испытания

Посмотрим теперь, как это работает. Сначала нужно зарегистрировать наш класс в системе (с помощью контекстного меню) и установить прослушивание событий. Все готово к работе. Никаких особых инструментов мы не добавляли. Все что требуется – это оснастка Active Directory Users and Computers и стандартные средства системы управления правами доступа операционной системы.

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

Рисунок 3. Объекты для тестирования

Рисунок 3. Объекты для тестирования

Затем создадим открытую папку, с содержимым которой запретим работать с компьютера insecure (см. рис. 4).

Рисунок 4. Запрет работы с ресурсом для группы insecure_cg

Рисунок 4. Запрет работы с ресурсом для группы insecure_cg

Все. Теперь если пользователь, наделенный достаточными правами, обратится к папке с рабочей станции secure, никаких проблем не будет. Если тот же пользователь зайдет с insecure, то доступа уже не получит (см. рис. 5).

Рисунок 5. Запрет на использование ресурса

Рисунок 5. Запрет на использование ресурса

Более того, поскольку отслеживается процесс аутентификации пользователя, то корректно будут обрабатываться и случаи вторичного входа в систему (см. рис. 6). В группе, привязанной к рабочей станции, будет содержаться несколько пользователей.

Рисунок 6. Вторичный вход в систему

Рисунок 6. Вторичный вход в систему

Вам было представлено простое и удобное в использовании решение, которое позволит предоставлять права к ресурсам пользователям в зависимости от рабочей станции, на которой они находятся. Никаких дополнительных элементов и модификаций схемы Active Directory не требуется, поскольку используется лишь соглашение об именах. Отключать расширение нет необходимости – если нет групп, привязанных к компьютерам, ничего происходить не будет.

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

  1. Андросов В. Реализуем нестандартные правила управления доступом на основе архитектуры организации в Windows Server 2003. //Системный администратор, №10, 2007 г. – С. 48-58.
  2. Андросов В. Синхронизация ACL и структуры организации. Часть 1. //Системный администратор, №12, 2007 г. – С. 36-41; часть 2. №1, 2008 г. – С. 56-61; часть 3. №2, 2008 г. – С. 82-87.
  3. Андросов В. Делегируем права на перемещение учетных записей пользователей в Active Directory. Часть 1. Постановка задачи. //Системный администратор, №3, 2009 г. – С. 16-21.
  4. Андросов В. Делегируем права на перемещение учетных записей пользователей в Active Directory. Часть 2. Реализация основных функций. //Системный администратор, №4, 2009 г. – С. 24-30.
  5. Андросов В. Делегируем права на перемещение учетных записей пользователей в Active Directory. Часть 3. Реализуем необходимые операции. //Системный администратор, №5, 2009 г. – С. 3037.
  6. Андросов В. Делегируем права на перемещение учетных записей пользователей в Active Directory. Часть 4. Завершение надстройки. //Системный администратор, №6, 2009 г. – С. 40-47.
  7. Андросов В. Проводим реализацию тонкого делегирования прав в Active Directory. //Системный администратор, №7, 2009 г. – С. 32-38.

Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-41
Fax: (499) 277-12-45
E-mail: sa@samag.ru