Tag Archives: passwords

Hashcat Masks

This article covers an alternative tool for the technique presented in Suggested Rules for Suggested Passwords. It uses Hashcat in place of the open source John the Ripper. Hashcat is free to use, but its source is not available.

Check out the previous article first. You’ll need the four example hash files that it contains. Then return here to run the same brute force using Hashcat.

Define a Custom Charset

We’ll use three of Hashcat’s predefined charsets to build the alphanumeric seed for our guesses. They are lowercase (?l), uppercase (?u), and digits (?d).

We only need one custom charset, which we’ll specify with the -1 option (the option’s long name is --custom-charset1). Make sure to enclose the charset string with single quotes, otherwise your shell may misinterpret the question marks. This example uses the 64-bit hashcat-cli64.app for OS X; the options are identical for Linux or Windows binaries.

-1 '?l?u?d'

Define a Mask

You can create a mask via command-line option. The custom charset is number one, i.e. ?1. (Not to be confused with lowercase ?l in this case.) We wish to build groups of triples. So the first step is to create a mask of three characters based on charset 1, like this:

‘?1?1?1’

In fact, that mask will produce guesses of one, two, and three characters in length. We only care about alphanumeric triples, so we’ll use the --pw-min option to specify a minimum password length of 3.

Verify the output with the --stdout option.

$ ./hashcat-cli64.app --stdout -m0 -a 3 -1 '?l?u?d' --pw-min=3 '?1?1?1' | less
aaa
baa
caa
daa
eaa
faa
gaa
haa
iaa

Now create a mask for the full format. It should be four groups of alphanumeric triples separated by dashes. Use the ?1 placeholder to reference the custom charset defined in the -1 option.

'?1?1?1-?1?1?1-?1?1?1-?1?1?1'

Verify the mask.

$ ./hashcat-cli64.app --stdout -m0 -a 3 -1 '?l?u?d' --pw-min=15 '?1?1?1-?1?1?1-?1?1?1-?1?1?1' | less
aaa-aaa-aaa-aaa
baa-aaa-aaa-aaa
caa-aaa-aaa-aaa

Start Guessing

Use the -m option to select the hashing algorithm. So far we’ve been using type 0, which corresponds to MD5.

$ ./hashcat-cli64.app -m0 -a 3 -1 '?l?u?d' --pw-min=15 safari_md5.txt '?1?1?1-?1?1?1-?1?1?1-?1?1?1'
Initializing hashcat v0.47 by atom with 8 threads and 32mb segment-size...

Added hashes from file safari_md5.txt: 8 (1 salts)

Now try the SHA-256 hash function, which is mode 1400.

$ ./hashcat-cli64.app -m1400 -a 3 -1 '?l?u?d' --pw-min=15 safari_sha256.txt ‘?1?1?1-?1?1?1-?1?1?1-?1?1?1'
Initializing hashcat v0.47 by atom with 8 threads and 32mb segment-size...

Added hashes from file safari_sha256.txt: 8 (1 salts)

Note the difference in cracking speed due to the target hashing method. Specific numbers will vary from system to system, but you’ll probably see the words/sec. drop in half when switching from MD5 to SHA-256. This kind of drop is desirable because it affects the work factor (the amount of effort measured in time and computing resources) required for an attacker to iterate guesses.

If a list of password hashes were stolen, you’d want the hashing algorithm to have a high work factor. There are additional methods like salting and algorithms like PBKDF2 that may also increase the work factor.

The choice of hashing algorithm won’t effectively protect weak passwords, whether they’re short (squ!d), use small character sets (8675309), or longer ones based on common words or phrases (221bBakerStreet). In other words, the best security is to prevent the hashed version of the password from being stolen in the first place.

Suggested Rules for Suggested Passwords

Web sites rely on passwords to authenticate users. It’s a way for users to prove who they claim to be — if you know an account’s password then you (are assumed to) own the account. Sites must protect passwords to prevent attackers from stealing them. Users must create strong passwords to prevent attackers from easily guessing them. The password suggestion feature of Safari 7 helps users do this. (Here are a few more ideas).

This case study demonstrates some of the features of John the Ripper, a password cracking tool. It gives a perspective on the strength of suggested passwords and reinforces why sites must manage passwords securely. The scenario assumes that a hacker has obtained a list of hashed passwords and they wish to target the format of Safari’s suggestions.

Safari suggests passwords that consist of four alphanumeric triples. This produces a 15-character password with 12 characters of entropy (the three dashes are static and predictable). They keyspace is 6212 (26 each of upper- and lower-case letters plus 10 digits), or about 271 if you prefer powers of 2.

