Site icon Windows Active Directory

Identifying unsecure SPN configurations

Identifying Insecure SPN Configurations in Active Directory (Detection + Fix Runbook)

Service Principal Names (SPNs) are a core part of how Kerberos knows which service you’re trying to reach and which account should decrypt the service ticket. That also makes SPNs a high-signal control point for both security and reliability: weak service-account hygiene, legacy encryption, and sloppy delegation settings often show up here first.

SPNs in 2 minutes

In Kerberos, a client requests a service ticket for something like MSSQL, HTTP, CIFS, or a custom service. The Key Distribution Center (KDC) looks up the SPN in Active Directory to determine which security principal “owns” that service (a user account, computer account, or gMSA). The service ticket is encrypted so that only the owning account can decrypt it.

If your Kerberos foundations are rusty, it’s worth revisiting how tickets, TGS requests, and service authentication work: NTLM authentication and Kerberos Authentication Protocols Explained and User authentication and user authorization process: An explanation.

The key implication: an SPN effectively points at the account whose secret must protect that service. If that account’s secret is weak (old password, poor rotation, legacy crypto), your SPN becomes a “handle” attackers and auditors will both pull on.

What “insecure SPN configuration” actually means

“Insecure SPN” is rarely about the string itself. It’s usually about the security posture of the account attached to the SPN and the ways that account can be abused. Below are the patterns that matter most in real environments.

1) SPNs on user/service accounts with weak password hygiene (Kerberoast exposure)

  • Password never expires or “set-and-forget” service accounts.
  • Old password age (no rotation for months/years).
  • Human-managed service accounts where passwords are shared across teams.
  • Service accounts in high-privilege groups (Domain Admins, server local admins at scale, app “superusers”).

Why it’s risky: if an attacker can request service tickets, weak/offline-crackable secrets become a practical path to credential compromise. Your goal is to ensure SPNs are owned by strong, rotated, preferably managed identities (gMSA where possible), and never tied to Tier-0 privileges.

2) Duplicate SPNs (auth breaks + “confused deputy” risk)

Duplicate SPNs cause intermittent Kerberos failures and can push admins into unsafe “fixes” (like falling back to NTLM). Duplicates also create ambiguity: Kerberos relies on SPN uniqueness for clean service mapping.

3) Stale or over-broad SPNs (attack surface drift)

  • Services that were decommissioned, but the SPN remained.
  • SPNs registered on the wrong account (e.g., moved service, changed identity, or rebuilt server).
  • “Convenience” SPNs created during outages and never cleaned up.

4) Delegation misalignment (SPNs + delegation = powerful impersonation paths)

Delegation is where SPNs and identity trust intersect. If a computer/service is trusted for delegation broadly, it can request downstream services “on behalf of users,” which becomes a major escalation vector when mis-scoped. Review your delegation posture alongside SPNs: Active Directory Computer Delegation tab.

5) Legacy encryption settings (DES/RC4) on SPN-bearing accounts

If service accounts are constrained to older Kerberos encryption types, you’re effectively lowering the cryptographic bar that protects service tickets. Modern guidance generally prefers AES-based Kerberos where feasible and avoids legacy algorithms.

6) Excessive ability to write SPNs (rights problem, not a string problem)

The ability to create/modify SPNs can be abused to redirect authentication or enable stealthy persistence. Treat “who can write SPNs” as a privileged permission and keep it tightly delegated. If you’re designing delegation boundaries, this is directly related: Delegating OU permissions with minimal risk.

Inventory: find every SPN and baseline it

Option A: setspn (fast, built-in)

  • List SPNs on an account: setspn -L <accountName>
  • Search for a specific SPN: setspn -Q <serviceClass/host:port>
  • Find duplicates (high priority): setspn -X

Option B: PowerShell (audit-friendly, exportable)

Use the ActiveDirectory module to export SPNs and the account properties you’ll need for risk triage (password age, delegation flags, encryption types). The following commands are read-only and safe for audit runs.

