This lab will guide you through some of the most interesting features of the DSInternals PowerShell Module, which was featured at Black Hat Europe 2019 and is also included in FireEye’s Commando VM. This open-source toolset exposes many internal and undocumented security-related features of Active Directory (AD), but we will primarily focus on its state-of-the-art offline database access capabilities. In the course of this lab, you will learn how to perform Active Directory password audits, offline password resets and group membership changes, or SID history injection.
Active Directory Database
The Active Directory database contains information about objects such as user accounts, computers, groups, contacts, organizational units, printers, and security policies. Servers hosting this database are called Domain Controllers (DCs) and expose the information through a plethora of network protocols, including the Lightweight Directory Access Protocol (LDAP).
Database files, transaction logs and checkpoint files are typically stored in the C:\Windows\NTDS directory on all DCs. The main database file is called ntds.dit. The following diagram shows the data store physical structure:
Sensitive information in the ntds.dit file is encrypted using the Boot Key (sometimes called System Key or SysKey), which is unique to each DC and is located deep in the HKEY_LOCAL_MACHINE\SYSTEM registry hive. This hive is physically stored in the C:\Windows\system32\config\SYSTEM file.
Setting Things Up
To be able to perform all exercises in this lab, you need to prepare the following:
1. Windows 10 Computer
First of all, you will need a Windows 10 computer with internet connectivity and local administrative rights. A virtual machine can be used instead of a physical computer.
Note that the DSInternals PowerShell module relies heavily on Win32 API calls that are not available in PowerShell Core for Linux and Mac. As a result, Windows is the only supported platform.
Notice that the database file comes from a DC running Windows Server 2019.
Note that if the database had transaction logs that were located in a different directory than the database itself, you would need to specify their location using the -LogPath parameter.
In case you see a red error message instead of the output above, read the next chapter. You can otherwise skip to Exercise 2.
If Things Do Not Work
Before opening a database that originates from a different Windows version or build, you sometimes need to defragment it first by running the following sequence of commands:
cd “ADBackup\Active Directory” esentutl.exe /d ntds.dit
Our sample database is in a clean state. It would otherwise have to be repaired by replaying the corresponding transaction logs. This can be achieved by running the following sequence of commands:
cd “ADBackup\Active Directory” esentutl.exe /r edb /d
Additionally, the built-in esentutl tool might fail to open a database that originates from Windows Server 2016 or newer and throw the following error message instead:
Operation terminated with error -2102 (JET_errCallbackNotResolved, A callback function could not be found) after 9.78 seconds.
This issue can be resolved by installing the Active Directory Lightweight Directory Services Windows component by executing the following command in an elevated PowerShell console:
Note that this component is not available on Windows 10 Home edition.
Exercise 2: Decrypting Password Hashes
In order to decrypt the database, we first need to retrieve the encryption key from the registry hive by running the following command in an elevated PowerShell console:
Notice that AD contains multiple types of password hashes in order to support different authentication protocols, including Kerberos, NTLM, and WDigest.
We might also be interested in the built-in Administrator account. As some companies rename this account, it is safer to locate it by its well-known security identifier (SID), which always ends with 500 (AKA relative identifier or RID):
There are many password cracking tools that can be used to perform dictionary or brute-force attacks against NT hashes (that is MD4 hashes) of passwords that are contained in the AD database and thus identify user accounts with weak passwords. One of the more popular ones is Hashcat and DSInternals can be used to export data in a format that is understood by this tool:
For security reasons, some companies are reluctant to use password cracking tools. That is why DSInternals has a built-in password auditing capability:
# Create a sample text file containing banned/weak passwords‘Pa55w.rd’,‘December2019’,‘November2019’ > ‘.\banned-passwords.txt’# Read all accounts from the AD database and test them against the provided lists of weak passwords Get-ADDBAccount -All ` -DatabasePath ‘.\ADBackup\Active Directory\ntds.dit’ ` -BootKey 0be7a2afe1713642182e9b96f73a75da | Test-PasswordQuality -WeakPasswords ‘Pa$$w0rd’,‘Password123’ ` -WeakPasswordsFile ‘.\banned-passwords.txt’ ` -WeakPasswordHashesSortedFile ‘.\pwned-passwords-ntlm-ordered-by-hash-v4.txt’
The output should look like this:
Active Directory Password Quality Report —————————————- Passwords of these accounts are stored using reversible encryption: Sory1992 LM hashes of passwords of these accounts are present: These accounts have no password set: Guest Passwords of these accounts have been found in the dictionary: Abouty AdfsService Administrator Forsel Install joe john Messin Nibeshe Sloned Thopliterce1964 Throson Tilen2000 These groups of accounts have the same passwords: Group 1: Abouty Administrator Forsel Install joe john Group 2: Messin Sloned Group 3: Throson Tilen2000 These computer accounts have default passwords: PC01$ PC03$ Kerberos AES keys are missing from these accounts: Thopliterce1964 Kerberos pre-authentication is not required for these accounts: Countim Madisenly Theamorty Only DES encryption is allowed to be used with these accounts: Spitied Stely1971 Theamorty These administrative accounts are allowed to be delegated to a service: AdfsService Administrator Install Passwords of these accounts will never expire: Abouty AdfsService Administrator Affeard Guest Install joe john These accounts are not required to have a password: Guest PC01$ PC02$ PC03$
In the example above, we are providing lists of weak passwords (dictionaries) to the Test-PasswordQuality cmdlet in multiple ways: Directly in the command line parameters, in a text file containing one password per line and in a text file containing password hashes. Note that the -WeakPasswordHashesSortedFile parameter should point to the list of leaked password hashes from HIBP. You can omit this parameter if you have not downloaded this list.
Exercise 5: Filtering Accounts
If it is desired to only check a subset of user accounts, we can use PowerShell’s built-in filtering capabilities. The following script will check passwords of accounts that are located in the Employees organizational unit (OU):
The account should now be enabled and a member of Domain Admins. As we do not know its password, we can perform an offline password reset:
$password = Read-Host -AsSecureString -Prompt ‘Provide new password for user hacker’ Set-ADDBAccountPassword -SamAccountName hacker ` -NewPassword $password ` -DatabasePath ‘.\ADBackup\Active Directory\ntds.dit’ ` -BootKey 0be7a2afe1713642182e9b96f73a75da
If we now copied the database back to the original DC, we would be able to authenticate as user hacker.
Exercise 7: Injecting SID History
The sIDHistory attribute is commonly used during AD migrations and may contain historical SIDs of users and groups. For security reasons, it cannot be modified through the LDAP protocol and even the Active Directory Migration Tool (ADMT) cannot be used to write any arbitrary values into it. But we can again use DSInternals to inject any SID into sIDHistory by directly modifying the database:
Note that S-1-5-21-1236425271-2880748467-2592687428 is the SID of the domain and 500 and 512 are well-known rids of the Administrator account and the Domain Admins group, respectively.
Exercise 8: Replication Metadata
All the commands from the previous exercises properly modified replication metadata. If we were on a live domain controller, the modified attribute values would thus get replicated to other DCs. This could also be checked using the repadmin tool:
Notice how the version, time and USN of attributes userAccountControl, dBCSPwd, unicodePwd, ntPwdHistory, pwdLastSet, primaryGroupID, supplementalCredentials, and lmPwdHistory, that we intentionally modified, differs from the others.
In some cases, this default and correct behavior might be undesirable. Hence the optional -SkipMetaUpdate parameter of all cmdlets that modify AD database:
Changes performed using the command above would only stay locally instead of replicating to other DCs. This could be used by adversaries to hide from security audits.
Conclusion
You now know how to use the DSInternals PowerShell module to identify many violations of Active Directory security best practices, including bad credential hygiene. We have also discussed several attack vectors that would open to malicious attackers and insiders by gaining read/write access to either a physical or virtual hard drive of a DC containing its ntds.dit database file. Limiting access to domain controller hard drives is, therefore, an important aspect of keeping Active Directory secure. However, this task has become more complex in today’s era of virtualization and cloud computing.
To Be Continued…
The DSInternals PowerShell module can do so much more. We will explore more of its capabilities in a future lab.
Author
Michael Grafnetter is an expert on Active Directory security who works as a consultant, trainer, and researcher. He is best known as the author of the open-source Directory Services Internals (DSInternals) PowerShell module and Thycotic Weak Password Finder, tools used by security auditors and penetration testers worldwide. He holds a master’s degree in Software Engineering and is a former Microsoft MVP. Michael was a speaker at many conferences, including Black Hat Europe, HipConf New York, and BSides Lisbon.