With this in mind, let’s explore some of John’s features.

First, open the john.local.conf file and add the following line:

.include "$JOHN/john.ahtk.conf"

Now open the john.ahtk.conf file. Add custom rules from the following examples to this file.

Create a Charset File with an External Filter

John uses charset files when running in incremental mode. The charset file contains all the candidate symbols for a password, including probability measures based on position. John selects symbols based on filters and generates probabilities based on cracked passwords in its john.pot file.

Create a filter that extracts upper- and lower-case letters and numbers. Filters are defined by the filter() function that uses a subset of the C programming language.

[List.External:Filter_Alphanumeric]
void filter()
{
  int i, c;

  i = 0;
  while (c = word[i++]) {
    if(c < '0' || c > '9') {
      if((c < 'a' || c > 'z') && (c < 'A' || c > 'Z')) {
        word = 0;
        return;
      }
    }
  }
}

Create a charset based on this filter. Your john.pot file influences the quality of the probabilities associated with each symbol. In the following example, the charset is generated from over 3 million plaintext passwords.

$ ./john --make-charset=alphanumeric.chr —external=Filter_Alphanumeric john.pot
Loaded 3190632 plaintexts
Generating charsets... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 DONE
Generating cracking order... DONE
Successfully written charset file: alphanumeric.chr (62 characters)

Define an Incremental Rule

Create a rule called Alphanumeric12 to generate 12-character passwords based on the charset that’s just been created.

[Incremental:Alphanumeric12]
File = $JOHN/alphanumeric.chr
MinLen = 12
MaxLen = 12
CharCount = 62

Verify that the rule works by using the--stdout option to print brute force guesses.

$ ./john --stdout --incremental:Alphanumeric12 | less

Define a Transformation Rule

Create a rule that inserts a dash (-) after every three letters. The following rule uses the insert (i) command. The insert command’s syntax is iNX, which the John documentation explains as “insert character X in position N and shift the rest right”.

[List.Rules:AHTK_Safari]
i3-i7-iB-

Positions are 0-based (position 0 is before the first letter). Hence, we’ll insert a dash into positions 3, 7, and 11. Note that john requires a single-character position indicator, which means that position 11 needs a special representation (i.e. i11- would be invalid). John uses A-Z to represent positions 10 and greater, e.g. 11 maps to B.

Test your rule by piping the output of the incremental Alphanumeric12 rule into the AHTK_Safari rule. Your specific guesses will vary, but the output should be four triples separated by dashes.

$ ./john --stdout --incremental=Alphanumeric12 | ./john --rules=AHTK_Safari --pipe --stdout | less
lan-ist-ari-n12
lan-ist-ari-n11
lan-ist-ari-n01
lan-ist-ari-n08
lan-ist-ari-sta
lan-ist-ari-sto
lan-ist-ari-sha
lan-ist-ari-shi
lan-ist-ara-nce

Define a Word Generator with an External Rule

The previous technique that combined an incremental charset and a rule demonstrated some John concepts, but wasn’t the most efficient way to crack this password format.

John supports custom word generation using C functions similar to the filter() used previously. The init() function sets up global variables. The generate() function produces a guess based on the pre-defined word[] array.

The following rule generates four triples separated by dashes.

[List.External:AHTK_IncrementalSafari]
int alnum[63];
int character[15];
int length, maxlength;
int position;

void init()
{
  int c;
  int i;

  i = 0;
  alnum[0] = 'a';
  while(i < 26) {
    c = alnum[i++];
    alnum[i] = ++c;
  }
  alnum[26] = 'A';
  while(i < 52) {
    c = alnum[i++];
    alnum[i] = ++c;
  }
  alnum[52] = '0';
  while(i < 62) {
    c = alnum[i++];
    alnum[i] = ++c;
  }
  alnum[62] = 0;

  length = 15;
  maxlength = 15;
  position = length - 1;
  i = 0;

  while(i < length) {
    character[i] = 0;
    word[i] = alnum[character[i]];
    ++i;
  }
  --character[length - 1];
  --word[length - 1];
  word[length] = 0;

  word[3] = '-';
  word[7] = '-';
  word[11] = '-';
}

void generate()
{
  while(++character[position] > 61) {
    if(position) {
      character[position] = 0;
      word[position] = alnum[character[position]];
      --position;
      if(3 == position || 7 == position || 11 == position)
        --position;
    }
    else {
      word = 0;
      return;
    }
  }

  word[position] = alnum[character[position]];
  position = length - 1;
}

Test your rule with the --stdout option. The output should be identical to the following:

