Silver and Golden Tickets for Pentesters

Why should I care about Kerberos?

As pentesters, we are used to using NTLM to authenticate to services in an Active Directory domain. NTLM authentication requires a username and password (or password hash) to authenticate. It's easy and it usually just works. Kerberos is another option for authenticating in Windows domains, but presents some annoyances to use, such as requiring the use of a hostname instead of IP address. So why would we want to use Kerberos over NTLM?

The real reason to use Kerberos is because some attacks are unique to Kerberos and cannot be done using NTLM. You already abuse Kerberos-only features every time you Kerberoast. In this blog post I try to cover the two biggest Kerberos abuses I think pentesters are sleeping on.

Kerberos for dummies

Let's do a really quick refresher on Kerberos. In the context of Active Directory, Kerberos is a more secure method of authentication intended to replace NTLM. Instead of using passwords (like NTLM) Kerberos uses tickets to authenticate to services. In the context of Kerberos, a service is just something that you can log into, like a file share or a SQL server.

There are two kinds of Kerberos tickets: TGT's (Ticket Granting Ticket) and Service Tickets (aka TGS's). Logging into a service using Kerberos is a 3 step process:

  1. A user uses their NTLM password to get a TGT from the DC.
  2. Then they use their TGT to get a Service Ticket from the DC.
  3. After that, they use the Service Ticket to authenticate to the desired service.
A step by step diagram of authenticating to a service using Kerberos
A step by step diagram of authenticating to a service using Kerberos

Lastly, a principal is just the Kerberos name for any Active Directory object. For this blog post, we really only care about user and computer objects as principles.

For the 100th time: What is an SPN?

SPN's represent a unique service available to be accessed via Kerberos on a network.

To quote the Microsoft documentation:

Service Principal Names (SPNs) are unique identifiers for services running on servers. Every service that will use Kerberos authentication needs to have an SPN set for it so that clients can identify the service on the network. If an SPN is not set for a service, then clients will have no way of locating that service. Without properly set SPNs, Kerberos authentication is not possible.

Usually an SPN is a service on a computer, like MSSQLSvc/sql01.domain.local. When a user requests a service ticket, the SPN for the requested service is included in the ticket. For more in depth about SPN's, read this great blog post.

I borrowed the following Powershell script which lets us see a list of all SPN's in Active Directory.

Running the script in my lab produces a long list with several SPN's per computer. Here's a snippet of just a few SPN's.

Viewing SPN's on two hosts in my AD lab environment
Viewing SPN's on two hosts in my AD lab environment

We can see a few service names:

  • WSMAN - Service name Windows Remoting (WinRM) and Powershell Remoting services.
  • TERMSRV - Service name for Microsoft Remote Desktop server (Terminal Server) services.
  • HOST - A catch-all service name for many services, including RPC, DCOM and WMI.

This resource lists additional possible Microsoft and 3rd party service names, such as MSSQLSvc, NFS, LDAP, JBoss, and Oracle.

The last thing we need to know about Kerberos to put this exploitation puzzle together: Kerberos tickets are encrypted using the NTLM hash of the service principle.

  • TGT's are encrypted with the special krbtgt hash.
  • Service Tickets are encrypted with the hash of the associated SPN, for example, a Service Ticket for the TERMSRV/WS01 SPN would be encrypted with the NTLM password hash of the WS01$ computer account.

For attackers, this means a few important things:

  1. If we have a Kerberos ticket, but don't know the password of the service, we can attempt to crack the plaintext password out of the ticket. This is what Kerberoasting is.
    • Note: passwords for computer accounts and the krbtgt account are randomly generated and extremely long, which means all TGT's and Service Tickets for SPN's with computers cannot be cracked.
  2. If we have the NTLM hash for a computer account, we can create a forged Service Ticket. Forged Service Tickets are called Silver Tickets.
    • Remember that Service Tickets are only good for a specific host and service! We must forge a Silver Ticket for each host we want to access.
  3. If we have the NTLM hash for the krbtgt account, we can create a forged TGT. Forged TGT's are called Golden Tickets.