Export all SPN-bearing users

Get-ADUser -LDAPFilter "(servicePrincipalName=*)" -Properties servicePrincipalName,PasswordLastSet,PasswordNeverExpires,Enabled,MemberOf,msDS-SupportedEncryptionTypes,AccountNotDelegated |
Select-Object SamAccountName,Enabled,PasswordLastSet,PasswordNeverExpires,AccountNotDelegated,msDS-SupportedEncryptionTypes,@{n="SPNCount";e={$_.ServicePrincipalName.Count}},ServicePrincipalName |
Export-Csv .\spn_users.csv -NoTypeInformation

Export all SPN-bearing computers (services often live here too)

Get-ADComputer -LDAPFilter "(servicePrincipalName=*)" -Properties servicePrincipalName,TrustedForDelegation,TrustedToAuthForDelegation,msDS-AllowedToDelegateTo |
Select-Object Name,TrustedForDelegation,TrustedToAuthForDelegation,@{n="SPNCount";e={$_.ServicePrincipalName.Count}},msDS-AllowedToDelegateTo,ServicePrincipalName |
Export-Csv .\spn_computers.csv -NoTypeInformation

Export gMSA SPNs (preferred for many services)

Get-ADServiceAccount -LDAPFilter "(servicePrincipalName=*)" -Properties servicePrincipalName,msDS-SupportedEncryptionTypes |
Select-Object Name,msDS-SupportedEncryptionTypes,@{n="SPNCount";e={$_.ServicePrincipalName.Count}},ServicePrincipalName |
Export-Csv .\spn_gmsa.csv -NoTypeInformation

High-value detections

Detection 1: Duplicate SPNs

Duplicates create downtime and security workarounds. Start here:

setspn -X

Follow up by querying the specific SPN and confirming which account is the correct owner:

setspn -Q <SPN_STRING>

Detection 2: SPNs on user accounts with risky password posture

This is the classic “service account that never changes” problem. Identify SPN-bearing users with old passwords and “never expires”:

$cutoff = (Get-Date).AddDays(-90)

Get-ADUser -LDAPFilter "(servicePrincipalName=*)" -Properties PasswordLastSet,PasswordNeverExpires,servicePrincipalName,Enabled |
Where-Object {
  $_.Enabled -eq $true -and (
    $_.PasswordNeverExpires -eq $true -or
    $_.PasswordLastSet -lt $cutoff -or
    -not $_.PasswordLastSet
  )
} |
Select-Object SamAccountName,Enabled,PasswordLastSet,PasswordNeverExpires,@{n="SPNCount";e={$_.ServicePrincipalName.Count}} |
Sort-Object PasswordLastSet |
Format-Table -AutoSize

Detection 3: SPN-bearing accounts that are privileged

Your rule of thumb: services should not run as Tier-0. Find SPN-bearing users that are members of well-known admin groups (customize group names to match your environment):

$adminGroups = @(
  "Domain Admins",
  "Enterprise Admins",
  "Administrators",
  "Schema Admins"
)

$adminDns = foreach ($g in $adminGroups) {
  (Get-ADGroup $g -ErrorAction SilentlyContinue).DistinguishedName
}

Get-ADUser -LDAPFilter "(servicePrincipalName=*)" -Properties MemberOf,servicePrincipalName |
Where-Object {
  $_.MemberOf | Where-Object { $adminDns -contains $_ }
} |
Select-Object SamAccountName,@{n="SPNCount";e={$_.ServicePrincipalName.Count}},MemberOf |
Format-List

Detection 4: Delegation risk where SPNs matter most

Focus on: unconstrained delegation (TrustedForDelegation) and protocol transition / constrained delegation (TrustedToAuthForDelegation and msDS-AllowedToDelegateTo). These settings can create “impersonation highways” if mis-scoped.

# Computers trusted for unconstrained delegation
Get-ADComputer -LDAPFilter "(userAccountControl:1.2.840.113556.1.4.803:=524288)" -Properties servicePrincipalName |
Select-Object Name,@{n="SPNCount";e={$_.ServicePrincipalName.Count}},servicePrincipalName |
Format-Table -AutoSize

