Offline Password Cracking: The Attack and the Best Defense
In Part 1 of this two-part series, I explained what Online Password Cracking is and how to defend against it.
In (the long-awaited) Part 2, I will describe:
- Offline Password Cracking
- The primary differences between Online and Offline Password Cracking
- And my favorite tools for Offline Password Cracking, hashcat
What Is “Offline Password Cracking?”
Offline Password Cracking is an attempt to recover one or more passwords from a password storage file that has been recovered from a target system. Typically, this would be the Security Account Manager (SAM) file on Windows, or the /etc/shadow file on Linux. In most cases, Offline Password Cracking will require that an attacker has already attained administrator/root level privileges on the system to get to the storage mechanism. It is possible, however, that the password hashes could also have been pulled directly from a database using SQL injection, an unprotected flat text file on a web server, or some other poorly protected source.
Using Online Password Cracking, an attacker does not have to have any previous access to the system. The attacker uses the interface or service presented to legitimate users, such as a login web page or an SSH or FTP server, to try to guess user account names and passwords. However, Online Password Cracking is much slower than Offline Password Cracking; Offline Password Cracking can be 1000 – 1,000,000 times faster than cracking online. Online Password Cracking is also noisier, potentially leaving one entry per attempt in a log file. Once the credential storage mechanism is recovered, Offline Password Cracking leaves no other trace on the victim’s system.
Offline Password Cracking Methods
Offline Password Cracking, like its online counterpart, can use a variety of methods to guess the password. A Brute Force attack uses all possible combinations of passwords made up of a given character set, up to a given password size. For instance, a Brute Force attack could attempt to crack an eight-character password consisting of all 95 printable ASCII characters. This would mean that there would be 95 ^ 8 possible combinations (95x95x95x95x95x95x95x95), or 6,634,204,312,890,625 (6.6 quadrillion) passwords. Assuming a rate of 1 million guesses per second, an eight-character password would take about 210 years to crack with a Brute Force attack.
An attacker who knows something about the passwords’ pattern can use a Mask attack. A Mask attack reduces the number of combinations from the Brute Force method by either making guesses or using knowledge about the password’s format. For instance, if an attacker knows or assumes that the passwords pattern is:
- Password is eight characters long
- First character is upper case
- Next five characters are lower case
- Next character is a number
- Next character is a symbol
The number of possible combinations is: 26 x 26 x 26 x 26 x 26 x 26 x 10 x 34 or 105,031,363,840 combinations. At 1,000,000 combinations per second, this password would take up to 1.2 days to crack with a Mask Attack. Compare this with 210 years to crack the same password using a Brute Force attack where no assumptions are made about the password.
A Dictionary Attack allows an attacker to use a list of common, well-known passwords, and test a given password hash against each word in that list. Each word in the list is hashed (with the salt from the password hash to be cracked, if it has one) and compared with the hash. If it matches, the word from the list is either the original password or another password that can produce the same hash (which is mathematically very improbable). The website CrackStation has a downloadable dictionary of 1.5 billion passwords, taken from well-known breaches, along with every word in the Wikipedia website, Project Gutenberg, and other lists. This is the list I typically use in our pentesting engagements.
There are other types of attacks, such as the Rule-Based attack, which can apply permutations to the password(s) to be guessed, and the Hybrid Attack, which combines a limited Brute Force attack with a dictionary attack (such as appending all combinations of four-digit numbers to all words in a dictionary).
With the Online Password Cracking attack, the solution is quite simple. Allow the user X number of login attempts during Y period, before locking their account for Z minutes/hours (or until an admin unlocks it). Many web development frameworks have the capability to specify these rules in the configuration file. Account lockout pretty much ruins the day for the Online Password hacker.
But once the password hash file has been captured, how do you stop the Offline Password hacker? You can’t lock out the attacker at that point. The best solution is to slow down the attacker, so that it is prohibitively expensive to crack the passwords offline. An individual user is not going to notice when their login attempt takes 100ms longer to come back than it did before… but a password cracking attacker sure will!
A Tale of Two Password Hashes
To illustrate, let’s choose a password for an imaginary web application. Let’s say that the passwords are hashed and stored on disk in a flat file, and that an attacker somehow manages to obtain the file. We will compare two hash algorithms: SHA1 (unsalted) and the Django Password-Based Key Derivation Function 2 (PBKDF2), using a salted password and 20,000 iterations of the SHA256 hashing algorithm.
As a short side-note: password salting is a defense against a Rainbow Table attack, which uses a dictionary of precomputed hashes for all passwords of a given character set and size. A Rainbow Table attack is prevented by the salt, or random piece of data added to the password before hashing it (which is usually stored with the password because it is needed when the password being compared is hashed). A Rainbow Table attacker would have to have a Rainbow Table for each salt value (usually 32-bits or more), and each Rainbow Table can be multiple terabytes in size for even a small password, such as seven characters. Salting effectively stops a Rainbow Table attack, but does nothing against a GPU-powered Offline Password Cracking attack, since the hashes are generated, adding in the salt, on the fly.
For our password, let’s choose one that appears to be very secure, according to the byzantine password generation rules that we usually live within the corporate world: 051206/jonathan06. This password would be infeasible to crack using a Brute-Force attack. However, this password was recovered from the RockYou! Breach, and therefore, it appears in the 14-million password rockyou.txt password dictionary that comes with Kali, which we will be using for this test.
When we hash the password using SHA1, we get: e88d9d595c0da845e31a421f025ffa047a888c98.
When we hash the password using PBKDF2-SHA256 (20,000 iterations), we get: pbkdf2_sha256$20000$3hG9tCawVQRv$YQmMzntbh73QYD+UdEPi4tYpT9LXZciDuNrs01rwc1E=
You might notice that the second password has some meta-data built into the hash, with each field delimited by the $ sign. The hash itself tells us that it is using the PBKDF2 algorithm, with SHA256 as the basis, with 20,000 iterations, and a salt value of “3hG9tCawVQRv”. Finally, the part after the last dollar sign is the Base64-encoded version of the binary hash itself (64 characters unencoded, 32 bytes, or 256 bits long).
We can use my favorite password cracking program, hashcat, to crack these passwords using Graphical Processing Unit (GPU) acceleration. hashcat can leverage the power of the graphics card, much the same way that Crypto Currency mining does, to greatly parallelize password cracking.
hashcat uses numeric codes for the different hash types. Here is a list of hashes that hashcat can crack, along with examples of what they should look like. The examples can be helpful when trying to debug error messages about the wrong hash length.
To crack the SHA1 hash, we use the following command line:
./hashcat64.bin -m 100 -a 0 super-secure-password.hash ~/rockyou/rockyou.txt
So how long does it take a laptop with an Nvidia GTX 1060 (gaming-class) GPU to crack the “super-secure” password using a 14-million-word dictionary? Less time than it takes to ask the question!
As we can see in the screenshot above, for the SHA1 hash, it took less than one second to find the password in the 14-million password list!
Now, we will run the same attack against the PBKDF2 SHA256 Django hash with the following command line:
./hashcat64.bin -m 10000 -a 0 django_sha256.hash ~/rockyou/rockyou.txt
Django Hash Crack
As we can see from the screenshot above, it takes considerably longer to crack this password (over 1000x longer). We can crack 31 million SHA1 hashes per second, but only 27 thousand Django hashes per second. Now, that doesn’t help this poor fellow much. His password was compromised in a breach, via a ten-year old SQL-injection vulnerability, of a system that stored user passwords in plaintext.
In both cases, our “secure” password was easily cracked on a gamer-class laptop in a few minutes. So how can we select truly secure passwords? The traditional wisdom has always been to pick a password of at least eight characters with a mix of upper case, lower case, numbers, and symbols, with policies often enforcing these rules. The new guidelines now recommend a minimum of 8 characters, and that systems allow maximum password lengths of no less than 64 characters. Also gone are the complicated rules that almost guarantee a user will reuse passwords or write them on sticky notes! A memorable phrase, from a song, poem, novel, or just an easily memorable sentence is preferable. NIST also recommends password screening when passwords are being selected, to prevent use of commonly used passwords. As I mentioned in Part 1, login and password credentials by themselves are fairly insecure. Using multi-factor authentication is highly recommended as well. If a password should get compromised, the attacker would also need the second factor to log in.
For application developers, never store passwords in plaintext or using weak hashing algorithms, such as MD5 or SHA1. Use a PBKDF2 format with strong hashing, such as SHA256 or SHA512, and thousands of iterations. Alternatively, use bcrypt or scrypt, which are designed to slow down the password-checking process. CrackStation.net has some excellent guidance on securely storing and checking passwords.
Daniel “Doc” Sewell is the Lead Cybersecurity Engineer and Trainer for Alpine Security. He currently holds many security-related certifications, including EC-Council Certified Security Analyst (ECSA), Licensed Penetration Tester (Master), Offensive Security Certified Professional (OSCP), Certified Information Systems Security Professional (CISSP) and Certified Secure Software Lifecycle Professional (CSSLP). Doc has many years of experience in software development, working on web interfaces, database applications, thick-client GUIs, battlefield simulation software, automated aircraft scheduling systems, embedded systems, and multi-threaded CPU and GPU applications. Doc’s cybersecurity experience includes penetration testing a fighter jet embedded system, penetration testing medical lab devices, creating phishing emails and fake web sites for social engineering engagements, and teaching security courses to world-renowned organizations such as Lockheed Martin and the Hong Kong Police Department. Doc’s hobbies and interests include home networking, operating systems, computer gaming, reading, movie watching, and traveling.