Active Directory Pentest Recon Part 1: SPN Scanning aka Mining Kerberos Service Principal Names

I wrote a lengthy post on Kerberos earlier which describes the Kerberos protocol as well as how Active Directory leverages Kerberos.

There are several interesting Active Directory components useful to the pentester. The one I cover here relates to how Kerberos works, specifically Service Principal Names. As I mentioned in my Kerberos post, Service Principal Names (aka SPNs) are effectively the sign posts of Kerberos pointing users where to go to connect to resources. I won’t deal with Kerberos in depth here, but will recap.

Kerberos in a nutshell:

  1. When a user logs on to Active Directory, the user authenticates to the Domain Controller (DC) using the user’s password which of course the DC knows.
  2. The DC sends the user a Ticket Granting Ticket (TGT) Kerberos ticket. The TGT is presented to any DC to prove authentication for Kerberos service tickets.
  3. The user opens up Outlook which causes the user’s workstation to lookup the Service Principal Name (SPN) for the user’s Exchange server.
  4. Once the SPN is identified, the computer communicates with a DC again and presents the user’s TGT as well as the SPN for the resource to which the user needs to communicate.
  5. The DC replies with the Ticket Granting Service (TGS) Kerberos service ticket.
  6. The user’s workstation presents the TGS to the Exchange server for access.
  7. Outlook connects successfully.

Obviously this is an over-simplification, but explains why the SPN is important.
The key take-away here is that every service that is enabled for Kerberos authentication must have a SPN.

You may be thinking: “Ok, got it. So, what’s the point?”

This is where things get interesting.

Since every server needs to register SPNs for Kerberos authenticated services, this provides a perfect method for gathering information about an environment without port-scanning.

For example:

  • An administrator installs and configures Microsoft SQL Server on a server called “MetcorpKCS17” with a SQL instance listening on port 3170 3 & 3171.

The SPNs created by this action look like this:

The part in blue is the service component followed by a slash, the part in orange is the computer’s FQDN followed by a colon, and the last part in green is the network port number (or instance or some other unique identifier for this service on the server). Interestingly enough, the number at the end doesn’t have to be the port the service is listening on the server since Kerberos matches the SPN request to an existing SPN in the directory. With that stated, most of the time with few exceptions (as in practically none), the port noted in the SPN is the listening port on the server. Not all SPNs include a port.

Historically identifying that SQL is running on this server would either require a port scan of all ports on each server to find the non-standard ports or perform a “SQL ping” to UDP 1434 which would respond with the SQL instances and ports as well as the SQL version(s). Port scans on an internal network are typically noisy and the “SQL ping” approach to server profiling is usually flagged by IDS/IPS.

Now we have a better method for discovering SQL servers in an Active Directory domain or forest: perform a search of AD for ServicePrincipalName=MSSQL*
I used this method over the past couple of years for helping customers identify SQL servers in their environment to secure or decomission (saving licensing money).

While doing research on the different SPN types in Active Directory environments, I found there wasn’t much information on different SPNs and what they are used for – at least not in one place. So, I added created a Service Principal Name reference page listing all of the SPNs I have discovered.

There are several interesting services that leverage SPNs for Kerberos Auth which can be discovered with simple AD searches:

  • exchange*
  • http
  • ldap
  • nfs
  • *sql*
  • wsman

Interestingly enough, SPNs are queried almost constantly in an Active Directory environment all the time as clients request access to services. Furthermore, since the servicePrincipalName attribute is indexed in Active Directory, the results are usually returned in under a second.

Here’s the PowerShell (v2) code for discovering all SQL servers in the Active Directory forest:

ADForestInfoRootDomain = ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()).RootDomain

$ADForestInfoRootDomainDN = “DC=” + $ADForestInfoRootDomain -Replace(“\.”,’,DC=’)

$ADDomainInfoLGCDN = ‘GC://’ + $ADForestInfoRootDomainDN

$root = [ADSI]$ADDomainInfoLGCDN

$ADSPNSearcher = new-Object System.DirectoryServices.DirectorySearcher($root,”(serviceprincipalname=*sql*)”)

$ADSPNSearcher.PageSize = 500

$AllADSQLServerSPNs = $ADSPNSearcher.FindAll()


Note: This PowerShell code can be run as a standard AD user.
Change the bolded text to change the service type.

In order to simplify the identification of SQL servers and Exchange Servers (and others) in your Active Directory environment, I wrote PowerShell functions supporting this. These are available in GitHub:

There’s a ton more information on what Service Principal Names are, and what they do, etc can be found on the TechNet Wiki.


(Visited 25,970 times, 3 visits today)