Then review the delegation settings in the GUI (and what services are listed) using: Active Directory Computer Delegation tab.

Detection 5: Stale SPNs after service moves, DC changes, or hostname changes

Stale SPNs commonly appear after “fast fixes”: service account swaps, server renames, IP/role changes, or rebuilds. For domain controllers specifically, SPN registration health matters operationally; if you’re touching DC networking, validate SPNs during post-change checks: How to change the IP address of a domain controller.

Practical approach:

  • Identify SPNs whose host portion references decommissioned hostnames.
  • Confirm the service actually runs where the SPN claims it runs.
  • Remove or correct SPNs that no longer map to a real service endpoint.

Remediation playbook (fix without breaking production)

SPNs are authentication wiring. Changes can break apps. The safest approach is: confirm ownership → plan a maintenance window → change in small steps → validate.

Step 1: Confirm the “right” owner of the SPN

  • Which host/service is the SPN meant to represent?
  • Which identity does the service actually run as today?
  • Is that identity a computer account, gMSA, or user account?

Step 2: Prefer managed identities for services

  • Move from user-based service accounts to gMSA where possible (automatic password rotation, reduced operational risk).
  • Minimize privileges: only the rights the service needs, scoped to the resource.
  • Avoid “service account is local admin everywhere” as a pattern.

Step 3: Eliminate “password never expires” on SPN-bearing accounts

If you can’t migrate immediately, at least enforce rotation and strong password policies, and isolate those accounts in dedicated OUs with tight controls (including who can write SPNs).

Step 4: Reduce delegation blast radius

  • Remove unconstrained delegation unless there is a documented, tested requirement.
  • Prefer constrained delegation (and modern patterns like resource-based constrained delegation) with tight allow-lists.
  • Mark sensitive accounts as “not delegatable” where appropriate.

Step 5: Clean up duplicates and stale entries

Once you’ve identified the correct owner, remove the SPN from the wrong account and ensure it exists only once on the correct account. Validate with setspn -Q and application authentication tests.

Step 6: Validate after changes

  • Confirm the service can obtain and decrypt tickets.
  • Confirm clients authenticate via Kerberos (not silently falling back).
  • Document the SPN mapping and baseline it.

Monitoring & guardrails (stop drift)

1) Alert on SPN changes

A mature program treats SPN writes like privileged changes. Good options include:

  • Directory Service Changes auditing (captures attribute modifications like SPN updates when configured correctly).
  • SIEM rules: “servicePrincipalName changed” on user/computer objects, especially outside change windows.
  • Periodic diffing: export SPNs nightly and alert on deltas.

2) Watch for suspicious ticket volume patterns

Even if you can’t detect every technique directly, you can baseline normal service-ticket request rates and flag anomalies by service account (especially high-frequency requests to rarely used services).

3) Lock down who can write SPNs

Ensure SPN write permissions are granted only where necessary and are scoped properly. Delegation is a design discipline: Delegating OU permissions with minimal risk.

Quick checklist

  • Run setspn -X and resolve duplicates.
  • Export all SPN-bearing accounts (user/computer/gMSA) and baseline.
  • Flag SPN-bearing user accounts with old passwords / never-expire.
  • Ensure no SPN-bearing accounts are Tier-0 privileged.
  • Review delegation: remove unconstrained where possible; constrain everything else.
  • Prefer gMSA for services; document SPN ownership as “service-to-identity” contracts.
  • Turn on monitoring for SPN changes and alert on deltas.

Further reading (from Windows-Active-Directory.com)

Practical takeaway: Treat SPNs as “identity wiring.” If the owning account is weak, over-privileged, or overly delegatable, the service is weak. Your best wins usually come from (1) killing duplicates, (2) migrating to gMSA, (3) enforcing rotation, and (4) constraining delegation.

Exit mobile version