Политика случайной длительности действия пароля

Что же представляет собой политика случайной длительности действия пароля? Использование политики Maximum Password Age заставляет пользователя менять свой пароль по истечении определенного количества дней. Например, если политика Maximum Password Age настроена на период в 60 дней, пользователь сможет использовать один и тот же пароль только в течение 59 дней. Например, к определенной дате пользователь А использовал свой пароль в течение 45 дней. У него осталось еще 14 дней, прежде чем пароль перестанет действовать. Длительность действия пароля устанавливается не случайным образом и равна 60 дням. Однако если Пользователь А по собственной инициативе изменит пароль после 45 дней использования, счетчик длительности действия пароля сбросится в значение «60 дней», определяемое настройками политики Maximum Password Age в домене. Таким образом, самостоятельно изменяя свой пароль, Пользователь1 превращает период действия пароля для своей учетной записи в случайную величину. Вместо того чтобы проработать 60 дней, пароль аннулируется по истечении 45 дней.

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

Теоретически вы можете реализовать политику случайной длительности действия пароля, просто сообщив всем пользователям о необходимости немедленно сменить пароль. Однако на практике простой просьбы сменить пароли недостаточно; некоторые пользователи, к сожалению, просто проигнорируют ее. Сценарий RndmPwdAge.vbs решает эту проблему, принудительно вводя политику случайной длительности действия пароля в домен. Код сценария приведен в Листинге 1.

Что делает сценарий RndmPwdAge.vbs?

В определенный день сценарий RndmPwdAge.vbs активирует параметр User Must Change Password at Next Logon для пользователей, не сменивших пароли, после того как был послан запрос. Сценарий не активирует данный параметр для особых учетных записей, в которых администратор отключил истечение срока действия пароля. Сценарий RndmPwdAge.vbs напоминает пользователям о необходимости сменить пароль за два дня и за сутки до активации параметра.

Чтобы служба поддержки не была завалена вызовами при активации данного параметра, сценарий использует различные временные интервалы в разных организационных подразделениях (OU). Например, вы можете настроить сценарий таким образом, что все учетные записи в подразделении Finance и в его подразделениях-потомках будут иметь 6-дневный миграционный период после того, как вы выпустите запрос на смену. На 4-й и 5-й дни сценарий RndmPwdAge.vbs предупредит пользователей подразделения Finance о том, что они должны сменить свои пароли в кратчайшие сроки. Если пользователь, не сменивший пароль, регистрируется в системе в течение 4 дней после окончания миграционного периода (я называю этот 4-дневный «постмиграционный» период локальным временным окном), сценарий активирует параметр «User Must Change Password at Next Logon». Если пользователь не входит в систему в течение локального временного окна, процедура перехвата, которая содержит временное окно домена для всех подразделений в домене, перехватывает следующую процедуру аутентификации в системе и активирует параметр User Must Change Password at Next Logon для пользователя. Сценарий RndmPwdAge.vbs определяет миграционный период длиной в 17 дней, по истечении которого начинает действовать временное окно домена. Временное окно действует в течение 5 дней. Использование временного окна домена – удобный способ обратиться к пользователям, которые могут быть в поездках и не входят в систему в течение локального временного окна, определенного для их организационных подразделений. Временное окно домена также позволяет работать с учетными записями, не относящимися к подразделениям, для которых определены локальные временные окна.

Авторизованный пользователь

Если сделать сценарий RndmPwdAge.vbs частью процедуры авторизации пользователей, при регистрации пользователя в системе сценарий RndmPwdAge.vbs будет работать в контексте учетной записи пользователя. Как видно из кода в блоке A Листинга 1, сценарий использует функцию CreateObject для создания объекта ADSystemInfo Active Directory Services Interfaces (ADSI), реализующего интерфейс IADsADSystemInfo, который, помимо прочего, возвращает уникальное имя (DN) пользователя. Сценарий использует функцию GetObject() и службу протокола Lightweight Directory Access Protocol (LDAP) для подключения к учетной записи пользователя в службе Active Directory (AD), которая соответствует уникальному имени пользователя.

