Remediation Guides

Kerberoasting Mitigation: How to Fix Privileged Accounts With SPNs (Nessus 150480, PingCastle P-Kerberoasting)

26 September 2026 8 min read

Kerberoasting mitigation means ensuring no privileged account carries a service principal name (SPN), because any domain user can request its service ticket and crack the password offline. Remove SPNs from human admin accounts with setspn -D, take service accounts out of admin groups, move services to gMSAs, and use AES plus long random passwords where an SPN must stay.

The finding usually lands on one of two accounts: an old service account someone put in Domain Admins “to make it work”, or a human admin account that picked up an SPN during a test years ago. Both are quick to fix once you know what the service actually needs.

What the scanner is actually detecting

All three tools read Active Directory and look for the same combination: membership in a privileged group plus a populated servicePrincipalName attribute on a user account.

Scanner Finding title What triggers it
Nessus, plugin 150480 (High) AD Starter Scan – Kerberoasting LDAP enumeration of users and groups finds a privileged user account with an SPN. Disabled privileged accounts are skipped unless thorough tests are enabled. Tenable states results are accurate for AD deployments up to 5,000 users, groups or machines.
PingCastle, rule P-Kerberoasting Check if admin accounts are vulnerable to the Kerberoast attack. A member of Domain Admins, Enterprise Admins, Schema Admins or Administrators has an SPN and a password older than 40 days. The report detail lists the user, the groups and the SPNs.
Tenable Identity Exposure Privileged Accounts Running Kerberos Services Indicator of exposure for privileged accounts with an SPN. Tenable’s stated solution is that privileged accounts should not have one.

Real-world risk, stated honestly

Any authenticated domain user can ask a domain controller for a service ticket to any SPN. Part of that ticket is encrypted with a key derived from the service account’s password. The attacker takes it offline and guesses passwords against it at whatever speed their hardware allows, with no lockout and no failed logons on the DC. MITRE ATT&CK tracks this as T1558.003. If the account is a Domain Admin, one cracked password is the whole domain.

The limits are real too. The attacker needs a foothold first (any domain account will do), and success depends entirely on the password. A randomly generated password of 25 or more characters is not a practical cracking target; a human-chosen password set years ago often is. Microsoft notes that GPU-accelerated cracking is making the attack more effective, which is why RC4 tickets (faster to crack) and old service passwords are the usual victims. Also remember that a privileged service account leaves its credentials on every server where the service runs, so protecting LSASS with Credential Guard and RunAsPPL matters on those hosts as well.

How to confirm it in your domain

Run these from a machine with the RSAT Active Directory module. The first query is a fast first pass using adminCount:

Import-Module ActiveDirectory

