Detecting compromised passwords

July 19, 2021

Yes, dear hearts, the bad guys do have extensive dictionaries of passwords that either are commonly used or have been compromised. One of the most effective ways of brute-forcing passwords is to use these dictionaries to perform a dictionary attack. This is when the password-cracking tool reads in passwords from a specified dictionary and tries each one until either the list has been exhausted, or until the attack is successful. So, how do you know if your password is on one of those lists? Easy. Just use one of the online services that will check your password for you. One popular site is Have I Been Pwned?, which you can see here:

compromised passwords

All you really have to do is to type in your password, and the service will show if it’s on any lists of compromised passwords. But think about it. Do you really want to send your production password to somebody’s website? Yeah, I thought not. Instead, let’s just send a hash value of the password. Better yet, let’s just send enough of the hash to allow the site to find the password in its database, but not so much that they can figure out what your exact password is. We’ll do that by using the Have I Been Pwned? Application Programming Interface (API).

To demonstrate the basic principle, let’s use curl, along with the API, to see a list of password hashes that have 21BD1 as part of their values. (You can do this on any of your virtual machines. I’ll just do it on the Fedora workstation that I’m currently using to type this.) Just run this:

$ curl https://api.pwnedpasswords.com/range/21BD1

You’re going to get a lot of output like this, so I’ll just show the first few lines:

[donnie@fedora-teaching ~]$ curl https://api.pwnedpasswords.com/range/21BD1
0018A45C4D1DEF81644B54AB7F969B88D65:1
00D4F6E8FA6EECAD2A3AA415EEC418D38EC:2
011053FD0102E94D6AE2F8B83D76FAF94F6:1
012A7CA357541F0AC487871FEEC1891C49C:2
0136E006E24E7D152139815FB0FC6A50B15:3
01A85766CD276B17DE6DA022AA3CADAC3CE:3
024067E46835A540D6454DF5D1764F6AA63:3
02551CADE5DDB7F0819C22BFBAAC6705182:1
025B243055753383B479EF34B44B562701D:2
02A56D549B5929D7CD58EEFA97BFA3DDDB3:8
02F1C470B30D5DDFF9E914B90D35AB7A38F:3
03052B53A891BDEA802D11691B9748C12DC:6
. . .
. . .

Let’s pipe this into wc -l, a handy counting utility, to see how many matching results we’ve found:

[donnie@fedora-teaching ~]$ curl https://api.pwnedpasswords.com/range/21BD1 | wc -l
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 20592 0 20592 0 0 197k 0 --:--:-- --:--:-- --:--:-- 199k
526
[donnie@fedora-teaching ~]$

According to this, we’ve found 526 matches. But that’s not very useful, so let’s fancy things up just a bit. We’ll do that by creating the pwnedpasswords.sh shell script, which looks like this:

#!/bin/bash
candidate_password=$1
echo "Candidate password: $candidate_password"
full_hash=$(echo -n $candidate_password | sha1sum | awk '{print substr($1, 0, 32)}')
prefix=$(echo $full_hash | awk '{print substr($1, 0, 5)}')
suffix=$(echo $full_hash | awk '{print substr($1, 6, 26)}')
if curl https://api.pwnedpasswords.com/range/$prefix | grep -i $suffix;
then echo "Candidate password is compromised";
else echo "Candidate password is OK for use";
fi

Okay, I can’t try to turn you into a shell scripting guru at the moment, but here’s the simplified explanation:

  • candidate_password=$1: This requires you to enter the password that you want to check when you invoke the script.
  • full_hash= , prefix=, suffix=: These lines calculate the SHA1 hash value of the password, and then extract just the portions of the hash that we want to send to the password-checking service.
  • if curl: We wrap up with an if..then..else structure that sends the selected portions of the password hash to the checking service, and then tells us whether or not the password has been compromised.

After saving the file, add the executable privilege for the user, like so:

$ chmod u+x pwnedpasswords.sh

Now, let’s see if TurkeyLips, my all-time favorite password, has been compromised:

[donnie@fedora-teaching ~]$ ./pwnedpasswords.sh TurkeyLips
Candidate password: TurkeyLips
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 09FDEDF4CA44D6B432645D6C1D3A8D4A16BD:2
100 21483 0 21483 0 0 107k 0 --:--:-- --:--:-- --:--:-- 107k
Candidate password is compromised
[donnie@fedora-teaching ~]$

Yeah, it’s been compromised, all right. So, I reckon that I don’t want to use that for a production password. 

Now, let’s try it again, except with a random two-digit number tacked on at the end:

[donnie@fedora-teaching ~]$ ./pwnedpasswords.sh TurkeyLips98
Candidate password: TurkeyLips98
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 20790 0 20790 0 0 110k 0 --:--:-- --:--:-- --:--:-- 110k
Candidate password is OK for use
[donnie@fedora-teaching ~]$

Well, it says that this one is okay. Still though, you probably don’t want to use such a simple permutation of a password that’s known to have been compromised.

Now, having said all of this, I still need to remind you that a passphrase is still better than a password. Not only is a passphrase harder to crack, it’s also much less likely to be on anyone’s list of compromised credentials.

Hands-on lab for detecting compromised passwords

In this lab, you’ll use the pwnedpasswords API in order to check your own passwords:

  • Use curl to see how many passwords there are with the 21BD1 string in their password hashes:
$ curl https://api.pwnedpasswords.com/range/21BD1
  • In the home directory of any of your Linux virtual machines, create the pwnpassword.sh script with the following content:
#!/bin/bash
candidate_password=$1
echo "Candidate password: $candidate_password"

full_hash=$(echo -n $candidate_password | sha1sum | awk '{print substr($1, 0, 32)}')
prefix=$(echo $full_hash | awk '{print substr($1, 0, 5)}')
suffix=$(echo $full_hash | awk '{print substr($1, 6, 26)}')

if curl https://api.pwnedpasswords.com/range/$prefix | grep -i $suffix;
then echo "Candidate password is compromised";
else echo "Candidate password is OK for use";
fi
  • Add the executable permission to the script:
$ chmod u+x pwnedpasswords.sh
  • Run the script, specifying TurkeyLips as a password:
./pwnedpasswords.sh TurkeyLips
  • Repeat Step 4 as many times as you like, using a different password each time.

What we’ve looked at so far works great on a small number of computers. But what if you’re working in a large enterprise? We’ll look at that next.

Related Articles

How to add swap space on Ubuntu 21.04 Operating System

How to add swap space on Ubuntu 21.04 Operating System

The swap space is a unique space on the disk that is used by the system when Physical RAM is full. When a Linux machine runout the RAM it use swap space to move inactive pages from RAM. Swap space can be created into Linux system in two ways, one we can create a...

read more

Lorem ipsum dolor sit amet consectetur

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

five + 6 =