Код в блоке B возвращает атрибуты учетной записи userAccountControl и pwdLastSet и сохраняет их значения в массиве. Сценарий RndmPwdAge.vbs использует атрибут userAccountControl, чтобы определить, ограничен ли срок действия пароля для учетной записи пользователя. Если это так, то сценарий считывает атрибут pwdLastSet, чтобы определить, когда пользователь в последний раз устанавливал пароль. Сценарий RndmPwdAge.vbs использует метод GetInfoEx, чтобы загружать только эти два атрибута, а не все существующие атрибуты учетной записи. Сценарий может функционировать и без использования метода GetInfoEx, но так как администратор вызывает этот сценарий в ходе авторизации пользователя, требуется, чтобы он выполнялся быстро. Благодаря тому, что загружаются только необходимые атрибуты, обработка проходит быстрее.

Анализ настроек пароля учетной записи пользователя

Далее сценарий RndmPwdAge.vbs определяет, отмечен ли для данной учетной записи параметр Password never expires. Хотя использование параметра Password never expires для учетной записи является рискованным с точки зрения безопасности, администраторы иногда устанавливают этот параметр для специальных учетных записей, например учетных записей служб. Обычно администратор отвечает за регулярное изменение пароля вручную. Сценарий RndmPwdAge.vbs не работает с учетными записями, настроенными подобным образом. Процедура CheckForNoExpiration, приведенная в блоке E, проверяет настройку длительности действия пароля учетной записи, анализируя флаг ADS_UF_DONT_EXPIRE_PASSWD в параметре userAccountControl. Если этот флаг включен, значит, действие пароля не имеет временных ограничений, и сценарий RndmPwdAge.vbs завершает работу.

Если параметр Password never expires не отмечен для учетной записи пользователя, сценарий вызывает функцию EvalPwdLastSet. Эта функция возвращает параметр pwdLastSet из учетной записи пользователя и использует полученное значение для выполнения следующих действий:

  1. Если параметр User Must Change Password at Next Logon уже активирован, сценарий завершает работу.
  2. Если параметр User Must Change Password at Next Logon не отмечен, определяется, как давно пользователь менял пароль. Для этого сценарий RndmPwdAge.vbs получает дату последнего изменения пароля, после чего выставляет значение функции EvalPwdLastSet в соответствии с разницей между полученной датой и текущей.

Параметр pwdLastSet учетной записи пользователя никогда не бывает пустым. Даже если бы вы создали учетную запись пользователя и сняли флаг с параметра User Must Change Password at Next Logon, служба AD прописала бы в параметр pwdLastSet дату и время снятия флага.

Я мог бы сделать сценарий RndmPwdAge.vbs чуть более простым, используя свойство PasswordLastChanged интерфейса IADsUser вместо параметров, предоставляемых основным интерфейсом IADs. В целях совместимости я использовал интерфейс IADs для получения параметров pwdLastSet и userAccountControl.

Пользователи, сменившие пароль согласно запросу

Теперь сценарий имеет дату изменения пароля для всех учетных записей, в которых снят флаг у параметра User Must Change Password at Next Logon. Следующий шаг – определить, сменил ли пользователь пароль. Вы же не хотите игнорировать добросовестность пользователя и выставлять для него флаг у параметра User Must Change Password at Next Logon? Сценарий RndmPwdAge.vbs сравнивает число дней, прошедших с момента отсылки запроса на изменение пароля, с числом дней с момента смены пользователем пароля. Если первое число больше второго, сценарий завершает работу. Иначе работа сценария продолжается.

Реализация приращения

В коде блока C функция DaysSinceChgReq возвращает количество дней, прошедших с момента отсылки пользователям запроса на изменение паролей. Если это число меньше количества дней, прошедших с момента изменения пароля пользователем, значит, вы обнаружили пользователя, который игнорировал запрос. Выражение Select Case использует функции TopContainer() и SetPwdChange() для изменения параметра User Must Change Password at Next Logon для пользователей, не изменивших свои пароли.

