Pwdlastset что это за атрибут
sergey vasin
The IT blog
Получение значения атрибута pwdLastSet объекта пользователя при запросе к Active Directory с использованием LDAP
Скажем сразу — все, что здесь описано касается также и остальных атрибутов, содержащих значение даты и времени. Тем не менее в этой статье мы будем говорить об атрибуте pwdLastSet, а применить описанные подходы к другим атрибутам вы сможете и сами.
Когда для запросов к Active Directory мы используем командлеты одноименного модуля, то результаты их выполнения не требуют от нас каких-либо дополнительынх действий. Однако, если по каким-то причинам решили использовать LDAP, здесь все немного сложнее.
DirectorySearcher
Начнем с варианта с использованием объекта DirectorySearcher.
Создать его мы можем несколькими способами.
Один из них — это использование акселератора [adsisearcher] и указания нужной нам строки фильтра. Например, так:
Либо же мы можем воспользоваться командлетом New-Object для создания объекта DirectorySearcher и уже затем определить значения тех его свойств, которые нам понадобятся. К ним же относится и свойство Filter.
Вне зависимости от метода создания объекта DirectorySearcher, выполнить поиск в Active Directory мы можем при помощи методов FindOne и FindAll. Предположим, что в нашем случае существует только один пользователь, UPN которого начинается с someuser.
Теперь, если мы обратимся к значению атрибута pwdLastSet, мы получим что-то вроде:
Что это означает? Как известно, значение атрибута pwdLastSet отражает момент времени, когда пользователь последний раз изменял пароль. Но представлено это значение в виде количества интервалов длиной 100 наносекунд, исчисляемого с 1 января 1601 (UTC).
Для того, чтобы перевести это значение в более привычный нам формат, мы можем воспользоваться статическим методом FromFileTime класса System.DateTime.
С другой стороны, если мы захотим перевести объект типа System.DateTime в вышеупомянутый формат, мы можем воспользоваться методом ToFileTime самого объекта DateTime. Например:
Теперь давайте предположим, что нам известно значение DistinguishedName пользователя и мы хотим запросить объект напрямую, без использования DirectorySearcher. Сделаем мы это так:
Теперь, обратившись к атрибуту pwdLastSet, мы получим еще более любопытный результат:
Таким образом отображается значение атрибута в формате large integer, в котором оно, собственно, и хранится в Active Directory.
И уже теперь, так же как и в прошлый раз, мы можем перевести полученное значение в формат DateTime:
Когда истекает пароль пользователя в AD, оповещаем пользователей о необходимости сменить пароль
В этой статье мы покажем, как с помощью PowerShell узнать, когда истекает пароль учетной записи пользователя в Active Directory, установить бессрочный пароль для учетной записи (PasswordNeverExpires = True) и заблаговременно оповестить пользователей о необходимости сменить пароль.
Если срок действия пароля пользователя в домене истек, учетная запись не блокируется, но не может использоваться для доступа к доменным ресурсам до тех пор, пока пользователь не сменит свой истекший пароль на новый. Чаще всего проблемы с истекшими паролями возникает у удаленных пользователей, которые не могут сменить свой пароль стандартными средствами.
Текущие настройки политики срока действия паролей в домене можно получить с помощью команды PowerShell
В нашем примере максимальный срок действия пароля пользователя в домене – 60 дней.
Как узнать срок действия пароля пользователя в Active Directory?
Можно узнать срок действия пароля и дату его последней смены из командной строки с помощь команды Net user:
net user aaivanov /domain
Необходимые данные присутствуют в значениях:
Для получения параметров учетных записей в AD мы будем использовать специальный модуль PowerShell для Active Directory, который позволяет получить значения различных атрибутов объектов AD (см. как установить и импортировать модуль AD PowerShell в Windows 10 и Windows Server 2012 R2/2016).
С помощью командлета Get-AdUser можно получить время последней смены пароля пользователя и проверить, установлена ли опция бессрочного пароля (PasswordNeverExpires):
Но как вы видите, в оснастке указана только время смены пароля. Когда истекает срок действия пароля — непонятно.
Чтобы получить не время последней смены пароля, а дату окончания его срока действия, нужно использовать специальный constructed-атрибут msDS-UserPasswordExpiryTimeComputed. Значение атрибута msDS-UserPasswordExpiryTimeComputed автоматически вычисляется на основании времени последней смены пароля и парольной политики домена
Параметр UserPasswordExpiryTimeComputed возвращает время в формате TimeStamp и для преобразования его в человеко-понятный вид я использую функцию FromFileTime:
Таким образом мы получили время истечения срока действия пароля пользователя.
Чтобы получить срок действия паролей для всех пользователей их определенного контейнера (OU) AD, можно воспользоваться таким скриптом PowerShell:
В результате появилась табличка со списком активных пользователей, сроком действия и временем последней смены пароля.
Можно вывести только список пользователей, чей пароль уже истек:
Отключить срок действия пароля для учетной записи
Если вам нужно сделать срок действия пароля определенной учетной записи неограниченным, нужно включить опцию Password Never Expires в свойствах пользователя в AD (это одно из битовых значений атрибута UserAccountControl).
Либо вы можете включить эту опцию через PowerShell:
Можно установить флаг Password Never Expires сразу для нескольких пользователей, список которых содержится в текстовом файле:
Можно вывести список всех пользователей, для которых отключено требование регулярной смены пароля:
Политика оповещения об окончании срока действия пароля
В Windows есть отдельный параметр групповой политики, позволяющий оповещать пользователей о необходимости сменить пароль.
По умолчанию эту политика включена на уровне локальных настроек Windows и уведомления начинают появляться за 5 дней до истечения срока действия пароля. Вы можете изменить количество дней, в течении которых должно появляться уведомление о смене пароля.
После включения этой политики, если пароль пользователя истекает, то при входе в систему в трее будет появляться уведомление о необходимости сменить пароль.
Также вы можете использовать простой PowerShel скрипт, который автоматически вызывает диалоговое окно со предложением сменить пароль, если он истекает менее чем через 5 дней:
Если пользователь нажимает ДА, появляется диалоговое окно Windows Security, которое вы видите при нажатии Ctrl+Alt+Del или Ctrl+Alt+End (при RDP подключении).
Данный скрипт нужно поместить в автозагрузку или запускать как logon скрипт групповых политик.
PowerShell скрипт для email-уведомления об истечении срока действия пароля
Если вы хотите индивидуально рассылать пользователям письма о том, что срок действия их паролей скоро истечет, можно использовать такой PowerShell скрипт.
Скрипт проверяет всех активных пользователей домена с истекающими паролями. За 7 дней до истечения пароля пользователю начинают отправляться письма на email адрес, указанный в AD. Письма отправляются до тех пор, пока пароль не будет изменен или просрочен.
Данный PowerShell скрипт нужно запускать регулярно на любом компьютере/сервере домена (проще всего через Task Scheduler). Естественно, нужно на вашем SMTP сервере добавить IP адрес хоста, с которого рассылаются письма, в разрешенные отправители без аутентификации.
LDAP-фильтры для поиска объектов в Active Directory. Часть 3
Продолжаем тему LDAP-фильтров. В третьей, завершаюшей статье рассмотрим некоторые инструменты для работы с фильтрами, а также примеры наиболее часто используемых фильтров. Начнем как всегда с
PowerShell
У командлетов Get-ADUser, Get-ADComputer, Get-ADGroup и Get-ADObject имеется параметр LdapFilter, специально предназначенный для использования LDAP-фильтров при поиске объектов в Active Directory. Для примера найдем всех пользователей с именем Vasya с помощью такой команды:
Большинство командлетов для поиска являются узкоспециализированными, т.е. предназначены только для определенного типа объектов (пользователи, компьютеры и т.п.). Исключение составляет командлет Get-ADObject, который может искать любые объекты. Например:
При использовании Get-ADObject мы получили не только пользователей, а все объекты с указанным в фильтре именем. Если требуется найти только пользователей, то надо в фильтре добавлять дополнительные параметры. Например:
При помощи LDAP-фильтра нельзя указать область поиска. Для примера найдем всех пользователей, у которых в описании (Description) имеется слово Руководитель:
Эта команда произведет поиск по всему домену и выдаст всех найденных пользователей, вне зависимости от их местоположения.
Для уточнения области поиска есть параметр SearchBase, с помощью которого можно указать для поиска конкретное подразделение (OU), например:
Еще один полезный параметр Subtree, с помощью которого можно ограничить глубину поиска. Этот параметр может принимать 3 значения:
• Base (0) — поиск только по указанному в запросе объекту. В результате поиска возвращается либо один объект, либо ничего. Данная область, как правило, используется для проверки наличия объекта.
• One level (1) — поиск только по дочерним объектам указанного объекта. Поиск по вложенным объектам не производится, также в результаты поиск не попадает сам базовый объект.
• Subtree (2) — поиск по всем дочерним объектам, включая вложенные. Сам базовый объект в поиск не попадает. Это значение используется по умолчанию.
Для примера возьмем предыдущую команду и ограничим поиск верхним уровнем (OneLevel):
А затем зададим поиск по всем вложенным объектам (Subtree):
Как видите, разница очевидна.
Для работы с Active Directory из командной строки существует великое множество различных утилит. Мы рассмотрим две наиболее часто используемые для поиска — dsquery и dsget.
Утилита dsquery возвращает различающееся имя (Distinquished Name) объекта, подходящего под заданные параметры, а для LDAP-фильтров у нее имеется параметр filter. К примеру, предыдущий запрос с использованием dsquery будет выглядеть так:
Утилита dsget получает на входе различающееся имя объекта и выдает для него значение указанного атрибута или атрибутов. Зачастую обе эти утилиты используются совместно, например:
ADSIEdit
Переходим к графическим утилитам. Оснастка ADSIEdit поддерживает использование LDAP-фильтров. Для добавления фильтра надо кликнуть по выбраному контексту именования (NC) и в контекстном меню выбрать пункт New — Query…
В открывшемся окне указываем имя запроса, выбираем область поиска (Root of Search) и в поле Query String добавляем нужный фильтр. Для примера отберем всех отключенных пользователей. Дополнительно можно выбрать глубину поиска Subtree или One level.
В результате получим что то вроде этого.
Active Directory Users and Computers
В оснастке Active Directory Users and Computers (ADUC) имеется функция Saved Queries, которая представляет из себя сохраненные LDAP-фильтры. Для создания сохраненного запроса кликаем правой клавишей мыши и выбираем New — Query.
Даем запросу понятное имя и описание, в Query root выбираем область поиска и отмечаем пункт Include subconteiners (аналог Subtree) для поиска по всем вложенным объектам. Затем жмем кнопку Define Query.
Оснастка поддерживает несколько режимов и в принципе вовсе не обязательно писать текст фильтра вручную. Для наиболее часто встречающихся ситуаций достаточно выбрать нужный пункт и\или поставить галочку. Например, для показа всех пользователей с бессрочным паролем можно просто отметить чекбокс Non expiring passwords
Но мы не ищем легких путей, поэтому зададим фильтр руками. Для этого выбираем режим Custom Search и на вкладке Advanced вводим текст фильтра.
В результате в папке Saved Queries появляется список пользователей, у которых пароль не истекает. Таким же образом можно отслеживать множестао различных параметров пользователей, компьютеров и т.д.
А полученные результаты можно экспортировать в виде списка. Очень удобный и полезный функционал.
Примеры LDAP-фильтров
В заключение приведу примеры наиболее часто используемых LDAP-фильтров. Для удобства фильтры сгруппированы по типу объектов (пользователи, компьютеры, группы и прочие непонятные сущности).
Все пользователи:
Фильтр с использованием sAMAccountType более эффективен для объекта пользователь.
Все отключенные (Disabled) пользователи:
Все пользователи кроме отключенных:
Заблокированные (Locked) пользователи:
Здесь используется атрибут badPwdCount, в котором хранится количество неудачных попыток ввода пароля пользователем. Значение нужно указывать в соответствии с политиками безопасности вашего домена.
Пользователи, не менявшие пароль более 3 месяцев:
Атрибут pwdlastSet содержит в себе дату и время последней смены пароля пользователем. Он имеет тип Integer8 и представляет собой число временных интервалов длительностью 100 наносекунд, прошедших с 12:00 01.01.1601 (UTC). Получить требуемое значение можно с помощью PowerShell, например:
Пользователи, у которых пароль не истекает (Password newer expires):
Пользователи, обязанные сменить пароль при следующем входе в систему:
Если значение атрибута pwdlastSet равно 0 и при этом в свойствах учетной записи не отмечен пункт Password newer expires, то пользователь должен сменить пароль при следующем входе.
Пользователи, у которых не требуется пароль:
Пользователи с ограниченным сроком действия учетной записи:
Пользователи, у которых срок действия учетной записи не ограничен:
Атрибут accountExpires содержит дату истечения срока действия учетной записи и тоже представляет из себя число 100нс интервалов, прошедших с 01.01.1601 (UTC). Значение 0 или 9223372036854775807 (максимально возможное 64-битное число) означает, что срок действия учетной записи никогда не истечет.
Пользователи, созданные за определенный период:
В первом случае мы указываем только начальный период, во втором ограничиваем и начальный и конечный. Формат даты используется следующий:
YYYY MM DD HH mm ss.s Z
2020 01 01 00 00 00.0 Z
Кстати, таким образом можно искать не только пользователей, но и любые другие объекты в AD (компьютеры, группы и т.п.).
Пользователи, не заходившие в систему более чем 3 месяца:
Атрибуты lastLogon и lastLogonTimeStamp имеют такой же кривой тип, как pwdLastSet, и вычисляются таким же образом. Но между ними есть кардинальные различия, о которых необходимо знать.
lastLogon изменяется при входе пользователя только на том контроллере домена, на котором происходила аутентификация, на другие контроллеры он не реплицируется. Поэтому для получения точной информации необходимо произвести поиск на всех контроллерах домена, а потом сравнить полученные данные.
lastLogonTimeStamp также изменяется при входе пользователя, при этом он реплицируется на все контроллеры домена. Но сама репликация происходит с большой задержкой, порядка 9-14 дней. Поэтому полученные с его помощью данные могут быть не очень актуальны.
Пользователи, никогда не заходившие в систему:
Пользователи с почтовыми ящиками:
Пользователи, скрытые из адресной книги:
Все компьютеры:
Все компьютеры с определенной ОС:
Вместо Windows 7 можно поставить любую требуемую ОС.
Все серверы (компьютеры с серверной ОС):
Все контроллеры домена:
Контроллеры домена, доступные только для чтения:
Все серверы, не являющиеся контроллерами домена:
SQL серверы:
Exchange серверы:
Все группы:
Все локальные (Domain local) группы:
Все глобальные (Global) группы:
Все универсальные (Universal) группы:
Все группы безопасности (Security):
Все группы рассылки (Distribution):
Во втором случае ищутся все группы, имеющие почтовый адрес. Напомню, что группы безопасности также могут иметь почтовый адрес и использоваться для рассылки.
Все локальные группы безопасности:
Теоретически правильно использовать отрицательное значение, на практике работают оба.
Все глобальные группы безопасности:
Все универсальные группы безопасности:
Все встроенные группы (BuiltIn):
Все глобальные группы рассылки:
У группы безопасности восьмой бит должен быть установлен в 1, соответственно значение маски равно 2147483648. У группы рассылки этот бит установлен в о, соответственно и значение маски равно 0. Отсюда получаем значение 0 (Distribution) + 2 (Global) = 2 (Global Distribution Group).
Все локальные группы рассылки:
Все универсальные группы рассылки:
Все члены группы (без учета вложенности):
Все члены группы с учетом вложенности:
Все пользователи, не являющиеся членами группы (с учетом вложенности):
Все группы, в которые входит пользователь:
Все группы, в которые входит пользователь (с учетом вложенности):
Все пустые группы:
Все подразделения (OU):
Все контейнеры (CN):
Все встроенные контейнеры:
Все объекты групповой политики:
Все отношения доверия:
Все связи между сайтами в контейнере конфигурации:
Для запросов к атрибутам конфигурации нужно использовать поиск по контейнеру Configuration (напр. cn=Configuration,dc=test,dc=local).
Объекты, защищенные AdminSDHolder:
AdminSDHolder — это механизм защиты административных учетных записей. Если пользователь является членом защищенной группы (Domain Admins, Enterprise Admins и т.п.) то его учетной записи назначаются разрешения, установленные в объекте AdminSDHolder, а атрибуту adminCount пользователя присваивается значение 1.
Обратите внимание, что при удалении пользователя из защищенной группы его атрибут adminCount не возвращается к прежнему значению, соответственно запрос выдаст всех, кто когда либо входил в одну из этих групп.
Объекты, которые не могут быть удалены:
Атрибут systemFlags определяет дополнительные свойства объекта и представляет из себя битовую маску.
Объекты, которые не могут быть перенесены:
Объекты, которые не могут быть переименованы:
Атрибуты, помеченные в схеме как конфиденциальные:
Атрибут searchFlags определяет правила поиска и индексации для атрибута и представляет из себя битовую маску.
Атрибуты, сохраняемые в объекте захоронении (tombstone) при удалении объекта:
Объекты nTDSDSA связанные с глобальным каталогом:
С помощью этого запроса можно найти серверы глобального каталога. Поиск нужно проводить по контейнеру конфигурации. Подробнее об объектах nTDSDSA и их атрибутах.
Объекты nTDSDSA связанные с ролями FSMO:
Для ролей PDC Emulator, RID Master и Infrastructure Master нужно опрашивать домен. Владельца роли Schema Master нужно искать в контейнере Schema (напр. cn=Schema,cn=Configuration,dc=test,dc=local), а владельца Domain Naming Master — в контейнере Configuration (напр. cn=Configuration,dc=test,dc=local).
Powershell: как мне запросить pwdLastSet и имеет ли это смысл?
Мне нужно получить последнее изменение пароля для группы учетных записей в группе безопасности Active Directory, и я чувствую, что это то, что PowerShell должен хорошо делать.
Прямо сейчас я уже застрял в том, как прочитать атрибут pwdLastSet из учетной записи AD, на которую я смотрю. Даже запустить что-то простое, как это:
дает результаты для pwdLastSet, которые выглядят так:
Я чувствую, что поступаю неправильно, поэтому как лучше запросить, а затем отформатировать вывод (значение основано на эпохе Windows и не очень хорошо читается человеком) атрибута pwdLastSet?
Вы также можете сделать это без оснастки. Я попробовал это, и это сработало:
Если вы собираетесь много работать с AD (или Exchange, или с SQL Server), вы можете получить оснастку и использовать ее.
Встроенные командлеты AD, которые поставляются с Windows 7 / Windows Server 2008 R2, теперь могут делать это достаточно просто. В Windows 7 из командной строки Powershell:
Атрибут «PasswordLastSet» представляется переведенной версией фактического атрибута «pwdLastSet».
Есть более простой способ.
Это даст вам метку времени LDAP, которую необходимо преобразовать в удобочитаемую дату, как объяснено в Bratch выше. Это будет работать для любого значения атрибута timestamp, возвращаемого поставщиком ADSI, и метод ConvertLargeIntegerToInt64 (я полагаю) предоставляется любым объектом, представляющим запись каталога.
Собрав все вместе, вот как вы получите дату, когда пароль был последний раз установлен: