How to Harden Active Directory Against Common Attacks on Windows Server 2025
Active Directory remains the most frequently targeted component in enterprise environments. Once an attacker gains initial access to a domain-joined machine, the path to domain compromise runs through AD — harvesting credentials, abusing Kerberos, and exploiting misconfigured delegations or excessive privileges. Windows Server 2025 introduces enhanced security defaults and updated tooling, but hardening requires deliberate configuration across multiple layers. This tutorial covers the six most prevalent AD attack techniques and the specific, actionable defenses you can deploy today: the Protected Users security group, Credential Guard for Tier-0 assets, KRBTGT key rotation, Kerberoasting and AS-REP roasting detection and remediation, and AdminSDHolder/SDProp auditing. Each section includes PowerShell you can run immediately in your environment.
Prerequisites
- Windows Server 2025 domain controllers with Active Directory Domain Services
- Domain functional level 2012 R2 or higher (required for Protected Users group)
- Domain Admin or equivalent privileges
- RSAT Active Directory PowerShell module:
Install-WindowsFeature RSAT-AD-PowerShell - Microsoft Defender for Identity or similar behavioral detection (recommended)
- PowerShell 5.1 or later
Step 1: Understand the Top Active Directory Attack Vectors
Each attack technique targets a specific weakness in Active Directory’s design or a common misconfiguration:
- Pass-the-Hash (PtH): Reusing an NTLM hash captured from memory (LSASS) to authenticate as the victim without knowing the plaintext password.
- Pass-the-Ticket (PtT): Stealing an in-memory Kerberos TGT or service ticket (using tools like Mimikatz) and replaying it from a different machine.
- Golden Ticket: Forging a Kerberos TGT signed with the KRBTGT account’s password hash, granting domain-wide, long-lived authentication as any user including fabricated accounts.
- Kerberoasting: Requesting Kerberos service tickets for accounts with SPNs (any domain user can do this), then cracking the RC4-encrypted ticket offline to recover the service account password.
- AS-REP Roasting: Requesting an AS-REP for accounts that do not require Kerberos pre-authentication. The encrypted portion can be cracked offline without needing a TGT first.
- DCSync: Using the
DS-Replication-Get-Changes-Allright to simulate a domain controller and pull password hashes for all accounts — including KRBTGT — directly from AD replication.
Step 2: Deploy the Protected Users Security Group
The Protected Users security group, introduced in Windows Server 2012 R2, is one of the most powerful and underutilized Active Directory hardening controls. Membership in this group enforces the following restrictions at the KDC level — no client-side configuration required:
- NTLM authentication is blocked (eliminates Pass-the-Hash for group members)
- DES and RC4 Kerberos encryption types are blocked (forces AES)
- Kerberos ticket lifetime is reduced to 4 hours (not renewable)
- Credentials are not cached on the local machine (blocks offline credential extraction)
- Kerberos delegation (constrained or unconstrained) is blocked
Import-Module ActiveDirectory
# Add high-privilege accounts to Protected Users
$accountsToProtect = @(
"Administrator",
"Domain Admins",
"Enterprise Admins",
"Schema Admins"
)
foreach ($account in $accountsToProtect) {
try {
Add-ADGroupMember -Identity "Protected Users" -Members $account -ErrorAction Stop
Write-Host "Added $account to Protected Users" -ForegroundColor Green
} catch {
Write-Warning "Could not add $account : $($_.Exception.Message)"
}
}
# Verify membership
Get-ADGroupMember -Identity "Protected Users" -Recursive |
Select-Object Name, objectClass, DistinguishedName |
Sort-Object objectClass, Name
# Test impact: verify NTLM is blocked for a Protected User account
# This will fail with NTLM error if working correctly
# Test-WSMan -ComputerName "dc01" -Authentication NTLM -Credential (Get-Credential)
Warning: Do not add service accounts or computer accounts to Protected Users without thorough testing. Applications relying on NTLM authentication, cached credentials, or Kerberos delegation will break immediately for members of this group.
Step 3: Enable Credential Guard on Tier-0 Assets
Windows Defender Credential Guard uses Virtualization-Based Security (VBS) to isolate LSASS into a separate, protected virtual trust level. Even if an attacker achieves kernel-level code execution on a Tier-0 server, they cannot extract credentials from the protected LSASS instance.
# Enable Credential Guard via registry (for individual servers)
# Requires reboot to take effect
# LsaCfgFlags values:
# 0 = Disabled
# 1 = Enabled with UEFI lock (cannot be disabled remotely)
# 2 = Enabled without UEFI lock (can be disabled remotely)
$regPath = "HKLM:SYSTEMCurrentControlSetControlDeviceGuard"
# Enable VBS
Set-ItemProperty -Path $regPath -Name "EnableVirtualizationBasedSecurity" -Value 1 -Type DWord
Set-ItemProperty -Path $regPath -Name "RequirePlatformSecurityFeatures" -Value 3 -Type DWord # Secure Boot + DMA protection
# Enable Credential Guard with UEFI lock (recommended for Tier-0)
$lsaPath = "HKLM:SYSTEMCurrentControlSetControlLsa"
Set-ItemProperty -Path $lsaPath -Name "LsaCfgFlags" -Value 1 -Type DWord
Write-Host "Credential Guard configured. Reboot required." -ForegroundColor Yellow
# Verify Credential Guard status after reboot
Get-WinEvent -LogName "System" -FilterXPath "*[System[EventID=14]]" |
Select-Object -First 5 TimeCreated, Message
# Alternative verification
$info = Get-ComputerInfo
$info.DeviceGuardCodeIntegrityPolicyEnforcementStatus
$info.DeviceGuardSecurityServicesRunning
Step 4: Rotate the KRBTGT Account Password
The KRBTGT account’s password hash is used to sign and encrypt all Kerberos TGTs in the domain. If an attacker obtains this hash (via DCSync, NTDS.DIT extraction, or domain controller compromise), they can forge Golden Tickets that remain valid indefinitely. KRBTGT password rotation invalidates all existing TGTs and is the primary remediation after any Tier-0 compromise.
KRBTGT rotation must be performed twice, at least 10 hours apart (the default maximum TGT lifetime). This ensures both the current and previous hash values are rotated out, eliminating any forged tickets that reference either key version.
# Download the official Microsoft KRBTGT rotation script
# Source: https://github.com/microsoft/New-KrbtgtKeys.ps1
$scriptPath = "C:ToolsNew-KrbtgtKeys.ps1"
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/microsoft/New-KrbtgtKeys.ps1/main/New-KrbtgtKeys.ps1" `
-OutFile $scriptPath
# Run in Simulation mode first to assess impact (does NOT change the password)
& $scriptPath -Mode Simulation -TargetDC "dc01.contoso.com"
# After reviewing simulation output, perform the actual first rotation
# (Run on the PDC Emulator FSMO role holder)
$pdcEmulator = (Get-ADDomain).PDCEmulator
& $scriptPath -Mode Reset -TargetDC $pdcEmulator
Write-Host "First KRBTGT rotation complete. Wait at least 10 hours before second rotation."
Write-Host "Monitor for Kerberos authentication failures before proceeding."
# Second rotation (run after 10+ hours to ensure replication and ticket expiry)
& $scriptPath -Mode Reset -TargetDC $pdcEmulator
Write-Host "Second KRBTGT rotation complete. All Golden Tickets are now invalid."
After each rotation, monitor Event ID 4769 (Kerberos service ticket request failures) on domain controllers. A spike indicates clients holding old TGTs that need to re-authenticate — this is expected and self-resolving within the ticket lifetime window.
Step 5: Detect and Remediate Kerberoasting
Kerberoasting exploits the fact that any authenticated domain user can request a Kerberos service ticket for any account with an SPN. The ticket is encrypted with the service account’s password hash using RC4-HMAC by default, allowing offline brute-force cracking. The defense is a combination of detection (monitoring for Event 4769 with RC4 encryption from unusual sources) and remediation (strong passwords, AES-only SPNs, managed service accounts).
# Find all Kerberoastable accounts (SPN + enabled + not Managed Service Account)
Get-ADUser -Filter { ServicePrincipalName -like "*" -and Enabled -eq $true } `
-Properties ServicePrincipalName, PasswordLastSet, PasswordNeverExpires |
Select-Object SamAccountName,
@{N='SPNs'; E={ $_.ServicePrincipalName -join '; ' }},
PasswordLastSet,
PasswordNeverExpires |
Sort-Object PasswordLastSet
# Force AES encryption only for service accounts (prevents RC4 downgrade)
$kerberoastableAccounts = Get-ADUser -Filter { ServicePrincipalName -like "*" -and Enabled -eq $true }
foreach ($account in $kerberoastableAccounts) {
# Set AES encryption types only (removes RC4/DES options)
Set-ADUser -Identity $account -KerberosEncryptionType AES128, AES256
Write-Host "Updated encryption types for $($account.SamAccountName)"
}
# Detect Kerberoasting attempts via Event 4769 (RC4 ticket requests at scale)
$startTime = (Get-Date).AddHours(-24)
Get-WinEvent -ComputerName (Get-ADDomainController -Filter *).Name `
-FilterHashtable @{ LogName = 'Security'; Id = 4769; StartTime = $startTime } `
-ErrorAction SilentlyContinue |
ForEach-Object {
[PSCustomObject]@{
Time = $_.TimeCreated
ServiceName = $_.Properties[2].Value
ClientName = $_.Properties[0].Value
EncryptType = $_.Properties[3].Value # 0x17 = RC4 (suspicious)
ClientAddress= $_.Properties[6].Value
}
} |
Where-Object { $_.EncryptType -eq "0x17" } |
Group-Object ClientAddress |
Sort-Object Count -Descending
Step 6: Disable AS-REP Roasting Vulnerability
AS-REP roasting targets accounts with Do not require Kerberos preauthentication enabled. When this flag is set, the KDC returns an AS-REP without requiring the client to prove identity first. The AS-REP contains data encrypted with the account’s password hash, enabling offline cracking. This flag should essentially never be set on user accounts.
# Find all accounts with Kerberos pre-authentication disabled
Get-ADUser -Filter { DoesNotRequirePreAuth -eq $true -and Enabled -eq $true } `
-Properties DoesNotRequirePreAuth, PasswordLastSet |
Select-Object SamAccountName, PasswordLastSet, DoesNotRequirePreAuth
# Remediate: re-enable Kerberos pre-authentication on all affected accounts
$asrepVulnerable = Get-ADUser -Filter { DoesNotRequirePreAuth -eq $true -and Enabled -eq $true }
foreach ($user in $asrepVulnerable) {
Set-ADAccountControl -Identity $user -DoesNotRequirePreAuth $false
Write-Host "Re-enabled Kerberos pre-auth for: $($user.SamAccountName)" -ForegroundColor Green
}
# Verify no accounts remain vulnerable
$remaining = Get-ADUser -Filter { DoesNotRequirePreAuth -eq $true -and Enabled -eq $true } |
Measure-Object
Write-Host "Accounts still vulnerable to AS-REP roasting: $($remaining.Count)"
Step 7: Audit AdminSDHolder and SDProp
AdminSDHolder is a special AD object whose ACL serves as a template. Every 60 minutes, the SDProp process copies AdminSDHolder’s ACL to all objects in protected groups (Domain Admins, Schema Admins, etc.). Attackers who gain a temporary foothold in a protected group may add a persistent backdoor ACE to AdminSDHolder, ensuring their access persists even after removal from the group. Regularly audit AdminSDHolder’s ACL for unexpected entries.
Import-Module ActiveDirectory
# Get AdminSDHolder object DN
$domain = Get-ADDomain
$adminSDHolderDN = "CN=AdminSDHolder,CN=System,$($domain.DistinguishedName)"
# Audit AdminSDHolder ACL for non-default entries
$acl = Get-Acl -Path "AD:$adminSDHolderDN"
$acl.Access |
Where-Object {
# Filter out well-known built-in SIDs that are expected
$_.IdentityReference -notmatch "^(BUILTIN|NT AUTHORITY|S-1-5-32)" -and
$_.IdentityReference -notmatch "(Domain Admins|Enterprise Admins|Administrators|SYSTEM|SELF)"
} |
Select-Object IdentityReference, ActiveDirectoryRights, AccessControlType, IsInherited |
Sort-Object IdentityReference
# Find accounts with AdminCount=1 that are no longer in protected groups
# These "orphaned" AdminCount accounts retain hardened ACLs but lack ongoing SDProp protection
$protectedGroups = @("Domain Admins","Enterprise Admins","Schema Admins",
"Administrators","Account Operators","Backup Operators",
"Print Operators","Server Operators","Group Policy Creator Owners")
$allProtectedMembers = foreach ($group in $protectedGroups) {
Get-ADGroupMember -Identity $group -Recursive -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty SamAccountName
}
Get-ADUser -Filter { AdminCount -eq 1 -and Enabled -eq $true } |
Where-Object { $allProtectedMembers -notcontains $_.SamAccountName } |
Select-Object SamAccountName, DistinguishedName |
Sort-Object SamAccountName
Step 8: Restrict DCSync Rights
DCSync attacks are executed by any account holding the DS-Replication-Get-Changes-All extended right on the domain NC root. By default only Domain Controllers, Domain Admins, and Enterprise Admins hold this right. Audit and remove any non-DC accounts holding this privilege.
# Identify accounts with DCSync rights (DS-Replication-Get-Changes-All)
$domainDN = (Get-ADDomain).DistinguishedName
$dsReplGuid = [GUID]"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2" # DS-Replication-Get-Changes-All
$acl = Get-Acl "AD:$domainDN"
$acl.Access |
Where-Object {
$_.ObjectType -eq $dsReplGuid -and
$_.ActiveDirectoryRights -match "ExtendedRight"
} |
Select-Object IdentityReference, ActiveDirectoryRights, AccessControlType |
Sort-Object IdentityReference
Conclusion
Active Directory hardening is not a one-time project — it is an ongoing operational discipline. The attack techniques covered in this tutorial (Pass-the-Hash, Pass-the-Ticket, Golden Ticket, Kerberoasting, AS-REP roasting, and DCSync) represent the real-world playbook used in the majority of enterprise breaches. On Windows Server 2025, deploying the Protected Users security group for all privileged accounts, enforcing Credential Guard on Tier-0 infrastructure, rotating the KRBTGT password on a regular maintenance cycle, and eliminating AS-REP roastable and Kerberoastable accounts dramatically reduces your attack surface. Pair these controls with behavioral detection (Defender for Identity or a SIEM), and regularly audit AdminSDHolder and DCSync rights to catch persistence mechanisms before attackers can leverage them. Defense in depth across all of these layers is the only reliable strategy against modern AD-focused threat actors.