Функция TopContainer() определяет, является ли объект-прародитель учетной записи в свою очередь объектом-потомком домена или объектом-потомком другого организационного подразделения. Функция TopContainer() возвращает имя подразделения-прародителя, которое является прямым потомком домена. Например, если пользовательская учетная запись находится в подразделении OU2, которое является потомком подразделения OU1, а подразделение OU1 является прямым потомком домена, то функция TopContainer() вернет имя подразделения OU1. Установив миграционный период и локальное временное окно для учетных записей в подразделении OU1, вы передадите те же значения для всех учетных записей в подразделении OU2. Если вы не используете подразделения-потомки, сценарий просто возвращает название подразделения, в котором размещена учетная запись. Функция TopContainer() ограничивает количество миграционных периодов и локальных временных окон, необходимых для настройки работы в домене, содержащем множество подразделений-потомков.

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

Если значение, возвращаемое функцией DaysSinceChgReq(), больше миграционного периода, определенного параметром intGracePeriod, но при этом меньше или равно сумме миграционного периода и временного окна (intGracePeriod + intTimeWindow), при следующей авторизации сценарий заставит пользователя изменить пароль. После этого функция SetPwdChange устанавливает параметр pwdLastSet в значение 0 и передает данные об изменении в службу AD, активируя параметр User Must Change Password at Next Logon в учетной записи пользователя.

Настройка сценария

Теперь, когда мы рассмотрели принцип работы сценария, вы можете настроить его под свою среду. Спланируйте временные интервалы, которые будут использоваться при реализации политики случайной длительности действия пароля для своей сети. Например, необходимо гарантировать, что все пользователи будут менять пароли каждые 15 рабочих дней (3 недели). Определитесь с днями, в которые вы будете по почте сообщать пользователям о необходимости изменить пароли. Найдите в сценарии в коде блока D функцию DaysSinceChgReq, и измените значение переменной strDate с даты «11/15/2006» на день, в который будет разослано сообщение.

Далее, определите, какое подразделение-прародитель содержит учетные записи пользователей, пароли которых должны быть изменены. В коде блока C добавьте выражения Case для каждого подразделения-прародителя. Каждое выражение Case должно выглядеть следующим образом:

Case LCase(parent OU name)

где parent OU name - имя подразделения-прародителя. За каждым выражением Case следует вызов функции SetPwdChange. Этой подпрограмме передается два параметра. Первый параметр определяет миграционный период для отдельного подразделения, а второй параметр содержит значение локального временного окна для пользовательских учетных записей данного подразделения и его подразделений-потомков. Миграционный период – это количество дней, которое вы хотите предоставлять пользователям для смены пароля, прежде чем для их учетных записей будет активирован параметр User Must Change Password at Next Logon. Локальное временное окно – количество дней после окончания миграционного периода, в течение которых сценарий работает с соответствующим организационным подразделением и его подразделениями-потомками. Реализация локального временного окна важна, так как миграционный период, определенный для соответствующего подразделения, может включать выходные, то есть дни, когда пользователи обычно не авторизуются в системе.

В Таблице 1 перечислены настройки, используемые сценарием. 15 ноября 2006 года (как указанно в переменной StrDate функции DaysSinceChgReq) я отправил всем пользователям электронное сообщение с требованием сменить пароли. Сценарий применяет настройки из Таблицы 1 только к пользователям, не сменившим свои пароли. Пользователи в подразделении Management или его подразделениях-потомках и вошедшие в систему в воскресенье (17 ноября 2006 года) получат предупреждение о необходимости смены пароля в течение 48 часов. В понедельник (18.11.2006) не выполнившие распоряжение пользователи в этих подразделениях будут предупреждены, что они должны сменить свои пароли в течение 24 часов. В дни со вторника по четверг пользователи, не сменившие пароли, будут информированы о том, что активирован параметр User Must Change Password at Next Logon. Аналогично в таблице представлены настройки для других подразделений. Чтобы продемонстрировать гибкость сценария, в таблице приведены различные миграционные периоды и временные окна для разных учетных записей из подразделения Finance. Однако вам не обязательно задавать различные настройки для разных подразделений.

