Skip to content
Closed
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
197 changes: 106 additions & 91 deletions docs/metasploit-framework.wiki/Hashes-and-Password-Cracking.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion documentation/modules/auxiliary/gather/kerberoast.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ $krb5tgs$23$*kerber.roastable$MSF.LOCAL$http/abc2.msf.local*$d335dc07b2c018de2a1
$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 -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
```
11 changes: 5 additions & 6 deletions lib/metasploit/framework/hashes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ module Framework
# http://pentestmonkey.net/cheat-sheet/john-the-ripper-hash-formats
# https://openwall.info/wiki/john/sample-hashes
# QNX formats -> https://moar.so/blog/qnx-password-hash-formats.html
# rubocop:disable Metrics/ModuleLength
module Hashes
JTR_NTLMV1 = 'netntlm'.freeze
JTR_NTLMV2 = 'netntlmv2'.freeze
Expand Down Expand Up @@ -67,9 +66,9 @@ def self.identify_hash(hash)
return 'nt'
when hash.length == 65 && hash =~ /^[\da-fA-F]{32}:[\da-fA-F]{32}$/
return 'lm'
when hash =~ /^[^\\\/:*?"<>|]{1,20}[:]{2,3}([^\\\/:*?"<>|]{1,20})?:[a-f0-9]{48}:[a-f0-9]{48}:[a-f0-9]{16}$/
when hash =~ %r{^[^\\/:*?"<>|]{1,20}:{2,3}([^\\/:*?"<>|]{1,20})?:[a-f0-9]{48}:[a-f0-9]{48}:[a-f0-9]{16}$}
return 'netntlm'
when hash =~ /^([^\\\/:*?"<>|]{1,20}\\)?[^\\\/:*?"<>|]{1,20}[:]{2,3}([^\\\/:*?"<>|]{1,20}:)?[^\\\/:*?"<>|]{1,20}:[a-f0-9]{32}:[a-f0-9]+$/
when hash =~ %r{^([^\\/:*?"<>|]{1,20}\\)?[^\\/:*?"<>|]{1,20}:{2,3}([^\\/:*?"<>|]{1,20}:)?[^\\/:*?"<>|]{1,20}:[a-f0-9]{32}:[a-f0-9]+$}
return 'netntlmv2'
# OSX
when hash.start_with?('$ml$') && hash.split('$').last.length == 256
Expand Down Expand Up @@ -124,18 +123,18 @@ def self.identify_hash(hash)
when hash =~ /^\*?[\da-fA-F]{32}\*[\da-fA-F]{32}$/
# we accept the beginning star as optional
return 'vnc'
when hash =~ /^\$pbkdf2-sha256\$[0-9]+\$[a-z0-9\/.]+\$[a-z0-9\/.]{43}$/i
when hash =~ %r{^\$pbkdf2-sha256\$[0-9]+\$[a-z0-9/.]+\$[a-z0-9/.]{43}$}i
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'
return 'krb5tgs'
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'
return 'krb5asrep' # hashcat is krb5asrep-rc4, but we use john format
end
''
end
Expand Down
16 changes: 13 additions & 3 deletions lib/metasploit/framework/password_crackers/cracker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ def initialize(attributes = {})
public_send("#{attribute}=", value)
end
end

def get_type
self.cracker
cracker
end

# This method takes a {framework.db.cred.private.jtr_format} (string), and
Expand Down Expand Up @@ -157,6 +157,16 @@ def jtr_format_to_hashcat_format(format)
'5500'
when 'netntlmv2'
'5600'
when 'krb5tgs'
'13100'
when 'krb5tgs-aes128'
'19600'
when 'krb5tgs-aes256'
'19700'
when 'krb5asrep'
'18200'
when 'timeroast'
'31300'
# dbs
when 'mssql'
'131'
Expand Down Expand Up @@ -576,7 +586,7 @@ def show_command
end
cmd << hash_path
end

def get_hashcat
# Look in the Environment PATH for the hashcat binary
self.cracker = 'hashcat'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ def add_equals_to_base64(str)
# https://hashcat.net/forum/thread-8833.html
# while we can do the transformation, we'd have to throw extra flags at hashcat which aren't currently written into the lib for automation
nil
when /^krb5$/
return "#{cred.id}:#{cred.private.data}"
# when /^krb5$/
# return "#{cred.id}:#{cred.private.data}"
when /^(krb5.|timeroast$)/
return cred.private.data
# krb5tgs, krb5tgs-aes128, krb5tgs-aes256, krb5asrep, timeroast
## hash-mode: 13100 19600 19700 18200 31300
return "#{cred.id}:#{cred.private.data}"
end
end
nil
Expand Down
5 changes: 4 additions & 1 deletion lib/metasploit/framework/password_crackers/jtr/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ def self.params_to_jtr(username, private_data, private_type, format: nil, db_id:
# for this we overload the username field with the db_id so we can find it in the db easier later
# https://github.com/openwall/john/issues/5944
private_data = private_data.split('$')
private_data[5] = private_data[5].split(':').first
# remove port if there is one
if private_data[5].include?(':')
private_data[5] = private_data[5].split(':').first + '*'
end
private_data = private_data.join('$')
return "#{db_id}:#{private_data}"
when /^(krb5.|timeroast$)/
Expand Down
5 changes: 4 additions & 1 deletion lib/msf/ui/console/command_dispatcher/creds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,12 @@ def filter_cred_cores(cores, opts, origin_ranges, host_ranges)
# Some creds may have been cracked that exist outside of the filtered cores list, let's resolve them all to show the cracked value
cores_by_id = cores.each_with_object({}) { |core, hash| hash[core.id] = core }
# Map of any originating core ids that have been cracked; The value is cracked core value
# Note: Multiple cracked cores may exist for the same originating core (e.g., same hash cracked via different methods)
# We only need one cracked core per originating core for display purposes, so we keep the first one found
cracked_core_id_to_cracked_value = cores.each_with_object({}) do |core, hash|
next unless core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword)
hash[core.origin.metasploit_credential_core_id] = core
originating_core_id = core.origin.metasploit_credential_core_id
hash[originating_core_id] ||= core # Only set if not already present
end

cores.each do |core|
Expand Down
25 changes: 22 additions & 3 deletions modules/auxiliary/analyze/crack_windows.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ def initialize
MSCASH2 is format 2100 in hashcat.
NetNTLM is format 5500 in hashcat.
NetNTLMv2 is format 5600 in hashcat.
krb5tgs is format 13100 in hashcat.
krb5tgs-aes128 is format 19600 in hashcat.
krb5tgs-aes256 is format 19700 in hashcat.
krb5asrep is format 18200 in hashcat.
timeroast is format 31300 in hashcat.
),
'Author' => [
'theLightCosine',
Expand Down Expand Up @@ -50,6 +55,7 @@ def initialize
OptBool.new('MSCASH', [false, 'Crack M$ CASH hashes (1 and 2)', true]),
OptBool.new('NETNTLM', [false, 'Crack NetNTLM', true]),
OptBool.new('NETNTLMV2', [false, 'Crack NetNTLMv2', true]),
OptBool.new('KERBEROS', [false, 'Crack krb5/timeroast related hashes', true]),
OptBool.new('INCREMENTAL', [false, 'Run in incremental mode', true]),
OptBool.new('WORDLIST', [false, 'Run in wordlist mode', true]),
OptBool.new('NORMAL', [false, 'Run in normal mode (John the Ripper only)', true])
Expand Down Expand Up @@ -108,17 +114,23 @@ def check_results(passwords, results, hash_type, method)
cred = { 'hash_type' => hash_type, 'method' => method }
if @cracker_type == 'john'
# If we don't have an expected minimum number of fields, this is probably not a hash line
next unless fields.count > 2
next unless fields.count >= 2 # krb5asrep and similar kerberoast fields have 2 fields only

cred['username'] = fields.shift
cred['core_id'] = fields.pop
case hash_type
when 'krb5asrep', 'krb5tgs'
cred['core_id'] = fields.shift
cred['password'] = fields.pop
when 'mscash', 'mscash2', 'netntlm', 'netntlmv2'
cred['username'] = fields.shift
cred['core_id'] = fields.pop
cred['password'] = fields.shift
when 'lm', 'nt'
# If we don't have an expected minimum number of fields, this is probably not a NTLM hash
next unless fields.count >= 6

cred['username'] = fields.shift
cred['core_id'] = fields.pop

2.times { fields.pop } # Get rid of extra :
nt_hash = fields.pop
fields.pop
Expand Down Expand Up @@ -148,6 +160,8 @@ def check_results(passwords, results, hash_type, method)
if ['netntlm', 'netntlmv2'].include? hash_type
# we could grab the username here, but no need since we grab it later based on core_id, which is safer
6.times { fields.shift } # Get rid of a bunch of extra fields
elsif ['krb5tgs', 'krb5asrep'].include? hash_type
2.times { fields.shift } # Get rid of extra hash fields
else
cred['hash'] = fields.shift
end
Expand Down Expand Up @@ -182,6 +196,11 @@ def run
hash_types_to_crack << 'mscash2' if datastore['MSCASH']
hash_types_to_crack << 'netntlm' if datastore['NETNTLM']
hash_types_to_crack << 'netntlmv2' if datastore['NETNTLMV2']
hash_types_to_crack << 'krb5tgs' if datastore['KERBEROS']
hash_types_to_crack << 'krb5tgs-aes128' if datastore['KERBEROS']
hash_types_to_crack << 'krb5tgs-aes256' if datastore['KERBEROS']
hash_types_to_crack << 'krb5asrep' if datastore['KERBEROS']
hash_types_to_crack << 'timeroast' if datastore['KERBEROS']

jobs_to_do = []

Expand Down
43 changes: 43 additions & 0 deletions spec/lib/metasploit/framework/hashes/identify_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,49 @@
end
end

describe 'identify_krb5tgs_hashcat_format' do
it 'returns krb5tgs' do
hash = described_class.identify_hash('$krb5tgs$23$*svc_test$MSFLAB.LOCAL$MSSQLSvc/sql01.msflab.local:1433*$cd5188391bf0e980a2cc48fddfcdb6c9$838309d0fe47fe1452faa663a378b37b5b69a170ee564ef4197f7f7ac918923e39dc0fe17b3beb9a963af47929d506d9d798fefb6038fe6447401cf23212a27aca5f05b8248aed48190d4b6b41405e796a960cc8c02bacb5c5e9869226e039f2581d98cd4d0defe15fd131d48a38ce95d69e28d8ae5f5fcfd371bdab8a68cd044c71a1b1cd46a0fb35eea7043bc7c3703186a9a0dcf6e8b688fdde20603de5daa7d428cf2923c0ba59a12c855ba396e080055e6d340231ba4822db632d12ba19eec436815fc28c88d8852601d58217019566c7c601ed37bb96920bbef4bf357b8e73549dbb70a5f4c53609c008e55d093b409572699b86fc8bd8cc395d6ec2de5fb2f64c56b7f6dd85ab89094883df99f3fd24db442b6da46c8998b3a5bd407fcb6fb2b65faded0b37034b54fa398d604c7030f52db4826ba09698a9a56a2f57a93f5299033cdcd641b4678926df5d8730b6b923c663fa2f9f2fa5f225a4108380f2b7bb9d75620478d1b912949a346bf19688877fcdf92231387b4c1d9ae83420abd38215802859c535205f8673125e0a559aa646663f4e41e97e5339be48972cafb501d01d3ec0f13bcc578b431b74eb285084d167d307ef5b5e2a2fa7cae7b221a6f5a0ce6a45883e6ccbdedcec7cfbc1dec3cad4b53d2db01750e087906747f3e5ed6d3e776a8844f578ff2072325d3d8122fd08342a18d5a637275aa1c534a78e9f798eb61dc2ca4a3cab0ea5b20bf67739763298cee85cc51443ba4faaf069593639fd474c69f31a5f6f29eb1ef20692091eb9eed5aa729dc84af1dde99ccbc978f2334fb1906d224101c425e088d98608ea05b7d4dccdee207d5a3e672829f35e3be751e2b395002619a6e0863e41b10efc321f2ae57fed86b5ed90b5a641e6d3488335ea4e8d8bea397ce35fa0113cf05b4c0c38ee0140d4be3bd490b461dc4fb41b4fc2c50bee160d379934f4043fec940f1549aee56543f7ba6c9c309805fe7397374bed469f1e1dabb6cdad02c9f663b17c64e6bb5a248f1389c2032b15e96d46172526329c29acf04ff537049420efc71aba58f29bac5b6a09522aa893d97ca59de9cc6d13789617859c0db170443e943e58ec7604745e475d1b16057aa8975b0b668fffc9a32f8b26452fa4a95129c53f8cf9a0191898dd8694ad9f0e106d7866b3e3116f92c2921e6ed6fc03a12a2aed56d73d6f9eee8eccad27839f55aef53942c2d7efc0e765621ba72d2280c21df512628011a56fc1aae3a6e62dc87cdd0a4c0c5a179b8ae233ce785293e7eca0b76a6418b0cf798be1eaf7a33f220dbdbb5166a529f129582b5a57b01b90c5c7c48b4d7c8e8aac1677704af319bd73816bbfa344cb10f070426746f162a4fc5809a5c37d566c45043b77e53e6cfb703e511ec1e6d14200d9b859fad51fb93b2477b61435ddcbea97ebf7c4b3dacbec3f8158c5c1d317887b7233199d20d7536febb8dd255aab')
expect(hash).to match('krb5tgs')
end
end

describe 'identify_krb5tgs_john_format' do
it 'returns krb5tgs' do
# https://github.com/openwall/john/issues/5944#issuecomment-3772129757
hash = described_class.identify_hash('$krb5tgs$23$*svc_test$MSFLAB.LOCAL$MSSQLSvc/sql01.msflab.local*$cd5188391bf0e980a2cc48fddfcdb6c9$838309d0fe47fe1452faa663a378b37b5b69a170ee564ef4197f7f7ac918923e39dc0fe17b3beb9a963af47929d506d9d798fefb6038fe6447401cf23212a27aca5f05b8248aed48190d4b6b41405e796a960cc8c02bacb5c5e9869226e039f2581d98cd4d0defe15fd131d48a38ce95d69e28d8ae5f5fcfd371bdab8a68cd044c71a1b1cd46a0fb35eea7043bc7c3703186a9a0dcf6e8b688fdde20603de5daa7d428cf2923c0ba59a12c855ba396e080055e6d340231ba4822db632d12ba19eec436815fc28c88d8852601d58217019566c7c601ed37bb96920bbef4bf357b8e73549dbb70a5f4c53609c008e55d093b409572699b86fc8bd8cc395d6ec2de5fb2f64c56b7f6dd85ab89094883df99f3fd24db442b6da46c8998b3a5bd407fcb6fb2b65faded0b37034b54fa398d604c7030f52db4826ba09698a9a56a2f57a93f5299033cdcd641b4678926df5d8730b6b923c663fa2f9f2fa5f225a4108380f2b7bb9d75620478d1b912949a346bf19688877fcdf92231387b4c1d9ae83420abd38215802859c535205f8673125e0a559aa646663f4e41e97e5339be48972cafb501d01d3ec0f13bcc578b431b74eb285084d167d307ef5b5e2a2fa7cae7b221a6f5a0ce6a45883e6ccbdedcec7cfbc1dec3cad4b53d2db01750e087906747f3e5ed6d3e776a8844f578ff2072325d3d8122fd08342a18d5a637275aa1c534a78e9f798eb61dc2ca4a3cab0ea5b20bf67739763298cee85cc51443ba4faaf069593639fd474c69f31a5f6f29eb1ef20692091eb9eed5aa729dc84af1dde99ccbc978f2334fb1906d224101c425e088d98608ea05b7d4dccdee207d5a3e672829f35e3be751e2b395002619a6e0863e41b10efc321f2ae57fed86b5ed90b5a641e6d3488335ea4e8d8bea397ce35fa0113cf05b4c0c38ee0140d4be3bd490b461dc4fb41b4fc2c50bee160d379934f4043fec940f1549aee56543f7ba6c9c309805fe7397374bed469f1e1dabb6cdad02c9f663b17c64e6bb5a248f1389c2032b15e96d46172526329c29acf04ff537049420efc71aba58f29bac5b6a09522aa893d97ca59de9cc6d13789617859c0db170443e943e58ec7604745e475d1b16057aa8975b0b668fffc9a32f8b26452fa4a95129c53f8cf9a0191898dd8694ad9f0e106d7866b3e3116f92c2921e6ed6fc03a12a2aed56d73d6f9eee8eccad27839f55aef53942c2d7efc0e765621ba72d2280c21df512628011a56fc1aae3a6e62dc87cdd0a4c0c5a179b8ae233ce785293e7eca0b76a6418b0cf798be1eaf7a33f220dbdbb5166a529f129582b5a57b01b90c5c7c48b4d7c8e8aac1677704af319bd73816bbfa344cb10f070426746f162a4fc5809a5c37d566c45043b77e53e6cfb703e511ec1e6d14200d9b859fad51fb93b2477b61435ddcbea97ebf7c4b3dacbec3f8158c5c1d317887b7233199d20d7536febb8dd255aab')
expect(hash).to match('krb5tgs')
end
end

describe 'identify_krb5tgs-aes128' do
it 'returns krb5tgs-aes128' do
hash = described_class.identify_hash('$krb5tgs$17$user$realm$ae8434177efd09be5bc2eff8$90b4ce5b266821adc26c64f71958a475cf9348fce65096190be04f8430c4e0d554c86dd7ad29c275f9e8f15d2dab4565a3d6e21e449dc2f88e52ea0402c7170ba74f4af037c5d7f8db6d53018a564ab590fc23aa1134788bcc4a55f69ec13c0a083291a96b41bffb978f5a160b7edc828382d11aacd89b5a1bfa710b0e591b190bff9062eace4d26187777db358e70efd26df9c9312dbeef20b1ee0d823d4e71b8f1d00d91ea017459c27c32dc20e451ea6278be63cdd512ce656357c942b95438228e')
expect(hash).to match('krb5tgs-aes128')
end
end

describe 'identify_krb5tgs-aes256' do
it 'returns krb5tgs-aes256' do
hash = described_class.identify_hash('$krb5tgs$18$user$realm$8efd91bb01cc69dd07e46009$7352410d6aafd72c64972a66058b02aa1c28ac580ba41137d5a170467f06f17faf5dfb3f95ecf4fad74821fdc7e63a3195573f45f962f86942cb24255e544ad8d05178d560f683a3f59ce94e82c8e724a3af0160be549b472dd83e6b80733ad349973885e9082617294c6cbbea92349671883eaf068d7f5dcfc0405d97fda27435082b82b24f3be27f06c19354bf32066933312c770424eb6143674756243c1bde78ee3294792dcc49008a1b54f32ec5d5695f899946d42a67ce2fb1c227cb1d2004c0')
expect(hash).to match('krb5tgs-aes256')
end
end

describe 'identify_krb5asrep' do
it 'returns krb5asrep' do
hash = described_class.identify_hash('$krb5asrep$23$user@domain.com:3e156ada591263b8aab0965f5aebd837$007497cb51b6c8116d6407a782ea0e1c5402b17db7afa6b05a6d30ed164a9933c754d720e279c6c573679bd27128fe77e5fea1f72334c1193c8ff0b370fadc6368bf2d49bbfdba4c5dccab95e8c8ebfdc75f438a0797dbfb2f8a1a5f4c423f9bfc1fea483342a11bd56a216f4d5158ccc4b224b52894fadfba3957dfe4b6b8f5f9f9fe422811a314768673e0c924340b8ccb84775ce9defaa3baa0910b676ad0036d13032b0dd94e3b13903cc738a7b6d00b0b3c210d1f972a6c7cae9bd3c959acf7565be528fc179118f28c679f6deeee1456f0781eb8154e18e49cb27b64bf74cd7112a0ebae2102ac')
expect(hash).to match('krb5asrep')
end
end

describe 'identify_timeroast' do
it 'returns timeroast' do
hash = described_class.identify_hash('$sntp-ms$cfc7023381cf6bb474cdcbeb0a67bdb3$907733697536811342962140955567108526489624716566696971338784438986103976327367763739445744705380')
expect(hash).to match('timeroast')
end
end

describe 'identify_vnc' do
it 'returns vnc' do
hash = described_class.identify_hash('*00112233445566778899aabbccddeeff*6feb3cb1f07b66151656b5832341f223')
Expand Down
Loading
Loading