Заметки о Windows и других программных продуктах Microsoft...

Управление паролями пользователей в Active Directory. Часть 1

Управление паролями пользователей в Active Directory. Часть 1

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

Политика паролей по умолчанию

Из штатных средств в Active Directory для управления паролями есть только групповые политики. По умолчанию настройки паролей располагаются в дефолтной политике домена (Default Domain policy), в разделе Computer Configuration\Windows Settings\Security Settings\Account Policies\Password Policy.

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

Политика паролей Active Directory

 

За сложность пароля отвечает параметр Password must meet complexity requirements (Пароль должен соответствовать требованиям сложности), и его можно либо включить, либо выключить. Произвольно управлять требованиями нельзя, они зашиты в фильтре паролей passfit.dll.

параметр, отвечающий за сложность пароля

 

Сами требования выглядят так:

• Пароли не могут содержать имя учетной записи (samAccountName) или отображаемое имя (displayName), без учета регистра символов.
• SamAccountName проверяется полностью, только чтобы определить, является ли оно частью пароля. Если samAccountName имеет длину менее трех символов, это проверка пропускается.
• DisplayName анализируется на наличие разделителей: запятые, точки, дефисы, символы подчеркивания, пробелы, знаки фунта и табуляции. Если какой-либо из этих разделителей найден, displayName разделяется и все проанализированные разделы проверяются на то, что они не будут включены в пароль. Разделы меньше трех символов игнорируются. Например, имя «Vasily I. Pupkin» делится на три части: «Vasily», «I» и «Pupkin». Так как вторая часть имеет длину всего в один символ, она игнорируется. Таким образом, у этого пользователя не может быть пароля, который включал бы в себя «vasily» или «pupkin».
• Пароли должны содержать символы трех из пяти следующих категорий.

Категории символов Примеры
Прописные буквы европейских языков (от A до Z, диакритические знаки, греческий и кириллический символы) A, B, C, Z
Строчные буквы европейских языков (от a до z, sharp-s (ß), диакритические знаки, греческий и кириллический символы) a, b, c, z
Цифры (0-9) 0, 1, 2, 9
Служебные символы $,!,%,^,(){}[];:<>?
Любой символ Юникода, который классифицируется как буквенный символ, но не является верхним или нижним регистром. Сюда входят символы Юникода из азиатских языков. Ǚ (U+01D9)

 

Эти требования довольно легко обойти, например всем известные P@$$w0rd или 1Qwe2wsx отлично проходят по критериям сложности. Конечно можно увеличить минимальную длину паролей, скажем до 15 символов. Это заметно повысит надежность паролей, но вызовет у большинства пользователей сложности, поэтому на практике обычно устанавливают минимальную длину 8-10 символов.

Поиск слабых паролей

Для начала немного теории.

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

  1. Детерминированность — одинаковые входные данные всегда дают одинаковое значение хэша.
  2. Высокая скорость вычисления хэш-функций из любого сообщения.
  3. Однонаправленность — невозможно получить исходное сообщение, зная его хэш, за исключением попыток полного перебора.
  4. Наличие лавинного эффекта – минимальное изменение в исходном сообщении приводит к кардинальному изменению хэша.
  5. Невозможность найти одинаковое значение хэша для двух разных сообщений.

В Active Directory пароль пользователя не хранится в открытом виде, а сохраняются в виде хеша. Если точнее, то используется два типа хешей — хэш LM и хэш NT. Оба хэша имеют одинаковую длину 16 байт, но различаются в способе их вычисления. Процедура создания хеша LM следующая:

• Пароль пользователя преобразовывается в верхний регистр;
• Если пароль пользователя меньше 14 символов, он дополняется пустыми символами до 14. Если же пароль больше 14 символов, то Windows не использует этот хэш, предпочитая ему хэш NT;
• Затем пароль разбивается на две строки по 7 символов, и каждая строка используется в качестве ключа для шифрования строки KGS!+#$% с использованием криптографического алгоритма DES;
• Полученные два хэша объединяются, в результате получается хэш LM.

Хеш NT вычисляется путем применения алгоритма MD4 непосредственно к паролю пользователя в кодировке UTF-16.

Для наглядности пример хешей:

Password: 12345678
LM hash: 0182BD0BD4444BF836077A718CCDF409
NT hash: 259745CB123A52AA2E693AAACCA2DB52

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

Хеши паролей хранятся в базе данных ntds.dit (в атрибутах unicodePwd, dBCSPwd, lmPwdHistory, ntPwdHistory и extramentalCredentials). По соображениям безопасности эти атрибуты недоступны для чтения обычными средствами администрирования. Но мы сможем добраться до них с помощью специального PowerShell модуля Directory Services Internals (DSInternals).

Модуль опубликован в PowerShell Gallery и его можно  установить командой:

Install-Module -Name DSInternals

Как вариант, модуль можно скачать с GitHub, распаковать в любую папку и импортировать вручную, например:

Import-Module C:\PSModules\DSInternals\DSInternals.psd1

Этот модуль содержит ряд командлетов, которые позволяют выполнять различные нестандартные операции с Active Directory, причем как в онлайн, так и в офлайн режиме (непосредственно с базой ntds.dit). Вывести список доступных командлетов можно командой:

Get-Command -Module DSInternals

импорт модуля DSInternals

 

Для получения хэша воспользуемся коммандлетом Get-ADReplAccount. Для примера выведем информацию по одному пользователю:

