GOTCHA Challenge
We envision a
rich interaction between the security community and the artificial intelligence
community. To facilitate this interaction we present an open challenge to break
our Inkblot-matching GOTCHA construction.
To set up the challenge
we selected five random passwords Pw1,Pw2,Pw3,Pw4 and
Pw5. Pw1,Pw2,Pw3 and Pw4 were chosen uniformly at random from the integer range
[0,107], and Pw5 was chosen uniformly at random from the integer
range [0,108]. We created accounts using each password. To simulate
an offline dictionary attack --- resulting from a server breach --- we are
releasing the password files associated with each account.
The password file for each account was generated by the function
storePassword(int pwd, string [] labels). These password files are stored in the file
PasswordFile.resx in the C# [Source Code].
We give the password file from account 1 as an example. The first line is a
BCRYPT hash value, which is one of the required parameters for the function verifyPassword(int pwd, int[]
permutation, string pwdHashBCrypt). The following lines are the labels we
created for ten inkblot images I1,…,I10
--- stored in permuted order. The Inkblot images I1,…,I10 were generated by running generatePuzzles(Pw1).
To verify that our password Pw1 is correct we would first run generatePuzzles(Pw1)
to recover the Inkblot images I1,…,I10, and then we would
match the labels below to recover the permutation --- the final required
parameter for verifyPassword. For example, if we
matched image I1 with the eighth label “large steroid insect with
big eyes” then we would set permutation[7] = 0.
Password File 1 |
$2a$15$kQllswv6yMGdRHbnPY6qzeH5m5uqTluGOKoUzj0tz6jlU.b8YN9DG body builder
lady with mustache and goofy in the center stern old guy
staring at me grasshopper
with big legs and wide-narrow head cone headed
king large lady with
fat face, mustache and bugs on stomach big viking guy with freckles really long
face that looks like a nose large steroid
insect with big eyes red eyed cow
running towards me warrior with
pink necklace |
Challenge: Break each password offline.
Approaches: One way to accomplish this goal would be to
enumerate over every possible password guess pw’ and compare hash values for
every possible permutation 𝛑:[10]-->[10]. However, the goal of this challenge is to see if
Artificial Intelligence techniques can be applied to attack our GOTCHA construction.
We intentionally selected our passwords from a smaller space to make the
challenge more tractable for AI based attacks, but to discourage participants
from trying to brute force over all password/permutation pairs we used the
BCRYPT hash function with Level 15 --- a very expensive hash function --- to
encrypt the passwords. Our implementation allows the Inkblot images to be
generated very quickly from a password guess pw' so an AI program that can use
the labels in the password file to distinguish between the correct Inkblots
returned by generatePuzzles(Pw1) and incorrect Inkblots returned by generatePuzzles(pw’)
would be able to quickly dismiss incorrect guesses. Similarly, an AI
program which generates a small set of likely permutations for each password
guess could allow an attacker to quickly dismiss incorrect guesses.
Challenge Results
Update: There was a bug in the
original challenge which allowed attackers to find the passwords directly
without solving any GOTCHA challenge. The culprit? I
forgot to remove actual inkblot images from the debug folder. This allowed an
attacker to directly verify a password guess by generating the corresponding
Inkblot images and comparing them with the actual inkblot images that the user
labeled. While this attack is easy to prevent (e.g., don’t save the original
inkblot images), it does serve as a valuable reminder about the importance of operational
security.
Credit: Thanks to Peter Kosinar and Ruxandra Olimid for pointing out this attack.
Fix: We have generated several
new password challenges (I am not including the original Inkblot images this
time!). Pw6,Pw7,Pw8 and Pw9 were chosen uniformly at
random from the integer range [0,107], and Pw10 was chosen uniformly
at random from the integer range [0,108].
(Challenges
6,7 and 10 have been released. Challenges 8 and 9 will
be released soon!)
|
Password |
Winner |
Institution |
Date Solved |
Example |
123456 |
Harry Q. Bovik |
Carnegie Mellon
University |
7/17/2013 |
Challenge 1 |
1258136 |
Peter Kosinar |
11/10/2013 |
|
Challenge 2 |
9945047 |
Peter Kosinar |
11/10/2013 |
|
Challenge 3 |
6868913 |
Peter Kosinar |
11/10/2013 |
|
Challenge 4 |
6523034 |
Peter Kosinar |
11/10/2013 |
|
Challenge 5 |
29157600 |
Ruxandra Olimid |
Department of Computer Science, University of Bucharest,
Romania |
11/11/2013 |
Challenge 6 |
Unsolved |
N/A |
N/A |
N/A |
Challenge 7 |
Unsolved |
N/A |
N/A |
N/A |
Challenge 8 |
Unsolved |
N/A |
N/A |
N/A |
Challenge 9 |
Unsolved |
N/A |
N/A |
N/A |
Challenge 10 |
Unsolved |
N/A |
N/A |
N/A |
Source Code
The source code
for the challenge was written in the C# programming language [Source Code].
In particular
there are three methods to take note of: generatePuzzles,
verifyPassword and storePassword.
The source code for these functions is found in the file GOTCHA_Challenge.cs.
/// <summary>
/// Generates n
Inkblot puzzles of using the password pwd
/// as a source of
randomness.
/// <param name="pwd">The password
provides the source of
/// randomness.</param>
/// <param name="width">Width of the Inkblot Puzzle
/// (use width = 500)</param>
/// <param name="height">Height of the Inkblot Puzzle
/// (use height = 500)</param>
/// <param name="n">Number
of Inkblot Puzzles to Generate
/// (use n = 10)</param>
/// <returns>An
array of Inkblot images</returns>
/// </summary>
public
static Bitmap[]
generatePuzzles(int pwd, int width=500, int height=500, int n=10)
/// <summary>
/// Verifies
whether or not the password pwd is correct.
/// <param name="pwd">The password to
verify</param>
/// <param name="permutation">The
solution to the Inkblot
/// matching challenge</param>
/// <param name="pwdHashBCrypt">The BCRYPT hash value of the original
/// password and permutation</param>
/// <returns>True if pwd is correct, otherwise false.</returns>
/// </summary>
public static Boolean verifyPassword(int pwd, int[] permutation, string pwdHashBCrypt)
/// <summary>
/// Hashes the password pwd. Before the
password is hashed a random permutation
/// is generated and appended to the
password. The hash value is stored in the
/// returned value along with the labels
(in permuted order).
/// <param name="pwd">The password</param>
/// <param name="labels"> The human's labels for the
Inkblot images returned
/// by generatePuzzles(500,500,10,pwd)</param>
/// <returns>
/// A string s, whose first line
contains the BCRYPT hash of pwd with the
/// permutation appended. The labels are
stored on the following lines
/// in permuted order.
/// </returns>
/// </summary>
public static string storePassword(int pwd, string [] labels)
Example
The project file
also contains the two forms: Create_Account and Authenticate.
The password files in PasswordFile.resx were
generated using the form Create_Account, and the form
Authenticate is used to validate a password guess.
To provide a
concrete example we used the Create Account form to create an example account with
the password Pw0 = 123456. After entering the password 123456 we clicked on
Generate Puzzles to generate ten inkblot images I1,…,I10
using the function generatePuzzles(123456), and we created labels for
each Inkblot image. In non-permuted order the labels for the ten Inkblot images
are:
1. lady with pink bowtie and purple mustache (Inkblot1.jpg)
2. ugly narrow eyed person puckering up for a
kiss (Inkblot2.jpg)
3. bees on top fling towards each other, big U
in the middle (Inkblot3.jpg)
4. robot on a skateboard like thing (Inkblot4.jpg)
5. square faced guy with big nose and short
yellow hair fuzz (Inkblot5.jpg)
6. hulk guy with tiny boxing gloves through the
waist (Inkblot6.jpg)
7. The letter H (Inkblot7.jpg)
8. lipstick on a lady who takes steroids (Inkblot8.jpg)
9. linebacker with mustache and yellow nose (Inkblot9.jpg)
10.little birdies facing eachother
on the bottom and little bees flying away from eachother
on top (Inkblot10.jpg)
We then clicked
on the Generate Password File button to generate the following password file
--- by running storePassword(123456, new string []{“lady
with pink bowtie and purple mustache”,…,”little
birdies facing eachother on the bottom and little
bees flying away from eachother on top”}).
Example
Password File |
$2a$15$mxBNEQ16k5bUgIvRr/JXOuGMzY9ymiJU.S4TX196mXOCLt4mY1Wbm lipstick on a lady
who takes steroids linebacker with
mustache and yellow nose hulk guy with
tiny boxing gloves through the waist bees on top
fling towards each other, big U in the middle little birdies
facing eachother on the bottom and little bees
flying away from eachother on top robot on a
skateboard like thing lady with pink
bowtie and purple mustache The letter H square faced
guy with big nose and short yellow hair fuzz ugly narrow
eyed person puckering up for a kiss |
To authenticate the
user would use the form Authenticate. We first select the account “Example (pw
is 123456)”, enter the password 123456, and click Generate Puzzles. Finally,
the user would match the labels with the appropriate Inkblots and click Check
Password. The computer uses the matching to recover the permutation (int [] permutation = {7,8,5,2,9,3,0,6,4,1}), and verify
that the password and matching are correct --- by running verifyPassword(123456, new int[]{7,8,5,2,9,3,0,6,4,1}, “$2a$15$mxBNEQ16k5bUgIvRr/JXOuGMzY9ymiJU.S4TX196mXOCLt4mY1Wbm”).