Rotating the krbtgt password safely in Active Directory
Rotate krbtgt without an outage: New-KrbtgtKeys.ps1, replication checks, RODC krbtgt accounts, a routine schedule and the incident-mode double reset.
The krbtgt account's keys encrypt and sign every TGT in the domain. Whoever holds them can forge a golden ticket for any identity, with any group memberships, for as long as the key stays valid. In many domains that key has not changed since the domain was created, which means every past compromise, every old backup and every DCSync performed by a long-departed contractor still produces working tickets. Regular krbtgt rotation is the only control that expires that exposure.
The procedure itself is two password resets. What makes it safe is everything around it: understanding the key history, confirming replication, handling RODC accounts, and choosing between routine and incident mode. This guide expands on the double-reset section of Kerberos hardening.
Why two resets, and why the spacing matters
When krbtgt is reset, the DC keeps the previous key alongside the new one. A TGT encrypted with either key is accepted. This is what prevents an outage: tickets issued a minute before the reset remain valid.
- After reset 1: current key = K1, previous key = K0. Golden tickets forged with K0 still work.
- After reset 2: current key = K2, previous key = K1. K0 is gone, so tickets forged with the original key are rejected.
If reset 2 happens too early, legitimate TGTs issued with K0 just before reset 1 are also rejected. Users see authentication failures until they lock and unlock or sign in again, and services with long-running sessions may fail. The safe gap is the maximum TGT lifetime plus clock skew, after replication has converged.
# Read the Kerberos policy from the Default Domain Policy
$gpo = Get-GPO -Name 'Default Domain Policy'
$report = [xml](Get-GPOReport -Guid $gpo.Id -ReportType Xml)
$report.GPO.Computer.ExtensionData.Extension.Account |
Where-Object { $_.Type -eq 'Kerberos' } |
Select-Object Name, SettingNumberIf the query returns nothing, the policy is not defined explicitly and the defaults apply. MaxTicketAge (hours, default 10) is the TGT lifetime, MaxRenewAge (days, default 7) the renewal window and MaxClockSkew (minutes, default 5) the tolerance. Renewal requests are validated against the current or previous key, so a TGT issued under K0 cannot be renewed after reset 2 regardless.
Measure: current state
# krbtgt accounts in every domain of the forest, including RODC krbtgt_ accounts
(Get-ADForest).Domains | ForEach-Object {
Get-ADUser -Server $_ -Filter 'SamAccountName -like "krbtgt*"' `
-Properties PasswordLastSet, msDS-KeyVersionNumber |
Select-Object @{n='Domain';e={$_.DistinguishedName -replace '^.*?,DC=','DC='}},
SamAccountName, PasswordLastSet, msDS-KeyVersionNumber
}A PasswordLastSet measured in years is the norm on first run. Each domain has its own krbtgt; a multi-domain forest needs a rotation in every domain. Each RODC has a krbtgt_NNNNN account, linked from the RODC computer object through msDS-KrbTgtLink:
Get-ADComputer -Filter 'PrimaryGroupID -eq 521' -Properties msDS-KrbTgtLink |
Select-Object Name, msDS-KrbTgtLinkAudit: replication health first
A reset that has not reached every writable DC is dangerous. A DC that missed reset 1 keeps issuing TGTs with K0, and if reset 2 then replicates before reset 1 has converged, DCs end up with different key histories and reject each other's tickets. Never start a rotation while replication is failing.
# Forest-wide replication summary: every "fails" column must be 0
repadmin /replsummary
# Per-DC failures
Get-ADReplicationFailure -Target (Get-ADDomain).DNSRoot -Scope Domain |
Select-Object Server, Partner, FailureCount, LastErrorFix any errors, confirm all DCs are reachable, and make sure you have a recent, tested system state backup of at least one DC per domain before the first reset.
Plan the change
The first rotation in a domain whose krbtgt has not changed for years deserves a proper change record, even though the command itself takes seconds.
Inventory what depends on long-lived tickets. Ask application owners about services that authenticate once and hold a Kerberos session for days: Linux hosts using keytabs with renewable tickets, application servers with custom Kerberos clients, and long-running batch jobs. These are the systems that notice reset 2.
Pick the window. Reset 1 is invisible to users if replication is healthy. Reset 2 is the one that can surface problems, so schedule it at the start of a working day when support staff are present, not overnight when nobody will notice a broken integration until morning.
Order in a multi-domain forest. Rotations in different domains are independent, because each domain's krbtgt only signs TGTs for that domain; inter-realm tickets across trusts use the trust account keys instead. Start with a small child domain to rehearse, then the forest root, then the remaining domains. Do not run them all in the same window.
RODCs. In routine mode, rotate RODC krbtgt_NNNNN accounts after the domain account, one RODC at a time, confirming that the RODC and its writable replication partners agree on the new key version before moving on. Branch offices behind slow links are where convergence checks save you.
Evidence. Record the before and after msDS-KeyVersionNumber and PasswordLastSet for each account. Auditors and incident responders will ask when the key last changed, and the answer should be a document, not a guess.
Enforce: routine rotation with New-KrbtgtKeys.ps1
Use New-KrbtgtKeys.ps1, originally published by Microsoft and now maintained by the community on GitHub, rather than ad hoc Set-ADAccountPassword calls. The script offers an informational mode, a simulation mode that exercises the procedure against test krbtgt accounts it creates, and a real reset mode. In real mode it resets the chosen account on the PDC emulator (or the RODC's source DC for RODC accounts), forces single-object replication of the account to every DC, and checks that each DC reports the new key version. Read its menu carefully and run the informational and simulation modes first in every domain.
A routine rotation looks like this:
- Run the script in informational mode and read the report: DCs discovered, reachability, key version on each DC.
- Run simulation mode against the test accounts; confirm replication succeeds to every DC.
- Reset 1 of the domain
krbtgtin real mode. ConfirmmsDS-KeyVersionNumberincremented on every DC. - Wait at least
MaxTicketAge+MaxClockSkew(24 hours is a comfortable default). - Reset 2 in real mode, with the same checks.
- Repeat for RODC
krbtgt_NNNNNaccounts and for every other domain in the forest.
Regardless of the password supplied, the DC generates its own random value for krbtgt, so there is nothing to store in a vault.
Schedule routine rotation at least every 180 days, and additionally after any Tier 0 admin leaves, after a restore of AD from backup media that left your control, and after any suspected DCSync or NTDS.dit exposure.
Incident mode
When you have evidence of krbtgt compromise (a DCSync from an unexpected source, golden ticket indicators, a stolen DC backup), you want the old key gone now, not tomorrow.
- First remove the attacker's ability to read the new key: reset or disable compromised Tier 0 accounts, remove rogue DCSync rights (see finding DCSync rights), and isolate compromised hosts.
- Perform reset 1, wait only for replication to converge across all DCs (minutes, not hours), then perform reset 2.
- Accept the impact: every TGT in the domain becomes invalid. Users re-authenticate at their next resource access or sign-in; long-running services may need restarts.
- Repeat the double reset at the end of recovery, once you are confident persistence is gone.
Forcing replication between resets matters more in incident mode, because you do not have the time buffer to absorb a slow link:
# Push the krbtgt object to all DCs from the PDC emulator
$pdc = (Get-ADDomain).PDCEmulator
$krbtgt = (Get-ADUser krbtgt).DistinguishedName
Get-ADDomainController -Filter 'IsReadOnly -eq $false' | ForEach-Object {
Sync-ADObject -Object $krbtgt -Source $pdc -Destination $_.HostName
}Verify
# Key version and pwdLastSet must match on every writable DC
Get-ADDomainController -Filter * | ForEach-Object {
$dc = $_.HostName
Get-ADUser krbtgt -Server $dc -Properties msDS-KeyVersionNumber, PasswordLastSet |
Select-Object @{n='DC';e={$dc}}, msDS-KeyVersionNumber, PasswordLastSet
}
# Replication metadata shows when and where the password change originated
Get-ADReplicationAttributeMetadata -Object (Get-ADUser krbtgt).DistinguishedName `
-Server (Get-ADDomain).PDCEmulator -Properties unicodePwd, pwdLastSet |
Select-Object AttributeName, LastOriginatingChangeTime, LastOriginatingChangeDirectoryServerIdentity, VersionRODCs do not hold the domain krbtgt secret, so check their own krbtgt_NNNNN accounts the same way after rotating them. On the security side, a krbtgt reset produces event 4724 (password reset attempt) and 4738 on the DC where it ran. Alert on those events outside planned change windows: an unexpected krbtgt reset is either a mistake or an attacker covering tracks. Tell the SOC about planned rotations in advance so the rotation itself does not trigger an incident.
What it breaks
- Reset 2 too early invalidates legitimate TGTs: users see access-denied or credential prompts until they sign in again, and services holding tickets fail until restarted.
- Replication lag between resets causes intermittent authentication failures that depend on which DC a client reaches. This is why convergence checks are not optional.
- Long-running sessions and services that cache TGTs for days (some Linux services with
k5start, application servers with renewable tickets, Kerberos-authenticated VPN sessions) may need restarts after reset 2. - Incident mode invalidates every TGT at once, so expect a spike in helpdesk calls and plan communications in advance.
- Old
krbtgtpasswords predating AES mean the first rotation is also the first timekrbtgthas AES keys, which can expose clients that only handled RC4. See disabling RC4 in Kerberos.
Related reading: the Kerberos and authentication area, identifying Tier 0 assets to find everything that could leak the new key, and the forest recovery plan, where the double reset is a mandatory step.
Frequently asked questions
How long should I wait between the two krbtgt resets?
At least the maximum TGT lifetime plus clock skew, and after confirming the first reset has replicated to every DC. With default Kerberos policy that is 10 hours plus 5 minutes; many teams simply wait 24 hours. The wait matters for routine rotations. During an active golden ticket incident you deliberately skip it and accept that every existing TGT is invalidated.
Do I need to rotate the krbtgt_ accounts of read-only domain controllers?
Yes, if the RODC may be compromised or as part of routine hygiene. Each RODC has its own krbtgt_NNNNN account whose key signs the TGTs that RODC issues. Resetting the domain krbtgt does not touch those keys. For a stolen or compromised RODC, Microsoft's guidance is to delete the RODC computer account, which also removes its krbtgt account, and reset the passwords of accounts cached on it.
Does rotating krbtgt stop an attacker who still has domain admin rights?
No. Rotation invalidates golden tickets forged with the old key, but an attacker with Domain Admin or DCSync rights can simply read the new key. Rotate krbtgt as part of eviction, after the attacker's access paths, persistence and privileged credentials have been removed, and repeat the double reset at the end of the recovery.
Rotating the krbtgt password safely in Active Directory