Подразделение Catch-All, последний «контейнер» из приведенных в таблице, работает с пользователями, которые не входили в систему в течение длительного времени. Данная настройка работает с пользователями по истечении 17-дневного миграционного периода и обеспечивает ожидание авторизации в течение 5 дней (доменное временное окно). Этот процесс будет применяться к большинству пользователей, не входящих в систему в рамках временных периодов, определенных для каждого подразделения. Процесс захвата применяется ко всем пользователям даже для тех, кто не входит в данное подразделение. Работа сценария не затронет пользователей, которые не будут авторизованы в системе ни в один из определенных временных периодов.

Используя логику, сходную с логикой, примененной в сценарии RndmPwdAge.vbs, вы можете использовать службы ADO и ADSI OLE DB для написания поискового сценария, создающего в результате работы множество, содержащее все учетные записи пользователей, пароли которых должны быть изменены. На основе этого множества можно использовать методы IADs Put и SetInfo для занесения значения 0 в параметр pwdLastSet и передачи данных об изменении в службу AD. Теперь при следующей регистрации в системе этим пользователям придется изменить свои пароли.

Работа со сценарием

После того как вы настроите сценарий RndmPwdAge.vbs, указав соответствующие миграционные периоды и временные окна, дату начала работы, подразделение-прародителя и отправите письмо всем пользователям, вы можете выполнить сценарий, вызвав его из сценария регистрации. Так как сценарий RndmPwdAge.vbs использует интерфейс ADSI IADsADSystemInfo, можно задействовать его только в системах Windows 2000 или более поздних клиентских системах, которые осуществляют вход в службу AD. Если вас интересует информация о том, как реализовать сценарий RndmPwdAge.vbs для более ранних клиентских систем, просмотрите сноску «Поддержка операций связывания для более ранних клиентских систем».

Чтобы убедиться, что сценарий RndmPwdAge.vbs применим только для клиентов с системами Windows 2000 и более поздними, следует вызвать сценарий из сценария регистрации в системе, запущенного из объекта Group Policy Object (GPO) на уровне домена. Из объекта GPO уровня домена перейдите в папку User ConfigurationWindows SettingsScriptsLogon и добавьте файл RndmPwdAge.vbs в список сценариев обрабатываемых при входе в систему. Если у вас уже есть инфраструктура обработки входного сценария, вы можете вызвать сценарий из другого файла сценария входа в систему. Так как лишь клиентские системы Windows 2000 и выше могут обрабатывать объекты GPO, настройка, в ходе которой сценарий запускается из объекта GPO, позволяет не волноваться о несовместимости сценария при работе с более ранними клиентскими системами.

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


Поддержка операций связывания для более ранних клиентских систем

Интерфейс IADsADSystemInfo недоступен в клиентских системах Windows, вышедших до появления системы Windows 2000 (то есть в системах Windows NT, Windows Me и Windows 9x). Если в этих клиентских системах установлена служба Windows Script Host (WSH) 2.0 или ее более поздняя версия (рекомендуется служба WSH 5.6), а также расширение клиентской системы для работы со службой Active Directory (AD), и при этом клиентские системы авторизуются в домене службы AD, вы можете модифицировать сценарий RndmPwdAge.vbs для работы с такими клиентами. Для модификации сценария RndmPwdAge.vbs замените строки кода в блоке A Листинга 1 содержанием файла DownLevelBind.vbs, показанным в Листинге A. Код файла DownLevelBind.vbs жестко кодирует «контейнер» Users для этих клиентов, но при этом позволяет указать миграционный период и временное окно для проверки учетных записей пользователей в данном «контейнере». После тестирования можно вызвать сценарий из ресурса NetLogon или добавить его в существующую инфраструктуру обработки сценариев входа в систему, которая не использует обработку на основе политики Group Policy. Старые клиентские системы не поддерживают такую обработку.

