A recent article by @mubix resurfaced the largely unknown fact that because password candidates (plain/mangled dictionary words and generated plain texts) are stored in GPU registers, there aren’t actually enough registers to store password candidates over certain lengths. As a result, our password cracking tools have been limited to these lengths (differing per algorithm). This limit could be exceeded, however doing so would double the amount of processing time required, so the trade-off for the speeds we’ve come to expect with our hardware are in fact stopping us from breaking a password of X length, even if it’s in our dictionary.
In this post, NotSoSecure’s Will Hunt will cover some examples in hashcat and John The Ripper. We’ll cover a couple of algorithms below, followed by a more complete breakdown of algorithm limits at the end of this post, as well as options to increase these limits (to a limit!).
Back in 2013, oclHashcat-plus v0.15 was released and one of the major updates was support for increased password lengths. The limit rose from a maximum of 15 characters to 55 (with some exceptions). These exceptions are shown in the table below, figures from which have been taken from hashcat’s FAQ.
|Inherent Limitations from Hash Itself|
|Algorithm||Hashcat Mode||Max. Length|
|MS Office <= 2003 $0/$1, MD5 + RC4, collider #1||9710||5|
|MS Office <= 2003 $3/$4, SHA1 + RC4, collider #1||9810||5|
|PDF 1.1 - 1.3 (Acrobat 2 - 4), collider #1||10410||5|
|phpass, phpBB3 (MD5), Joomla >= 2.5.18 (MD5), WordPress (MD5)||400||40|
|Cisco-IOS $1$ (MD5)||500||16|
|Apache $apr1$ MD5, md5apr1, MD5 (APR)||1600||16|
|sha512crypt $6$, SHA512 (Unix)||1800||16|
|Domain Cached Credentials 2 (DCC2), MS Cache 2||2100||16|
|Password Safe v3||5200||24|
|Samsung Android Password/PIN||5800||16|
|sha256crypt $5$, SHA256 (Unix)||7400||16|
|Lotus Notes/Domino 5||8600||16|
|SAP CODVN H (PWDSALTEDHASH) iSSHA-1||10300||40|
|PDF 1.4 - 1.6 (Acrobat 5 - 8)||10500||40|
|PDF 1.7 Level 8 (Acrobat 10 - 11)||10700||16|
There are also attack-mode factors that affect password lengths in hashcat. Information on this is also in the FAQ but is out of scope for this post. Windows passwords are another exception and that’s what we’ll look at first.
As almost all Windows hashing is based on UTF-16LE which uses 16 bits (2 bytes) per character, each character of a password candidate is twice the length, halving the limit from 55 to 27 (clearly 27.5 isn’t a password length!). This will apply to any UTF-16 based hash. Let’s start with a hashcat test using a dictionary containing just our password.
Great. Now let’s add a character to our password and replace it in the dictionary…
Oh dear. Now whilst 27 character passwords aren’t exactly common in the wild, they’re not out of the realm of possibility, especially as people start using memorable phrases. Another algorithm we’re likely to see is SHA512crypt which are the $6$ hashes found in /etc/shadow files and is also one of the exceptions noted earlier. These are limited to only 16 characters (!) which is a reasonably plausible length to expect these days, albeit maybe not very often.
Let’s make it 17 characters and see if we still have a winner.
Password: Weak SHA512crypt!
17 doesn’t cut it! *Runs to Ubuntu box and makes password 17 characters*
Now let’s explore some examples using John.
John the Ripper
By using the --list=format-all-details and --list=format-details switches, John dumps out various algorithm format info including details about length (screenshots are truncated).
Even though John shows us a max limit of 81, the actual max length of accepted NT passwords is the same as hashcat’s…27. This is because getting 27 Unicode characters may need up to 81 bytes of UTF-8 (up to 3 bytes per character). John does actually state bytes and not characters, look above if you don’t believe me ;-)
You can get john to reveal the 27 limit by adding an –enc:raw to the command, however the latest version of jumbo has reworked the output to help us, shown below.
Nice. By default we’re now shown our max limits and notice now John states max length, not bytes. In MD5’s case we’ve also got some helpful info about worst case scenarios where a password contains characters that all use 3 bytes of UTF-8, heavily bringing down the MD5 limit from 55 to 18. Typically we wouldn’t see worst case scenarios during tests, unless maybe you were testing foreign language passwords. For example, most Chinese, Korean and Japanese characters use 3 bytes of UTF-8.
Ok, let’s give john a crack at an MD5 hash (pun fully intended) of a 55 character password. Below we can see our wordlist containing our password, the character length of our password, it’s hash and the results.
Bingo. Let’s up the length by one.
John can’t break it. Lastly, let’s have a look at a higher limit SHA-384 hash. John shows this supports a maximum of 111 characters.
The below two screenshots show the tests, the first with a 111 character password, the second with a 112 characters.
So 111 cracks but 112 doesn’t. Clearly we’re defining very high upper limits here that you’re really not likely to see often in the wild, but it’s still important we understand the limitations of our tools.
NIST have also recently published new guidelines regarding passwords including the allowance for at least 64 characters. This is to provide greater flexibility for creating memorable passphrases instead of passwords.
You mentioned something earlier about possibly increasing these limits?
We did indeed and we found this via the originally referenced article so we won’t re-link everything here. John can be custom compiled to get a few more characters, however the performance hit you’ll take on cracking speed will be significant. You need to ask yourselves are you likely going to be encountering passwords above the corresponding limits and then make a decision based on time and resources. The article also notes a branch of hashcat that supports higher limits but it doesn’t currently support NTLM.
That’s cool! I could really use a cheat sheet for the max lengths on all algorithms…
It’s funny you should say that, we thought the same thing! We therefore created the below cheat sheet based from John’s output, covering both worst case UTF-8 scenarios as well as max lengths. If you ever stumble upon some of the lesser known/encountered hashes and want to know the construction format, the --list=format-all-details --format=<insert alg> info provides an example hash at the bottom. Also, please note that limits in John may differ from limits in hashcat.
Happy cracking everyone!
|Worst Case||Max Length||Algorithm(s)|
|2||8||tripcode, net-ah, PST, RACF|
|5||15||md5crypt, md5crypt-opencl, phpass-opencl|
|5||16||dynamic_19, dynamic_39, WoWSRP, Clipperz, lotus5, net-md5, pix-md5, lotus5-opencl, BitLocker-opencl|
|6||20||dynamic_40, net-sha1, Raw-SHA512-free-opencl, XSHA512-free-opencl|
|7||LM, nethalflm, LM-opencl|
|7||23||dynamic_1, dynamic_8, dynamic_1011, dynamic_1012, dynamic_1013, dynamic_1034, dynamic_1401, dynamic_1506, dynamic_1550, dynamic_1551, saph, sha512crypt-opencl|
|8||descrypt, sapb, VNC, descrypt-opencl|
|9||28||agilekeychain-opencl, enpass-opencl, iwork-opencl|
|10||31||dynamic_4, dynamic_5, dynamic_31, dynamic_32, dynamic_1015, BKS, CRC32, ipb2, osc, PKZIP, Raw-SHA1-ng|
|10||32||dynamic_10, dynamic_11, chap, cq, dmd5, Fortigate, hdaa, IKE, krb4, krb5, lotus85, MongoDB, mysqlna, mysql-sha1, mysql, nk, o10logon, o3logon, o5logon, PDF, postgres, PuTTY, RAR5, SIP, skey, SSH-ng, OpenVMS, wbb3, keystore-opencl, o5logon-opencl|
|13||39||dynamic_1008, dynamic_1009, phpass, Salted-SHA1, salted-sha1-opencl|
|16||48||BestCrypt, pfx, qnx|
|18||55||dynamic_0, dynamic_2, dynamic_3, dynamic_6, dynamic_9, dynamic_14, dynamic_22, dynamic_23, dynamic_30, dynamic_34, dynamic_1001, dynamic_1002, dynamic_1004, dynamic_1005, dynamic_1006, dynamic_1007, dynamic_1017, dynamic_1018, dynamic_1019, dynamic_1020, dynamic_1021, dynamic_1022, dynamic_1024, dynamic_1025, dynamic_1300, dynamic=md5($p), hsrp, MediaWiki, PHPS, PHPS2, Raw-MD4, Raw-MD5, Raw-SHA1, Raw-SHA1-AxCrypt, Raw-SHA1-Linkedin, Raw-SHA224, Raw-SHA256, Raw-SHA256-ng, Lastpass, vtp, RAR5-opencl, FVDE-opencl, mysql-sha1-opencl, PBKDF2-HMAC-SHA256-opencl, Raw-MD4-opencl, Raw-MD5-opencl, Raw-SHA1-opencl, Raw-SHA256-opencl, Raw-SHA512-opencl, XSHA512-opencl|
|21||63||AFS, Stribog-256, Stribog-512, ODF-AES-opencl, RAKP-opencl|
|21||64||dynamic_1560, dominosec, dominosec8, fde, krb5-18, po, Sybase-PROP, tc_aes_xts, tc_ripemd160, tc_sha512, tc_whirlpool, sha1crypt-opencl, PBKDF2-HMAC-MD4-opencl, PBKDF2-HMAC-MD5-opencl, PBKDF2-HMAC-SHA1-opencl, truecrypt-opencl, blockchain-opencl, dmg-opencl, encfs-opencl, keychain-opencl, krb5pa-sha1-opencl, ODF-opencl, strip-opencl, sxc-opencl, zip-opencl|
|24||72||bcrypt, bfegg, bcrypt-opencl, crypt|
|27||dynamic_29, dynamic_33, mscash, MSCHAPv2, netntlm, NT, Raw-MD5u, krb5pa-md5-opencl, mscash-opencl, nt-opencl, ntlmv2-opencl, NT-old|
|36||110||dynamic_12, dynamic_13, dynamic_15, dynamic_16, dynamic_18, dynamic_24, dynamic_25, dynamic_26, dynamic_35, dynamic_36, dynamic_37, dynamic_38, dynamic_50, dynamic_60, dynamic_61, dynamic_70, dynamic_80, dynamic_90, dynamic_100, dynamic_110, dynamic_120, dynamic_130, dynamic_140, dynamic_150, dynamic_160, dynamic_170, dynamic_180, dynamic_190, dynamic_200, dynamic_210, dynamic_220, dynamic_230, dynamic_240, dynamic_250, dynamic_260, dynamic_270, dynamic_280, dynamic_290, dynamic_300, dynamic_310, dynamic_320, dynamic_330, dynamic_340, dynamic_350, dynamic_360, dynamic_370, dynamic_380, dynamic_390, dynamic_400, dynamic_410, dynamic_420, dynamic_1003, dynamic_1014, dynamic_1016, dynamic_1023, dynamic_1026, dynamic_1027, dynamic_1028, dynamic_1029, dynamic_1030, dynamic_1031, dynamic_1501, dynamic_1502, dynamic_1503, dynamic_1504, dynamic_1505, dynamic_1552, dynamic_2000, dynamic_2001, dynamic_2002, dynamic_2003, dynamic_2004, dynamic_2005, dynamic_2006, dynamic_2008, dynamic_2010, dynamic_2011, dynamic_2014, FormSpring, hMailServer, md5ns, PBKDF2-HMAC-SHA512-opencl|
|37||111||cloudkeychain, Raw-SHA512, Raw-SHA384, Raw-SHA512-ng|
|41||125||scrypt, agilekeychain, aix-ssha1, aix-ssha256, aix-ssha512, as400-ssha1, axcrypt, AzureAD, Bitcoin, BitLocker, Blackberry-ES10, Blockchain, sha1crypt, dahua, Django, django-scrypt, dmg, DPAPImk, dragonfly3-32, dragonfly3-64, dragonfly4-32, dragonfly4-64, eCryptfs, electrum, EncFS, enpass, EPI, ethereum, FVDE, geli, gost, gpg, HAVAL-128-4, HAVAL-256-3, HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, HMAC-SHA512, itunes-backup, iwork, KeePass, keychain, keyring, keystore, known_hosts, krb5pa-sha1, krb5tgs, kwallet, lp, LUKS, MD2, mdc2, scram, Mozilla, mscash2, mschapv2-naive, krb5pa-md5, multibit, netlmv2, netntlmv2, netntlm-naive, nsec3, ODF, Office, OpenBSD-SoftRAID, openssl-enc, Oracle12C, Padlock, Palshop, Panama, PBKDF2-HMAC-MD4, PBKDF2-HMAC-MD5, PBKDF2-HMAC-SHA1, PBKDF2-HMAC-SHA256, PBKDF2-HMAC-SHA512, PEM, pomelo, pwsafe, RAKP, Raw-Blake2, Raw-Keccak, Raw-Keccak-256, Raw-SHA3, ripemd-128, ripemd-160, rsvp, Siemens-S7, skein-256, skein-512, aix-smd5, Snefru-128, Snefru-256, SNMP, STRIP, sxc, Tiger, vdi, whirlpool, whirlpool0, whirlpool1, xmpp-scram, ZIP, ZipMonster, plaintext, has-160, gpg-opencl, mscash2-opencl|