$ ./john --stdout --external=AHTK_IncrementalSafari | less
aaa-aaa-aaa-aaa
aaa-aaa-aaa-aab
aaa-aaa-aaa-aac
aaa-aaa-aaa-aad
aaa-aaa-aaa-aae
aaa-aaa-aaa-aaf
aaa-aaa-aaa-aag
aaa-aaa-aaa-aah
aaa-aaa-aaa-aai

Try Some Test Cases

Create the following four text files.

c5641fff11e90e5f1dec0dcb215207e815793620578ee7a6d709b43e2e139faa  
200d4f7d57bfa369a515b0c15563fba4a9d0df95a395ea2bc5058bfc56fd9fcb  
d5c5d9a1c6cd8e37d7c6dd6b6d1e9e7a618d28c44002af22158c6f4571cf9376  
9a3be48a96a21f86f6b7bf304a2a32ce749be855892eba0a20b922bd95aefa59 
c7133b40c5c9893430dd4775313dbe05308b3cd1824c1aa76a4307e0f58b04f6  
b7130b809bdb569ec279ce29148c261c9b3bfbe5b992edcfbf07269f404b1053  
62b25ca5aaee38e0b5214a8b08742fac311c4f2716ee50d25107ec2703b3e550
eebc150c1a79857fbe8482ffe5204c87ae2fe2e5aca87f9c82cab4276f98a964
a520fc129149257ad346548e698a18e4a62ec3da  
1e92c0f5d1dcbd2deff35760add6ea85db219cd1  
53e9af8d56b95bcb4ad69302dcc6380a70d8e66e  
ea8d03ae07a783800a2063f8284389cc3f2816d6 
8a77b690d5505143e913de68cfdac6e7fb7ba795  
7139c395c944d604469cf49353f40f98c9eb2d5e  
d9c60792218aeca55b18ea07374713f4f585eaf8
3fe8e5ce4f442fc4b3ab0a67868e0291d3e6cf5c
d0b51b6b9bce4a3ccfc088da0f37ee12
4405ebb8805a3ca097bbe49b5008b257
f6787c37375ee68a165defb30c2f6c17
0ffcf48533340110e584717eadbc9052
f0b44a076f0b34007c7bd6acc660bc8f
806a51455895160f7185e38a69272123
6ca3209cfbbc6019e4220b5f9e17f507
7828d23661dd05d628bfb9a2f94a6bc8
7edb3366cef77b22b0502087bd6b2886  
35b9ab5a36f3234dd26db357fd4a0dc1 
45e4812014d83dde5666ebdf5a8ed1ed  
057cea2fc37aabd4a59462d3fd28c93b  
1722442b586a85c95593a9c6131a0ebd  
64b6c5e0211c7450739c6e2212da8f49  
3d47be610143842dd6da774889a4a05b
2d08519ae6e58f1deba11dcfefd16168

Now try the combined incremental/transform rules. Remember that it’s up to the web site to store passwords securely. The following examples demonstrate the relative cracking speed for different hashing algorithms. A real web app should store the hashed value of a password based on at least an hmac or, even better, PBKDF2 (with well-chosen parameters). But that’s out of scope for this discussion.

$ ./john --stdout --incremental=Alphanumeric12 | ./john --rules=AHTK_Safari --pipe --format=raw-sha256 safari_sha256.txt

$ ./john --stdout --incremental=Alphanumeric12 | ./john --rules=AHTK_Safari --pipe --format=raw-sha1 safari_sha1.txt

$ ./john --stdout --incremental=Alphanumeric12 | ./john --rules=AHTK_Safari --pipe --format=raw-md5 safari_md5.txt

To prove the point that the dashes do not increase entropy, the following command runs a brute force against 12-character passwords.

$ ./john --incremental=Alphanumeric12 --format=raw-md5 safari_no_dash_md5.txt

Finally, try each of the example sets against your custom generator.

$ ./john --external=AHTK_IncrementalSafari --format=raw-sha256 safari_sha256.txt 
Loaded 8 password hashes with no different salts (Raw SHA-256 [32/64])

The generator will be slightly faster and may seem more elegant than the piping technique. However, the order of guesses will be different because the charset-based approach creates sequences in a statistical order (based on observed passwords) whereas the custom generator works in lexicographic order (e.g. aaa, aab, aac, …). In practice, the distribution of characters in suggested passwords should be uniform. So, neither approach should be superior. They will both eventually exhaust the keyspace —- but not in any reasonable or feasible time.

That’s all for now. There’s plenty more to talk about regarding password security, let alone other security topics. Security has a keyspace of concepts that I won’t be exhausting any time soon.