Get-ADReplAccount -SamAccountName ivanov_i -Server Test-DC

Результат выполнения Get-ADReplAccount

 

Как видите, Get-ADReplAccount умеет  извлекать из AD множество интересной информации:

• Наименование учетной записи в различных форматах (DistinguishedName, SID, GUID, SAMAccountname, PrincipalName);
• Свойства учетной записи, хранящиеся в атрибуте UserAccountControl;
• Историю NTLM-хешей пароля учетной записи;
• Историю LM-хешей пароля учетной записи;
• Историю хешей пароля для kerberos аутентификации;
• Предварительно вычисленные хэш-формы, используемые в протоколах дайджест-аутентификации;
• Если включен флаг обратимого шифрования, то добавляется строка с паролем в открытом виде.

Примечание. По сути своей с помощью Get-ADReplAccount производится атака DCSync атака, позволяющая выдавать себя за контроллер домена с целью получения учетных данных пользователей. В основе атаки лежит механизм, предназначенный для выполнения репликации данных между контроллерами домена. Компания Microsoft рекомендует устанавливать как минимум два и более контроллера для одного домена в корпоративной сети, чтобы обеспечить избыточность и, как следствие, повысить отказоустойчивость доменной инфраструктуры. Механизм репликации данных архитектурно заложен в операционной системе Windows, а службы Active Directory с помощью протокола MS-DRSR обеспечивают взаимодействие между контроллерами домена и осуществляют репликацию. В процессе репликации данных между контроллерами помимо обычных атрибутов объекта (имя, фамилии, списка групп и т.п.) передается и чувствительная информация, например, хеши паролей пользователей, поскольку каждый контроллер выступает как точка для аутентификации и авторизации в домене. Именно из-за наличия такого механизма возможна реализация атаки типа DCSync. Атакующий, имея необходимый набор привилегий, может отправить одному из контроллеров домена организации запрос на выполнение репликации, запросив при этом информацию по одному или нескольким объектам в домене. Таким образом можно удаленно собрать хеши паролей пользователей и другую полезную информацию в домене без выполнения какого-либо вредоносного кода на самих контроллерах домена.

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

Qwewsx123
P@$$w0rd
1qaz2wsx

Теперь сравним пароли пользователей с нашим списком, выполнив команду:

Get-ADReplAccount -All -Server Test-DC -NamingContext "DC=Test,DC=local" | Test-PasswordQuality -WeakPasswordFile "C:\PSModuels\dict.txt" -IncludeDisabledAccounts

В результате получим пользователей, пароли которых совпадают с паролями из нашего списка, а также много другой интересной информации, например пользователей с одинаковыми паролями, пользователей с пустыми паролями (Password Not Required) или тех, у кого пароли которых никогда не истекают (Password Never Expires).

вывод слабых паролей

 

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

$pwd = ConvertTo-SecureString "QweWsx123" -AsPlainText -Force
ConvertTo-NTHash $pwd

А теперь сравним с хешем одного из пользователей. Как видите, они совпадают.

Сравнение хеша пароля

 

Чтобы не изобретать велосипед, можно скачать готовый список слабых\скомпрометированных (pwned) паролей, например вот здесь https://haveibeenpwned.com/Passwords. Список содержит более 500 миллионов записей и постоянно обновляется.

Для загрузки этого списка необходимо использовать специальную утилиту PwnedPasswordsDownloader. Для установки этой утилиты необходим .NET 6.о, причем ставить надо целиком SDK.

Чтобы инсталлятор смог найти нужный пакет, добавляем источник:

dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org

и устанавливаем утилиту командой:

dotnet tool install --global haveibeenpwned-downloader

установка PwnedPasswordsDownloader

 

Список немаленький, поэтому загружать его лучше в несколько потоков. Например следующая команда выгрузит все NT-хэши в один текстовый файл с именем pwnedpasswords_ntlm.txt, используя 64 потока, перезаписывая файл, если он уже существует:

haveibeenpwned-downloader.exe C:\HIBP\pwnedpasswords_ntlm -n -o -p 64

Загрузка списка паролей

 

После загрузки можем сравнить список скомпрометированных паролей с паролями наших пользователей. Для этого выгрузим из AD хэши паролей в файл командой:

Get-ADReplAccount -All -Server Test-DC -NamingContext "DC=Test,DC=local" | Format-Custom -View HashcatNT | Out-File C:\HIBP\AllHashes.txt -Encoding ASCII

выгрузка хэшей паролей всех пользователей

 

Для следующего шага нам потребуется  PowerShell модуль Match-ADHashes. Загружаем его и импортируем в текущий сеанс:

Import-Module C:\PSModules\Match-ADHashes.ps1

Сравниваем хэши пользователей со списком:

$list = Match-ADHashes -ADNTHashes C:\HIBP\AllHashes.txt -HashDictionary C:\HIBP\pwnedpasswords_ntlm.txt

Форматируем результат и выгружаем его в CSV-файл:

$list | select Hash,Frequency,@{Name=’user’;Expression={[string]::join(“;”, ($_.user))}} | Export-Csv -Path C:\HIBP\pwned-users-report.csv -Delimiter ‘;’ -NoTypeInformation

сравнение хэшей

 

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

результат сравнения хэшей

 

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

 
 
Комментарии

• Если включен флаг обратимого шифрования, то добавляется строка с паролем в открытом виде.
И как его поставить? 🙂

Очень ждем продолжения!

Ответить