Вы можете загрузить расширения системы NT Workstation 4.0 для работы со службой AD с http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/ntwrkstn/downloads/utils/dsclient.asp. Расширения для систем Windows Me и Win9x доступны в папке Clients на установочном диске системы Windows 2000 Server. Загрузить службу WSH 5.6 для систем Windows 2000, NT 4.0, Windows Me и Win98 можно с http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/001/733/msdncompositedoc.xml&frame=true. Имейте в виду, что клиентские системы Windows 2000 и выше могут работать со службой AD, а клиентские системы Windows XP содержат службу WSH 5.6.


Таблица 1: Настройки миграционных периодов и временных окон
КонтейнерМиграционный период (в днях)Дата начала работыВременное окно (в днях)Дата завершения работы
Management419/11/2006 (Втор)221/11/2006 (Четв)
Finance621/11/2006 (Четв)425/11/2006 (Пон)
Accounting 1025/11/2006 (Пон)227/11/2006 (Среда)
Human Resources1227/11/2006 (Среда)229/11/2006 (Пятн)
Catch-All172/12/2006 (Пон)56/12/2006 (Пятн)

ЛИСТИНГ 1: RndmPwdAge.vbs
Const ADS_UF_DONT_EXPIRE_PASSWD = &h10000
Const ONE_HUNDRED_NANOSECOND = .000000100
Const SECONDS_IN_DAY = 86400
 
# BEGIN CALLOUT A
Set objADSystemInfo = CreateObject("ADSystemInfo")
Set objUser = GetObject("LDAP://" & objADSystemInfo.UserName)
Set objADSystemInfo = Nothing
# END CALLOUT A
 
# BEGIN CALLOUT B
arrAttributes = Array("userAccountControl", "pwdLastSet")
objUser.GetInfoEx arrAttributes, 0
# END CALLOUT B
 
blnNoExpiration = CheckForNoExpiration
If blnNoExpiration = True Then WScript.Quit
 
If EvalPwdLastSet = "Enabled" Then
 WScript.Quit
Else
 If SetPwdChange = "TwoDays" Or SetPwdChange = "OneDay" Then
  WScript.Quit
 Else
# BEGIN CALLOUT C
  If DaysSinceChgReq < intEvalPwdLastSet Then
   Select Case lCase(TopContainer())
    Case lCase("Management")
     SetPwdChange(4,2)
    Case lCase("Finance")
     SetPwdChange(6,4)
    Case lCase("Accounting")
     SetPwdChange(10,2)
    Case lCase("HR")
     SetPwdChange(12,2)
   End Select
   SetPwdChange(17,5)
  Else
   WScript.Quit
  End If  
# END CALLOUT C
 End If
End If
 
# BEGIN CALLOUT D
BEGIN COMMENT LINE
' FUNCTION: DaysSinceChgReq
END COMMENT LINE
Function DaysSinceChgReq()
 strDate = "11/15/2006"
 dtChangeRequest = strDate
 DaysSinceChgReq = _
 DateDiff("d", dtChangeRequest, DateValue(Now))
End Function
# END CALLOUT D
 
# BEGIN CALLOUT E
BEGIN COMMENT LINE
' FUNCTION: CheckForNoExpiration
END COMMENT LINE
Function CheckForNoExpiration
 intUserAccountControl = objUser.Get("userAccountControl")
 If intUserAccountControl And ADS_UF_DONT_EXPIRE_PASSWD Then
  CheckForNoExpiration = True
 Else
  CheckForNoExpiration = False
 End If
End Function
# END CALLOUT E

ЛИСТИНГ A: DownLevelBind.vbs
Set objRootDSE = GetObject("LDAP://rootDSE")
strADsPath = _
 "LDAP://cn=" & GetUserName & _
   ",cn=Users," & objRootDSE.Get("defaultNamingContext")
Set objUser = GetObject(strADsPath)
 
BEGIN COMMENT LINE
'  FUNCTION: GetUserName
END COMMENT LINE
Function GetUserName
  Set objNetwork = CreateObject("WScript.Network")
  Do While objNetwork.Username = ""
    WScript.Sleep 50
  Loop
  GetUserName = objNetwork.UserName
End Function