On recent pentests, I’ve been attempting to leverage unconstrained Kerberos delegation and stolen Kerberos tickets more. This is one of those privilege escalation methods that can fly under the radar - you might not need it to get the job done, but under the right conditions it might provide exactly what you’re looking for. One of the things I found most confusing when starting with stolen TGTs (ticket-granting-tickets) was the different formats you can prepare the tickets in for usage with various offensive tools. This post will cover how you can use tickets snatched with Rubeus with different tools like Impacket, CrackMapExec, Mimikatz and Rubeus itself.
Note: If you’re looking for Kerberos delegation background or attack scenarios, this is probably the most helpful post I found.
Stealing a Ticket
First off, we need to obtain a ticket before we can play around with formatting. In the test lab, I’ve got a Windows 10 system configured for unconstrained Kerberos delegation:
Assuming that we’ve already compromised an account with local admin rights to the target, I’ll use Rubeus to extract tickets from memory. This can be done with the monitor
command:
Rubeus.exe monitor /interval:1
It may be sufficent to just wait and see what privileged or high-interest users/computers authenticate to our compromised host, or it may be possible to force a sensitive system to authenticate through the printerbug. In this case, I’ve just waited until a domain admin, vizimir
, has logged in and pulled their TGT:
Now that we’ve got a ticket, we can explore the various tools that can utilize them and the various ticket formats.
Rubeus (base64 or .kirbi)
We’ll start with the easiest one. Rubeus can import a TGT to the current logon session from either a base64
string or a .kirbi
file. We’ll stick with base64 since it’s the most straightforward and also the format in which Rubeus initally presents the ticket to us.
Before we start, let’s verify that our current logon session (as REDANIA\dijkstra
) can’t access C$ on the domain controller:
Great, so if we successfully import a Domain Admin’s TGT to our session, we should then be able list folders on the DC.
This is pretty simple with Rubues - all we have to do is supply the base64 ticket to the ptt
command:
Rubeus.exe ptt /ticket:<base64 blob>
We can then use the klist
command to verify the ticket has been imported to our session:
Rubeus.exe klist
And there we can see the ticket for vizimir
successfully imported to our session. Now if we try accessing C$ on the domain controller again, we see it’s successful!
This is a simple test of the new privileges, but we could also use tools like PsExec to remotely execute commands now.
One thing to note with utilizing Kerberos authentication is that Kerberos relies on domain names and DNS entries. If we rerun the dir
command and target a host by IP address, NTLM authentication will be used and we’ll be back at access denied:
Mimikatz (.kirbi)
Mimikatz can import Kerberos tickets to the current session in the form of .kirbi
files. Before starting, we’ll again verify we don’t have rights on the domain controller:
We can use a PowerShell oneliner to write the base64 ticket grabbed with Rubeus out to a file:
[IO.File]::WriteAllBytes("C:\output.kirbi", [Convert]::FromBase64String("<base64 blob>"))
Boot up Mimikatz and import the ticket:
kerberos::ptt <path to kirbi file>
To test if it worked, we’ll start a new command prompt with misc::cmd
and verify we can access the DC:
W00t! While we’re here in Mimikatz, we should also be able to perform a dcsync attack:
Impacket and CrackMapExec (.ccache)
This is by far my preferred method for using a stolen ticket, but it’s also the one with the most formatting steps. We need to get the base64 ticket into a .ccache
file. We can do this by converting from a .kirbi
file, using Impacket’s ticketConverter.py
.
First, format the base64 ticket to remove line breaks, spaces, etc. and then decode it with the base64
command, writing the output to a kirbi file:
base64 -d <base64 ticket file> > <output .kirbi>
Convert to .ccache
using Impacket:
python3 ticketConverter.py <input kirbi file> <output ccache file>
Now that the ticket is in the right format, we’re almost ready to use it. We just need to export the KRB5CCNAME
variable and set it to the path of our .ccache
file:
export KRB5CCNAME=/path/to/ticket.ccache
Setup complete! Impacket and CrackMapExec have a -k
flag specifying to use Kerberos authentication. This will draw from the KRB5CCNAME
variable we set. Let’s verify we can access the DC:
Again, be careful to use DNS names since using IP addresses will fail: