diff --git a/lib/core/settings.py b/lib/core/settings.py index 6fab87446..5b3d3190b 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from lib.core.enums import OS from thirdparty import six # sqlmap version (...) -VERSION = "1.10.7.118" +VERSION = "1.10.7.119" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) diff --git a/lib/utils/hash.py b/lib/utils/hash.py index 9a7ef72e7..3386a322e 100644 --- a/lib/utils/hash.py +++ b/lib/utils/hash.py @@ -1074,9 +1074,6 @@ def hashRecognition(value): # Hashes for Oracle and old MySQL look the same hence these checks if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD: continue - elif regex == HASH.CRYPT_GENERIC: - if any((value.lower() == value, value.upper() == value)): - continue else: parts.append("(?P<%s>%s)" % (name, regex)) @@ -1088,6 +1085,10 @@ def hashRecognition(value): algorithm, _ = [_ for _ in match.groupdict().items() if _[1] is not None][0] retVal = getattr(HASH, algorithm) + # Note: greedy CRYPT_GENERIC requires a mixed-case value to reduce false positives + if retVal == HASH.CRYPT_GENERIC and any((value.lower() == value, value.upper() == value)): + retVal = None + return retVal def _bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, proc_id, proc_count, wordlists, custom_wordlist, api): diff --git a/tests/test_hash.py b/tests/test_hash.py index 4ab5546c0..42db6995e 100644 --- a/tests/test_hash.py +++ b/tests/test_hash.py @@ -97,6 +97,15 @@ class TestHashRecognition(unittest.TestCase): def test_mysql(self): self.assertEqual(H.hashRecognition("*00E247AC5F9AF26AE0194B41E1E769DEE1429A29"), HASH.MYSQL) + def test_crypt_generic(self): + # Traditional DES crypt(3) (hashcat -m 1500); mixed-case is required by the heuristic + self.assertEqual(H.hashRecognition("rl.3StKT.4T8M"), HASH.CRYPT_GENERIC) + + def test_crypt_generic_single_case_is_none(self): + # All-lower/all-upper 13-char values are too greedy to be trusted as crypt + self.assertIsNone(H.hashRecognition("abcdefghijklm")) + self.assertIsNone(H.hashRecognition("ABCDEFGHIJKLM")) + def test_junk_is_none(self): self.assertIsNone(H.hashRecognition("foobar"))