Silver Tickets: Bring your own ticket

By creating our own Silver Ticket, we skip the steps in the standard Kerberos procedure of requesting a TGT and requesting a Service Ticket.

Authentication flow for using a silver ticket (forged Service Ticket) to access a resource
Authentication flow for using a silver ticket (forged Service Ticket) to access a resource

An important feature of a silver ticket is an attacker does not talk to the Domain Controller. This makes silver ticket usage rather hard to detect.

So when would we actually want to make a silver ticket? One of the most annoying things in a pentest is dumping a machine's local SAM hashes only to find out that local administrator logon is denied.

Attempting and failing to log in with a local account after dumping SAM hashes
Access DENIED: Failing to log in with a local account after dumping SAM hashes

This seems needlessly frustrating. I am local admin and I already dumped SAM. Just let me log in.

Let me in! :(
Let me in! :(

Fortunately we can use the computer account hash to generate a Silver Ticket, allowing us to impersonate any user for that specific computer. To reiterate, given only a machine NTLM hash, it is possible to become an Administrator (and gain code execution) on that machine.

It's possible to get a computer's NTLM in a few ways, such as a server backup in a share or reversing a captured NTLMv1 hash, but for demonstration purposes I'm just going to use CrackMapExec to dump it out of the LSA.

Grabbing the WS01$ computer account's NTLM hash from LSA

We will use the Impacket ticketer.py script to create our silver ticket. Before we do though, we need a list of the following items:

  1. SPN for the service we want to access
  2. Domain name
  3. Computer NTLM hash
  4. Domain Controller IP address
  5. Domain SID
  6. Domain User account to impersonate

Once we have all of those, we can create our silver ticket. Pasteable command below:

python3 ticketer.py -spn HOST/WS01.borgar.local -domain borgar.local -nthash 3c0ca92a8fa19374d19bf887543a5e19 -dc-ip 192.168.1.20 -domain-sid S-1-5-21-3010306422-4235424541-3945354764 Administrator

Creating our Silver Ticket with ticketer.py
Creating our Silver Ticket with ticketer.py

Our silver ticket file (Administrator.ccache) is saved, and we can start using it with tools supporting Kerberos authentication. Using the following command, we can tell Impacket (and other tools) to use our silver ticket for Kerberos authentication.

export KRB5CCNAME=Administrator.ccache

Viewing and exporting our newly created ccache silver ticket file
Viewing and exporting our newly created ccache silver ticket file

Once we have that set up we can use Impacket's wmiexec or smbexec to gain a shell on WS01. Use the -k option to specify Kerberos authentication, and the -no-pass option because we are not authenticating with a password.

Using the silver ticket to authenticate as Borgar.local/Administrator to WS01
Using the silver ticket to authenticate as Borgar.local/Administrator to WS01

Lastly, the most common mistake I make when dealing with Kerberos is defaulting to IP addresses. I'm so used to using IP addresses for NTLM sometimes I forget that Kerberos requires hostnames for all authentication. The screenshot below shows what happens if you accidentally use an IP address instead of a hostname. Learn from my mistakes. Don't use IP addresses when dealing with Kerberos!

Using an IP address instead of a hostname? Access DENIED!
Using an IP address instead of a hostname? Access DENIED!

Everything we just did but on Windows

Since during some engagements you may be limited to Windows hosts, I am going to show you how to create a Silver Ticket on Windows. Skip to the next section if you're dedicated to the #KaliLife.

Mimikatz supports creating and importing Kerberos tickets into our current session. Again, we are going to need the following items to create our Silver Ticket:

  1. Domain name
  2. Domain SID
  3. Computer NTLM hash
  4. User to impersonate
  5. User ID
  6. User's group ID's
  7. Kerberos Principle (target computer hostname)
  8. Kerberos Service

Despite the name, kerberos::golden is the Mimikatz command used to create Silver Tickets. Pasteable command is included below:

kerberos::golden /domain:borgar.local /sid:S-1-5-21-3010306422-4235424541-3945354764 /rc4:3c0ca92a8fa19374d19bf887543a5e19 /user:"Administrator" /id:500 /groups:500,501,513,512,520,518,519 /target:WS01.borgar.local /service:cifs /ptt

Creating a Silver Ticket for CIFS using the kerberos::golden Mimikatz command
Creating a Silver Ticket for CIFS using the kerberos::golden Mimikatz command

We use the CIFS service to easily verify our ticket worked properly. After creating the ticket and using /ptt to pass-the-ticket into our current session, we use misc::cmd to open another command prompt from Mimikatz. We can use the dir command on the C$ or ADMIN$ shares on WS01 to confirm we are indeed Administrator.

Confirming we can view the C$ share on WS01
Confirming we can view the C$ share on WS01

A second reminder that we still cannot use IP addresses to authenticate to hosts:

Getting access denied when using an IP address instead of the WS01 hostname
Getting access denied when using an IP address instead of the WS01 hostname

We can use legitimate remote access tool PsExec to gain a remote shell on WS01 with our Silver Ticket. Since PsExec requires connections to both MSRPC and SMB to gain execution, we need to create a second ticket for the HOST service. Just replace /service:cifs with /service:host.

Using kerberos::list we can see we have tickets for both CIFS and HOST services.

Viewing CIFS and HOST Kerberos tickets with kerberos::list
Viewing CIFS and HOST Kerberos tickets with kerberos::list

Only now can we use PsExec to log into WS01.

Using PsExec to log into WS01
Using PsExec to log into WS01

That's it! We're Administrator. 😎

Golden Ticket: Welcome back Batman

As we talked about earlier, a Golden Ticket is a forged TGT. This means we can use this forged TGT to request legitimate Service Tickets from Active Directory. The authentication flow is different from Silver Tickets since the Golden Ticket must be submitted to the Domain Controller every time a new service is accessed. After a Service Ticket is granted, authentication takes place as normal.

Authentication flow for a Golden Ticket: Submit forged TGT to DC and request Service Tickets
Authentication flow for a Golden Ticket: Submit forged TGT to DC and request Service Tickets

To create a Golden Ticket, we need the krbtgt NTLM hash, which almost always means we need Domain Admin privileges. We can use Secretsdump or CrackMapExec to download the domain secrets from a Domain Controller.

Using CrackMapExec to get the krbtgt hash
Using CrackMapExec to get the krbtgt hash

Once again, we can use the ticketer.py script in Impacket to forge a Golden Ticket.

We will need:

  1. Domain name
  2. NTLM hash for the krbtgt account
  3. Domain Controller IP address
  4. Domain SID
  5. Domain User account to impersonate

The user doesn't matter (only for the first 20 minutes), so I chose the non-existent user "batman". Pasteable command below:

ticketer.py -domain borgar.local -nthash 47d91aca4b29907d30251a0bfe9b189c -dc-ip 192.168.1.20 -domain-sid S-1-5-21-3010306422-4235424541-3945354764 Batman

Generating a Golden Ticket with Ticketer.py
Generating a Golden Ticket with Ticketer.py

Once we generate our Golden Ticket and export the ccache file as we did before, we can log in to any system in the domain.

Using the Golden Ticket and logging into WS01 as Batman!
Using the Golden Ticket and logging into WS01 as Batman!

Lastly, Golden and Silver Tickets generated by Mimikatz or ticketer.py have, by default, a 10 year lifetime. Silver tickets will expire naturally when the computer account password cycles (by default every 30 days), but the krbtgt account has no such password rotation policy, and Golden Tickets created with a lifetime of 10 years will be valid for 10 years unless the krbtgt account password is manually changed.

It is for this reason that pentesters should limit the lifetime of their Golden Tickets to a few days or weeks. Impacket's ticketer.py allows specifying shorter lifetime values with the -duration flag. Likewise, ticket duration can be limited in Mimikatz with the /endin flag. 

In addition, generated Golden or Silver Tickets should be treated with the same sensitivity as NTLM password hashes or passwords. Kerberos tickets should be securely stored and securely deleted when they are no longer needed.

Golden Ticket as privilege escalation

Golden Tickets aren't just for fun, though. Thanks to another wonderful Microsoft feature, we can use a Golden Ticket to go from domain compromise to complete forest compromise. This means if we own one domain in a forest, we can compromise all other parent and child domains in that forest.

Upon creation of a child domain in Active Directory, a two-way trust is created between the parent and child domains. This allows any object in the child domain to authenticate to resources in the parent domain. Additionally, since intra-domain trusts perform no SID filtering, we can forge a Golden Ticket that states we are part of the Enterprise Admins group. Yes, it actually is that simple.

Mimikatz lets us create a Golden Ticket with an extra SID for the Enterprise Admins group.

We will need:

  1. Child domain name
  2. Child domain SID
  3. Child domain krbtgt NTLM hash
  4. User to use (can be anything)
  5. User ID to use (can also be anything)
  6. Parent domain Enterprise Admins SID (Parent domain SID plus -519)

Pasteable Golden Ticket command with extra sids:

kerberos::golden /domain:child.borgar.local /sid:S-1-5-21-3676245630-1584519168-1098963459 /krbtgt:cf28a3d01502d7912dedc4500d5ac990 /user:batman /id:500 /ptt /sids:S-1-5-21-3010306422-4235424541-3945354764-519

Using Mimikatz to generate a Golden Ticket with the extra sid for Enterprise Admin
Using Mimikatz to generate a Golden Ticket with the extra SID for Enterprise Admin

After generating our Golden Ticket, we can DCSync any hash from the root-level Domain Controller.

Using DCSync to download the krbtgt NTLM hash for the parent domain
Using DCSync to download the krbtgt NTLM hash for the parent domain

This same privilege escalation technique can be performed as a one-shot using Impacket's raiseChild.py script.

Fully automated pentesting with raiseChild.py
Fully automated pentesting with raiseChild.py
Detecting forged Kerberos tickets

Silver and Golden ticket generation and usage are unfortunately extremely difficult to differentiate from legitimate Kerberos activity. Detections can be built around subtle discrepancies between how Active Directory creates tickets and how 3rd party tools create tickets or mismatches between SID's and usernames. We can see example of these discrepancies using Event Viewer to view login events on the DC.

A login event from a Golden Ticket with mismatched SID and username
A login event from a Golden Ticket with mismatched SID and username
A Golden Ticket login event (left) next to a legitimate Kerberos login event (right)
A Golden Ticket login event (left) next to a legitimate Kerberos login event (right)

The problem with these detections is they rely on an attacker making mistakes or using tools with non-standard behavior. Knowing that legitimate login events use the NETBIOS domain name (BORGAR) instead of the FQDN (BORGAR.local) an attacker only needs to change their ticket to use the NETBIOS name to evade such a detection.

Unfortunately it's not as simple as changing the ticketer.py command from -domain borgar.local to -domain BORGAR, but with a little bit change to the code, we can break the detection above.

Hardcoding the ticket's Account Domain into ticketer.py
Hardcoding the ticket's Account Domain into ticketer.py

After generating a new ticket and logging in, the login event using this Golden Ticket looks identical to a legitimate Kerberos login.

A login from a forged ticket after ticketer.py modification
A login from a forged ticket after ticketer.py modification
Remediation?

Unfortunately, since Golden Tickets are a post domain compromise technique, there is not much the Blue Team can do to clean up after an attacker obtains a Golden Ticket. As shown above, a Golden Ticket gives attackers complete and total access to the entire forest, leaving defenders with no choice but to rebuild Active Directory.

The unfortunate reality of a domain compromise
The unfortunate reality of a domain compromise

The end for now

I'm ending this blog post here since too much Kerberos hurts my brain, but maybe in a future post I will revisit our favorite three-headed dog.

In summary:

  • Silver Ticket: Gain code execution on any host that we have the computer account's NTLM hash.
  • Golden Ticket: Own an entire forest from just one compromised domain.
  • Detection: Weak detections for forged tickets can be built by looking for abnormal or inconsistent login events.

This article was updated on May 12, 2021