Welcome, today we’re going to talk about “Brute Force” Password Breaking.
I know, it’s a controversial topic… though they say you should write about controversy if you want to get read right? 😛 But to ensure its as controversial as possible I’m going to give you an actual working prototype that you can use to try Brute Force attack your own passwords! 😉
However, before you call me irresponsible consider the following.
There are plenty of methods for cracking passwords that are far more efficient than a Brute Force attack and if you have to resort to Brute Force (trying all possible combinations against an unknown and likely long password) a modern hashing algorithm then you are essentially screwed!
If the creator of the password chose a “simple”, “common” or “guessable” password… like for example “123456789”, “Cat” or “Password”, Brute Force isn’t even necessary!
Rainbow Tables
A hacker can simply use a “Rainbow Table” (so colorful), which is basically a database, to lookup the pre-computed solution for the hash of your password and obtain the unhashed “Plaintext” of your password.
In most cases where a hacker can use a Rainbow Table they will save themselves significant time and effort simply because they don’t have to do any hashing (which cumulatively can take a lot of time), it’s just a matter of traversing a table and retrieving the associated data of the index that matches the hash provided, assuming of course that the hash was pre-computed and exists in the Rainbow Table.
For example, the hash output of the SHA1 algorithm for the word ‘Cat’ is cebe54c7626cb1cefaca5f7f5ea6c96b4a7a2882 and if a hacker was able to break into a database containing this hashed credential then they could reverse lookup the hashed password in seconds.
Clearly what makes a Rainbow Table so useful to a hacker is that it can take the insurmountable challenge of Brute Forcing a password and change it into something that is at the very least, manageable.
There are techniques however, called Password ‘Salting‘ & ‘Peppering‘ which expose a severe weakness with Rainbow Tables… namely, if you cannot pre-compute a big database of all possible hashes then you are forced to resort to some other technique if not a Brute Force attack.
A Salt is some unique (and long) string value that can be added to a password before it is hashed to make building a Rainbow Table difficult if not impossible.
Here’s an example of how Salting works, lets take the insecure password we used above ‘Cat’, and look at what happens when we add a 30 character Salt to it prior to hashing the value.
Password: Cat
Salt: LPdjlEfrMhGkENHf3e4Lp7VZgXd77f
Hash(Password + Salt) = d73b50b3d80762f55a28a44e49568be064ee8208
Note:To ensure you get the maximum benefit from Salting your passwords you should use a different Salt for every password credential that you store in your database. If you don’t it will be much easier to for a hacker to steal your passwords.
As you can see, by including a Salt with the password when it is hashed the result produced is different than the word by itself. This different hash is what is stored in the database.
The benefit of doing this is simply that it is now extremely unlikely (improbable but not impossible) that the combination of the word Cat and this long randomly generated Salt string will have been pre-computed anywhere, so it doesn’t even matter if a hacker gets both the hash and the Salt because a Rainbow Table will have to be generated from scratch using the Salt, which can take horrendous amounts of time, potentially on the order of a human life time or even longer for some hashing algorithms, password lengths and of course depending on how much raw computation an attacker can field.
Dictionary Attack
A Dictionary Attack is similar to the concept of a Rainbow Table in that it also utilizes a database, however where they differ is that a Rainbow Table’s purpose is to store pre-computed hashes so you can just lookup a password, whereas a Dictionary Attack still requires the attacker to break your password through hashing.
So from a Hackers perspective a Rainbow Table is preferable to a Dictionary.
The purpose of a Dictionary Attack then is to contain all the most likely passwords, which are then combined with your Salt (if they have it) or also generated as is the case with a Pepper before hashed to generate a new Rainbow Table that is unique to the Salt or Pepper.
This is a form of Brute Force attack and takes time to generate though it is still better than “true” brute force because it relies on the idea that words mean things and we all share the same words and meanings.
Anytime there is a massive breach of user credentials where the passwords are compromised… i.e. the passwords were kept as plain text or hashed using a single unchanged Salt, or simply too short of a salt for every password so all passwords in the database become compromised… all the compromised passwords get added to Dictionaries (and Rainbow Tables) because the passwords were used by someone so they are “known to be good” and are therefore more likely to be used by someone else.
Think of a Dictionary as a list of thousands to millions of “probable” common and known passwords.
The benefit of a Dictionary is that a hacker can focus on all the most likely passwords because people tend to think alike and of all the possible words that COULD be used for a password only a small subset will ever actually be selected by people.
Further, If the dictionary attack fails and the hacker must resort to True Brute Force, they can exclude the passwords in the Dictionary that they already tried and focus on a the Brute Force Attack by generating new previously untried passwords.
True Brute Force
The thing is, if Rainbow Tables and Dictionary Attacks failed to break your credentials then most hackers will give up and even the skilled professionals are forced to question the real value of their target because in most cases it’s not worth the hassle!
Having to resort to Brute force means that they tried EVERYTHING else and failed!
Your servers proved to be secure, your protocols are working, your “wetware” er… IT staff isn’t giving out credentials over the phone… and that “dumpster dive” the hackers took at 3 AM to see if your staff is throwing out documents with “sensitive” information, proved useless…
True Brute Force means that you take all typable letters:
Upper Case letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Lower Case letters: abcdefghijklmnopqrstuvwxyz
Symbols: !”#$%&'()*+,-./:;<=>?@[\]^_`{|}~
And while we’re at it why not include Numbers too: 0123456789
For a total of 94 possible characters and then starting with only 1 character, generate and iterate through all possible permutations until you give up or a solution is found!
This sounds easier to accomplish than it actually is!
Sure, generating the data is easy enough (I show you how and provide code below) but due to the sheer numbers involved it’s essentially an impossible task when considering the hash time is multiplied by all the combinations you have to try and a longer password means more combinations are required to break the hash.
This is why it is recommended by some technologists that your password include Upper and Lower case letters along with numbers and symbols and be longer than 15 characters!
Let’s do the math!
If there are 94 possible characters and a password is only 1 character long we would only need to try a maximum of 941 = 94 characters before we can guarantee we have the password.
In the case of a 3 character long password (943 = 830,584) we would have to try a little less than 1 million combinations!
This is simple exponentiation with the base being the number of symbols possible and the exponent is the length of the password.
Here’s a table:
Password Length | Combinations | Calculation |
1 | 94 | 941 |
2 | 8,836 | 942 |
3 | 830,584 | 943 |
4 | 78,074,896 | 944 |
5 | 7,339,040,224 | 945 |
6 | 689,869,781,056 | 946 |
7 | 64,847,759,419,264 | 947 |
8 | 6,095,689,385,410,816 | 948 |
9 | 572,994,802,228,617,000 | 949 |
10 | 53,861,511,409,490,000,000 | 9410 |
11 | 5,062,982,072,492,060,000,000 | 9411 |
12 | 475,920,314,814,253,000,000,000 | 9412 |
13 | 44,736,509,592,539,800,000,000,000 | 9413 |
14 | 4,205,231,901,698,740,000,000,000,000 | 9414 |
15 | 395,291,798,759,682,000,000,000,000,000 | 9415 |
Clearly a nice long password that contains upper and lower case letters along with numbers and symbols is definitely going to give your hacker a bad day though I personally prefer the idea of Passphrases which are a series of words in a phrase rather than a single word.
If the words you use in your passphrase are nice and long, have upper and lower case letters along with numbers and symbols and isn’t a well known phrase (so that it’s not in a phrase dictionary) then you can be fairly confident that your account is secure for the foreseeable future.
Breaker Class
So as you can see, I am not helping anyone break anything by giving out this code, your passwords are safe! 😉
Regular readers will notice in the code below I used my AppTimer Class that I released over on my Benchmarking PHP article.
Breaker has no properties and only 3 methods (not including PHP’s Magic Methods).
Methods: GetSymbols, IncrementValues & Match
GetSymbols()
GetSymbols converts the numbers in an array to the char the number represents.
For example: The number 0 represents the exclamation symbol ! and the number 33 represents uppercase B
IncrementValues()
IncrementValues takes an array of numbers and increments the values of each by 1 unless that would exceed the allowable max in which case it resets it to 0 and the value to the right is created or incremented by 1.
Match()
At this time, match just does a comparison though feel free to hash the values that are passed to this method to complete the Brute Force Attack program.
As is, this will only brute force plain text against plain text.
Breaker.php
<?php set_time_limit(0); // Disable the time limit on script execution // Create Breaker Class // // This tool is a demonstration of a "brute force" password breaker. // This prototype is provided AS IS and for informational & educational // purposes only! // // Modern Password Hashing should have little fear of this code though // for a minimum level of rationality I have excluded the parts that // would handle hashing the passwords to slow down the "Script Kiddies" // however any reasonably skilled PHP developer would have little trouble // adding their own hashing function to complete this prototype. // // DO NOT USE THIS SOFTWARE TO VIOLATE THE LAW! COMPLY WITH ALL DIRECTION // GIVEN TO YOU BY LAW ENFORCEMENT! ANY ILLEGAL OR MALICIOUS ACTIONS YOU // CHOOSE TO ENGAGE IN OUTSIDE OF AN EDUCATIONAL SETTING ARE YOUR OWN! class Breaker{ function GetSymbols($values, $symbols){ foreach($values as &$value){ if(isset($symbols[$value])){ $value = $symbols[$value]; } } return $values; } function IncrementValues($values, $number_of_valid_symbols){ foreach($values as $key=>&$value){ // If this value is maxed if($values[$key] >= $number_of_valid_symbols){ // Reset it to 0 and increment the next value $values[$key] = 0; // Reset this value if(!isset($values[$key+1])){ $values[$key+1] = '0'; }else{ $values[$key+1]++; // Reset this value } } else{ // If key greater than 0 if($key > 0){ if($values[$key-1]>$number_of_valid_symbols){ // Increment this value $values[$key]++; } } else{ // Always Increment this value $values[$key]++; } } } return $values; } function Match($hash, $test_password){ if($test_password == $hash){ return true; } return false; } } include('AppTimer.Class.php'); // Include AppTimer class file $Timer = new AppTimer(); // Create Timer $Timer->Start(); // Start() Timer $password_to_break = 'Cat'; // Concatenate all symbols explicitly //$valid_symbols = "!\"#$%&'()*+,-./0123456789:;<=>?@"; // note the escaped double quote //$valid_symbols .= "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`"; //$valid_symbols .= "abcdefghijklmnopqrstuvwxyz{|}~"; //$valid_symbols = str_split($valid_symbols); // split string into array // Cleaner way to Create array of ASCII char 33 - 126 $valid_symbols = range(chr(33), chr(126)); // Shorter version of above $number_of_valid_symbols = count($valid_symbols); // 94 chars $length = 1; // Start at 1 digit length to try all possible combinations // This assumes the password length is unknown. // If the length of the password is known then use the correct length i.e: // $length = strlen($password_to_break); // Generate first plain text password to try $values = str_split(strrev(str_repeat('0', $length))); $PlainTextPasswordBreaker = new Breaker(); $test_password = $PlainTextPasswordBreaker->GetSymbols($values, $valid_symbols); while(!$PlainTextPasswordBreaker->Match($password_to_break, $test_password)){ // We have not found the correct password so keep trying to generate it $values = $temp = $PlainTextPasswordBreaker->IncrementValues($values, $number_of_valid_symbols); $temp = $PlainTextPasswordBreaker->GetSymbols($values, $valid_symbols); $test_password = strrev(implode('', $temp)); //echo $test_password . PHP_EOL; // Uncomment to watch breaker // Will make Breaker much slower } $Timer->Stop(); // Stop() Timer $time = $Timer->Report(); // Report() echo "Password: $test_password \nFound in: $time" . PHP_EOL;
As presented the output of the code will look something like this:
Password: Cat
Found in: 5.8302 Seconds
If you uncomment the echo on line 105 inside the while loop you can watch each permutation get generated however echo will slow down the time it actually takes to find the password.
Here is what that would look like (note that I shortened the output to just the last few permutations before the solution was found):
...
Ca!
Ca"
Ca#
Ca$
Ca%
Ca&
Ca'
Ca(
Ca)
Ca*
Ca+
Ca,
Ca-
Ca.
Ca/
Ca0
Ca1
Ca2
Ca3
Ca4
Ca5
Ca6
Ca7
Ca8
Ca9
Ca:
Ca;
Ca
Ca?
Ca@
CaA
CaB
CaC
CaD
CaE
CaF
CaG
CaH
CaI
CaJ
CaK
CaL
CaM
CaN
CaO
CaP
CaQ
CaR
CaS
CaT
CaU
CaV
CaW
CaX
CaY
CaZ
Ca[
Ca\
Ca]
Ca^
Ca_
Ca`
Caa
Cab
Cac
Cad
Cae
Caf
Cag
Cah
Cai
Caj
Cak
Cal
Cam
Can
Cao
Cap
Caq
Car
Cas
Cat
Password: Cat
Found in: 14.9678 Seconds
USE BREAKER RESPONSIBLY FOR EDUCATIONAL PURPOSES ONLY!
You can find Breaker on my GitHub profile here.
You can find a list of all my other posts on my Topics and Posts page & I hope you enjoyed reading this article, if so please support me on Patreon for as little as $1 a month.
Your financial support allows me to dedicate time to developing awesome projects like this and while I am publishing them without cost, that isn’t to say they are free. I am doing this all by myself and it takes me a lot of time and effort to build and publish these projects for your enjoyment.
Your financial support means a lot to me and allows me to be able to afford to spend the time necessary to make great content for you.
So I ask again, please support me on Patreon for as little as $1 a month.
Feel free to suggest a project you would like to see built in the comments and if it sounds interesting it might just get built and featured here on my blog.
Much Love,
~Joy