From 5497a6e58dab264f32724321e3763e53bf0f091e Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Sat, 28 Oct 2017 22:40:55 +0200 Subject: [PATCH] Adding support for Base64 format of md5, sha1, sha256 and sha512 hashes (Issue #1881) --- lib/core/enums.py | 4 ++++ lib/utils/hash.py | 46 ++++++++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/lib/core/enums.py b/lib/core/enums.py index 77c9a21cb..e85f7a6a3 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -138,6 +138,10 @@ class HASH: SSHA512 = r'\A\{SSHA512\}[a-zA-Z0-9+/]+={0,2}\Z' DJANGO_MD5 = r'\Amd5\$[^$]+\$[0-9a-f]{32}\Z' DJANGO_SHA1 = r'\Asha1\$[^$]+\$[0-9a-f]{40}\Z' + MD5_BASE64 = r'\A[a-zA-Z0-9+/]{22}==\Z' + SHA1_BASE64 = r'\A[a-zA-Z0-9+/]{27}=\Z' + SHA256_BASE64 = r'\A[a-zA-Z0-9+/]{43}=\Z' + SHA512_BASE64 = r'\A[a-zA-Z0-9+/]{86}==\Z' # Reference: http://www.zytrax.com/tech/web/mobile_ids.html class MOBILES: diff --git a/lib/utils/hash.py b/lib/utils/hash.py index 87d575048..332df974b 100644 --- a/lib/utils/hash.py +++ b/lib/utils/hash.py @@ -538,6 +538,10 @@ __functions__ = { HASH.SSHA: ssha_passwd, HASH.SSHA256: ssha256_passwd, HASH.SSHA512: ssha512_passwd, + HASH.MD5_BASE64: md5_generic_passwd, + HASH.SHA1_BASE64: sha1_generic_passwd, + HASH.SHA256_BASE64: sha256_generic_passwd, + HASH.SHA512_BASE64: sha512_generic_passwd, } def storeHashesToFile(attack_dict): @@ -618,24 +622,24 @@ def attackDumpedTable(): break for column in columns: - if column == col_user or column == '__infos__': + if column == col_user or column == "__infos__": continue - if len(table[column]['values']) <= i: + if len(table[column]["values"]) <= i: continue - value = table[column]['values'][i] + value = table[column]["values"][i] if hashRecognition(value): found = True - if col_user and i < len(table[col_user]['values']): - if table[col_user]['values'][i] not in attack_dict: - attack_dict[table[col_user]['values'][i]] = [] + if col_user and i < len(table[col_user]["values"]): + if table[col_user]["values"][i] not in attack_dict: + attack_dict[table[col_user]["values"][i]] = [] - attack_dict[table[col_user]['values'][i]].append(value) + attack_dict[table[col_user]["values"][i]].append(value) else: - attack_dict['%s%d' % (DUMMY_USER_PREFIX, i)] = [value] + attack_dict["%s%d" % (DUMMY_USER_PREFIX, i)] = [value] col_passwords.add(column) @@ -883,34 +887,36 @@ def dictionaryAttack(attack_dict): try: item = None - if hash_regex not in (HASH.CRYPT_GENERIC, HASH.JOOMLA, HASH.WORDPRESS, HASH.UNIX_MD5_CRYPT, HASH.APACHE_MD5_CRYPT, HASH.APACHE_SHA1, HASH.VBULLETIN, HASH.VBULLETIN_OLD, HASH.SSHA, HASH.SSHA256, HASH.SSHA512, HASH.DJANGO_MD5, HASH.DJANGO_SHA1): + if hash_regex not in (HASH.CRYPT_GENERIC, HASH.JOOMLA, HASH.WORDPRESS, HASH.UNIX_MD5_CRYPT, HASH.APACHE_MD5_CRYPT, HASH.APACHE_SHA1, HASH.VBULLETIN, HASH.VBULLETIN_OLD, HASH.SSHA, HASH.SSHA256, HASH.SSHA512, HASH.DJANGO_MD5, HASH.DJANGO_SHA1, HASH.MD5_BASE64, HASH.SHA1_BASE64, HASH.SHA256_BASE64, HASH.SHA512_BASE64): hash_ = hash_.lower() - if hash_regex in (HASH.MYSQL, HASH.MYSQL_OLD, HASH.MD5_GENERIC, HASH.SHA1_GENERIC, HASH.APACHE_SHA1): + if hash_regex in (HASH.MD5_BASE64, HASH.SHA1_BASE64, HASH.SHA256_BASE64, HASH.SHA512_BASE64): + item = [(user, hash_.decode("base64").encode("hex")), {}] + elif hash_regex in (HASH.MYSQL, HASH.MYSQL_OLD, HASH.MD5_GENERIC, HASH.SHA1_GENERIC, HASH.APACHE_SHA1): item = [(user, hash_), {}] elif hash_regex in (HASH.SSHA,): - item = [(user, hash_), {'salt': hash_.decode("base64")[20:]}] + item = [(user, hash_), {"salt": hash_.decode("base64")[20:]}] elif hash_regex in (HASH.SSHA256,): - item = [(user, hash_), {'salt': hash_.decode("base64")[32:]}] + item = [(user, hash_), {"salt": hash_.decode("base64")[32:]}] elif hash_regex in (HASH.SSHA512,): - item = [(user, hash_), {'salt': hash_.decode("base64")[64:]}] + item = [(user, hash_), {"salt": hash_.decode("base64")[64:]}] elif hash_regex in (HASH.ORACLE_OLD, HASH.POSTGRES): item = [(user, hash_), {'username': user}] elif hash_regex in (HASH.ORACLE,): - item = [(user, hash_), {'salt': hash_[-20:]}] + item = [(user, hash_), {"salt": hash_[-20:]}] elif hash_regex in (HASH.MSSQL, HASH.MSSQL_OLD, HASH.MSSQL_NEW): - item = [(user, hash_), {'salt': hash_[6:14]}] + item = [(user, hash_), {"salt": hash_[6:14]}] elif hash_regex in (HASH.CRYPT_GENERIC,): - item = [(user, hash_), {'salt': hash_[0:2]}] + item = [(user, hash_), {"salt": hash_[0:2]}] elif hash_regex in (HASH.UNIX_MD5_CRYPT, HASH.APACHE_MD5_CRYPT): - item = [(user, hash_), {'salt': hash_.split('$')[2], 'magic': '$%s$' % hash_.split('$')[1]}] + item = [(user, hash_), {"salt": hash_.split('$')[2], "magic": "$%s$" % hash_.split('$')[1]}] elif hash_regex in (HASH.JOOMLA, HASH.VBULLETIN, HASH.VBULLETIN_OLD): - item = [(user, hash_), {'salt': hash_.split(':')[-1]}] + item = [(user, hash_), {"salt": hash_.split(':')[-1]}] elif hash_regex in (HASH.DJANGO_MD5, DJANGO_SHA1): - item = [(user, hash_), {'salt': hash_.split('$')[1]}] + item = [(user, hash_), {"salt": hash_.split('$')[1]}] elif hash_regex in (HASH.WORDPRESS,): if ITOA64.index(hash_[3]) < 32: - item = [(user, hash_), {'salt': hash_[4:12], 'count': 1 << ITOA64.index(hash_[3]), 'prefix': hash_[:12]}] + item = [(user, hash_), {"salt": hash_[4:12], "count": 1 << ITOA64.index(hash_[3]), "prefix": hash_[:12]}] else: warnMsg = "invalid hash '%s'" % hash_ logger.warn(warnMsg)