Get-ADUser -Filter {ServicePrincipalName -like '*'} `
    -Properties ServicePrincipalName, AdminCount, PasswordLastSet, 'msDS-SupportedEncryptionTypes' |
    Where-Object { $_.AdminCount -eq 1 -and $_.SamAccountName -ne 'krbtgt' } |
    Select-Object SamAccountName, Enabled, PasswordLastSet, 'msDS-SupportedEncryptionTypes',
        @{n='SPNs'; e={ $_.ServicePrincipalName -join '; ' }}

krbtgt is excluded because it always has an SPN and a system-managed password. adminCount is only a hint: it stays at 1 after an account leaves a protected group. For the accurate list, check recursive membership of the same groups PingCastle uses:

$groups = 'Domain Admins','Enterprise Admins','Schema Admins','Administrators'
$members = foreach ($g in $groups) {
    Get-ADGroupMember -Identity $g -Recursive -ErrorAction SilentlyContinue |
        Where-Object objectClass -eq 'user'
}
$members | Sort-Object SamAccountName -Unique | ForEach-Object {
    Get-ADUser -Identity $_.SID -Properties ServicePrincipalName, PasswordLastSet
} | Where-Object { $_.ServicePrincipalName } |
    Select-Object SamAccountName, PasswordLastSet, @{n='SPNs'; e={ $_.ServicePrincipalName -join '; ' }}

Enterprise Admins and Schema Admins exist only in the forest root domain, hence the silenced errors. For a single account, setspn -L CORPsvc-sql lists its SPNs. The SPN itself (for example MSSQLSvc/sql01.corp.example.com:1433) tells you which host and service depend on it. A value of 24 in msDS-SupportedEncryptionTypes means AES128 and AES256 only; an empty value means the domain default applies.

How to fix it

Human admin accounts: delete the SPN

A person’s admin account has no reason to be a service identity. Record the SPN first so you can put it back, then remove it:

setspn -L CORPjdoe-admin
setspn -D HTTP/test01.corp.example.com CORPjdoe-admin

The PowerShell equivalent is Set-ADUser jdoe-admin -ServicePrincipalNames @{Remove=’HTTP/test01.corp.example.com’}.

Service accounts: take them out of admin groups

Find out what the service really does (local admin on a few servers, a delegated right on one OU, read access to a share), grant exactly that, and then remove the membership:

Remove-ADGroupMember -Identity 'Domain Admins' -Members svc-backup -Confirm:$false

Restart the service afterward so its logon token no longer carries the old group.

Better: move the service to a gMSA

Microsoft recommends group Managed Service Accounts because their 120-character passwords are generated and rotated by the domain. Requirements: domain and forest functional level Windows Server 2012 or later and a KDS root key (check with Get-KdsRootKey).

# Once per forest, on a DC. Other DCs can use it only after replication (allow up to 10 hours)
Add-KdsRootKey -EffectiveImmediately

# Create the gMSA; SQL-Servers is a group holding the hosts' computer accounts
New-ADServiceAccount -Name gmsa-sql -DNSHostName gmsa-sql.corp.example.com `
    -PrincipalsAllowedToRetrieveManagedPassword 'SQL-Servers' `
    -KerberosEncryptionType AES128,AES256

# Move the SPN: delete it from the old account, then add it with a duplicate check
setspn -D MSSQLSvc/sql01.corp.example.com:1433 CORPsvc-sql
setspn -S MSSQLSvc/sql01.corp.example.com:1433 CORPgmsa-sql$

# On each host that runs the service
Install-ADServiceAccount -Identity gmsa-sql
Test-ADServiceAccount -Identity gmsa-sql

Then set the service’s logon account to CORPgmsa-sql$ with an empty password. Microsoft documents gMSA support for Service Control Manager services, IIS application pools and scheduled tasks; failover clusters themselves do not support gMSAs.

If the account must keep its SPN

Take it out of privileged groups anyway. Until you can, restrict it to AES and reset the password to a random value of 25 or more characters. Microsoft notes the password must be changed after the encryption type change so AES keys exist:

Set-ADUser svc-legacy -KerberosEncryptionType AES128,AES256
Set-ADAccountPassword svc-legacy -Reset -NewPassword (Read-Host -AsSecureString 'New password')

Rotate it on a schedule. This lowers the risk, but it will not clear the Nessus finding, which looks only at the SPN on a privileged account.

How to verify the fix and rescan

  1. Re-run both queries. The recursive-membership query should return nothing.
  2. For accounts moved to AES, request a ticket from a client with klist get MSSQLSvc/sql01.corp.example.com:1433, then run klist: the KerbTicket Encryption Type should read AES-256-CTS-HMAC-SHA1-96. On DCs, event 4769 (Audit Kerberos Service Ticket Operations) should show Ticket Encryption Type 0x12 or 0x11; 0x17 means RC4.
  3. Test the application itself, including anything that uses delegation.
  4. Rescan: rerun the Nessus AD Starter Scan with the same LDAP credentials, run PingCastle.exe –healthcheck –server corp.example.com, and confirm the deviance closes in Tenable Identity Exposure.

What can break and how to roll back

  • Deleting an SPN a service still uses. Clients can no longer get a Kerberos ticket for it and either fall back to NTLM (where allowed) or fail; delegation stops. Roll back with setspn -S <spn> <account>.
  • Removing admin group membership. Backup jobs and scripts that quietly relied on Domain Admin rights fail. Re-add the account temporarily with Add-ADGroupMember while you grant the specific rights.
  • AES only. Appliances, Java applications or Linux keytabs that only handle RC4 stop authenticating. Roll back with Set-ADUser svc-legacy -KerberosEncryptionType RC4,AES128,AES256, or clear the attribute with Set-ADUser svc-legacy -Clear ‘msDS-SupportedEncryptionTypes’.
  • Password reset. Every stored copy breaks: service logons, scheduled tasks, app pools, connection strings, keytabs. A password cannot be rolled back, so inventory those places first.
  • gMSA cutover. If Test-ADServiceAccount fails, the host is not allowed to retrieve the password (a newly added computer may need a reboot to pick up its group membership). Keep the old account disabled, not deleted, until the service has run cleanly for a while.

Common false positive reasons

  • Disabled accounts in Nessus output. They appear only when thorough tests are enabled. Low risk today, but anyone who re-enables the account restores the exposure; delete it or strip the SPN.
  • Scanners disagree. PingCastle ignores accounts whose password changed in the last 40 days and accounts listed as honeypots; Nessus has no such exclusion. An account in one report and not the other is expected.
  • Large domains. Above 5,000 users, groups or machines, Tenable says the AD Starter Scan returns incomplete results, so a clean Nessus report is not proof.
  • Your own query, not the scanner. Stale adminCount values and krbtgt show up in the quick query; scanners work from group membership.
  • Not a false positive: nesting. “He is not a Domain Admin” often means the account sits in a group nested into Administrators. That is still privileged.

FAQ

Does enforcing AES stop Kerberoasting?

No. AES tickets can still be requested and attacked offline; they are just slower to crack than RC4. Password length and randomness are what actually protect the account.

Should I remove SPNs from every service account?

No. This finding covers privileged accounts. Unprivileged SPN accounts can be Kerberoasted too, so audit them, remove SPNs nobody uses, and give the rest gMSAs or long random passwords.

Why did PingCastle stop reporting an account I only reset?

Its rule skips accounts whose password changed in the last 40 days, treating rotation as a mitigation. If you do not keep rotating, the finding returns.

How long before a new gMSA works?

Domain controllers wait up to 10 hours after the KDS root key is created before allowing gMSA creation, so create the key well before the change window. This fits naturally into a broader Windows Server hardening checklist.

Tracking this finding across many hosts

If you track results in SITEY, you can import the .nessus export from the AD Starter Scan, let AI triage suggest false positives with evidence for a human to decide, and re-test the individual Nessus finding once the account is fixed. Duplicates are merged per scanner, not across scanners, so the same account reported by two tools shows up once for each.

Sources

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing