Files
metasploit-gs/lib/metasploit/framework/hashes.rb
T
Matthew Dunn 1e50ba3415 Move to Hashes module, address requested changes
Fix rubocop

Move identify to hashes module up one layer, use full reference to identify_hash instead of full include

Fix SMTP require

Remove hashes require statement

Remove hashes require statement

Remove hashes require statement

Remove hashes require statement

Address remaining requested changes, reference constants directly

Add all the missing direct references

Co-Authored-By: Jeffrey Martin <jeffrey_martin@rapid7.com>
2022-10-17 17:28:31 -04:00

130 lines
5.7 KiB
Ruby

module Metasploit
module Framework
# This module contains utilities for hashes, including one to identify them
# Resource list:
# https://code.google.com/archive/p/hash-identifier/
# https://github.com/psypanda/hashID
# https://hashcat.net/wiki/doku.php?id=example_hashes
# 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
def self.identify_hash(hash)
# @param [str] a string of a hashed password
# @return [String] the jtr type or empty string on no match
hash = hash.to_s.strip
case
# operating systems
when hash.start_with?('$1$') && hash.length == 34
return 'md5'
when hash.start_with?('$2$') && hash.length == 59,
hash.start_with?('$2a$') && hash.length == 60,
hash.start_with?('$2b$') && hash.length == 60,
hash.start_with?('$2x$') && hash.length == 60,
hash.start_with?('$2y$') && hash.length == 60
return 'bf' # bcrypt
when hash.start_with?('$5$') && hash.split('$').last.length == 43
# we dont check full length since it may have 'rounds=' in the [1] area or not with an arbitrary length number
return 'sha256,crypt'
when hash.start_with?('$6$') && hash.split('$').last.length == 86
# we dont check full length since it may have 'rounds=' in the [1] area or not with an arbitrary length number
return 'sha512,crypt'
when hash.start_with?('@S@') && hash.length == 148
return 'qnx,sha512'
when hash.start_with?('@s@') && hash.length == 84
return 'qnx,sha256'
when hash.start_with?('@m@') && hash.length == 52
return 'qnx,md5'
when hash.start_with?('$y$') && hash.split('$').last.length == 43
return 'yescrypt'
when hash.start_with?('_') && hash.length == 20
return 'des,bsdi,crypt'
when hash =~ %r{^[./\dA-Za-z]{13}$} # hash.length == 13
return 'des,crypt'
when hash =~ /^\$dynamic_82\$[\da-f]{128}\$HEX\$[\da-f]{32}$/ # jtr vmware ldap https://github.com/rapid7/metasploit-framework/pull/13865#issuecomment-660718108
return 'dynamic_82'
when hash.start_with?(/{SSHA}/i)
return 'ssha'
when hash.start_with?(/{SHA512}/i)
return 'raw-sha512'
when hash.start_with?(/{SHA256}/i)
return 'raw-sha256'
when hash.start_with?(/{SHA}/i)
return 'raw-sha1'
when hash.start_with?(/{MD5}/i)
return 'raw-md5'
when hash.start_with?(/{SMD5}/i)
return 'smd5'
when hash.start_with?(/{SSHA256}/i)
return 'ssha256'
when hash.start_with?(/{SSHA512}/i)
return 'ssha512'
# windows
when hash.length == 65 && hash =~ /^[\da-fA-F]{32}:[\da-fA-F]{32}$/ && hash.split(':').first.upcase == 'AAD3B435B51404EEAAD3B435B51404EE'
return 'nt'
when hash.length == 65 && hash =~ /^[\da-fA-F]{32}:[\da-fA-F]{32}$/
return 'lm'
# OSX
when hash.start_with?('$ml$') && hash.split('$').last.length == 256
return 'pbkdf2-hmac-sha512,osx' # 10.8+
when hash =~ /^[\da-fA-F]{48}$/ # hash.length == 48
return 'xsha,osx' # 10.4-10.6
# databases
when hash.start_with?('0x0100') && hash.length == 54
return 'mssql05'
when hash.start_with?('0x0100') && hash.length == 94
return 'mssql'
when hash.start_with?('0x0200') && hash.length == 142
return 'mssql12'
when hash =~ /^[\da-f]{16}$/ # hash.length == 16
return 'mysql' # mysql323 (pre 4.1)
when hash.start_with?('*') && hash.length == 41
return 'mysql-sha1' # mysql 4.1+
when hash.start_with?('md5') && hash.length == 35
return 'postgres'
when hash =~ /^[\da-fA-F]{16}$/
return 'des,oracle' # pre 11g
when hash =~ /^S:[\dA-F]{60}$/
return 'raw-sha1,oracle11'
when hash =~ /^S:[\dA-F]{60};H:[\dA-F]{32};T:[\dA-F]{160}$/
return 'raw-sha1,oracle'
when hash =~ /^H:[\dA-F]{32};T:[\dA-F]{160}$/
return 'pbkdf2,oracle12c'
# webapps
when hash.start_with?('$P$') && hash.length == 34,
hash.start_with?('$H$') && hash.length == 34
return 'phpass' # wordpress, drupal, phpbb3 (H not P)
when hash.start_with?('$ml$') && hash.length == 203
return 'PBKDF2-HMAC-SHA512'
when hash.start_with?('{PKCS5S2}') && hash.length == 73
return 'PBKDF2-HMAC-SHA1'
when hash.start_with?('$B$') && hash.split('$').last.length == 32
return 'mediawiki'
# mobile
when hash =~ /^[A-F0-9]{40}:[a-f0-9]{16}$/
return 'android-sha1'
when hash =~ /^[A-F0-9]{32}:[a-f0-9]{16}$/
return 'android-md5'
# other
when hash =~ /^<\d+@.+?>#\w{32}$/
return 'hmac-md5'
when hash.length == 114 && hash.start_with?('$M$')
return 'F5-Secure-Vault'
when hash =~ /^M\$[[:print:]]+#[\da-fA-F]{32}(?:(?::[[:print:]]*$)|$)/
return 'mscash'
when hash =~ /^\$DCC2\$\d+#[[:print:]]+#[\da-fA-F]{32}(?:(?::[[:print:]]*$)|$)/
return 'mscash2'
when hash =~ /^\*?[\da-fA-F]{32}\*[\da-fA-F]{32}$/
# we accept the beginning star as optional
return 'vnc'
end
''
end
# rubocop:enable Metrics/ModuleLength
end
end
end