Added new post: password checking script write-up
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
title: "Password Checking Script"
|
title: "Password Checking Script"
|
||||||
date: 2019-04-13
|
date: 2019-04-13
|
||||||
lastmod: 2019-04-13
|
lastmod: 2019-04-13
|
||||||
draft: true
|
|
||||||
tags: ["linux","code"]
|
tags: ["linux","code"]
|
||||||
categories: ["Blog"]
|
categories: ["Blog"]
|
||||||
contentCopyright: false
|
contentCopyright: false
|
||||||
@@ -17,6 +16,10 @@ script with the following goals:
|
|||||||
|
|
||||||
<!--more-->
|
<!--more-->
|
||||||
# Preface
|
# Preface
|
||||||
|
The full **source code** for this script can be found in my public scripts
|
||||||
|
repository:
|
||||||
|
[scripts/bash/pass-check.sh](https://gitlab.com/bdebyl/scripts/blob/master/bash/pass-check.sh)
|
||||||
|
|
||||||
It's worth nothing that I use [`passwordstore`](https://www.passwordstore.org/)
|
It's worth nothing that I use [`passwordstore`](https://www.passwordstore.org/)
|
||||||
to generate, and manage my passwords. On mobile, this is done using the official
|
to generate, and manage my passwords. On mobile, this is done using the official
|
||||||
[OpenKeychain](https://www.openkeychain.org/), and
|
[OpenKeychain](https://www.openkeychain.org/), and
|
||||||
@@ -26,8 +29,8 @@ shared across my devices using Git[^2]
|
|||||||
# Pump Your Brakes
|
# Pump Your Brakes
|
||||||
Instead of jumping right into checking all my passwords, in plain-text, against
|
Instead of jumping right into checking all my passwords, in plain-text, against
|
||||||
the `pwnedpasswords` API, it would be best to figure out how to safely transform
|
the `pwnedpasswords` API, it would be best to figure out how to safely transform
|
||||||
them to `sha1sum`[^3]. The API supports sending the first 5 characters of a `sha1sum`,
|
them to SHA-1[^3]. The API supports sending the first 5 characters of a SHA-1
|
||||||
returning a list of all `sha1sum`s of exposed passwords (_with the exposed
|
hash, returning a list of all SHA-1s of exposed passwords (_with the exposed
|
||||||
count_) for the user to verify them on their end.
|
count_) for the user to verify them on their end.
|
||||||
|
|
||||||
# Gathering Passwords
|
# Gathering Passwords
|
||||||
@@ -56,7 +59,7 @@ treated in a special way (_also good practice!_)[^5]
|
|||||||
|
|
||||||
It may be worth mentioning, to folks less familiar with `awk`, that the
|
It may be worth mentioning, to folks less familiar with `awk`, that the
|
||||||
`FNR==1`, in this context, simply helps to get rid of any newline oddities from
|
`FNR==1`, in this context, simply helps to get rid of any newline oddities from
|
||||||
being piped into `sha1sum`. I discovered incorrect `sha1sum` values **without**
|
being piped into `sha1sum`. I discovered incorrect `sha1sum` outputs **without**
|
||||||
`FNR==1` resulting in a useless password check!
|
`FNR==1` resulting in a useless password check!
|
||||||
|
|
||||||
{{% admonition note Note %}}
|
{{% admonition note Note %}}
|
||||||
@@ -98,9 +101,76 @@ getpws()
|
|||||||
This accomplishes our *first goal* of checking duplicate passwords --
|
This accomplishes our *first goal* of checking duplicate passwords --
|
||||||
**hooray!**
|
**hooray!**
|
||||||
|
|
||||||
Next up: _Passwortstärke_
|
# Passwortstärke
|
||||||
|
The simplest method of password strength checking, with indications as to _why_
|
||||||
|
it's weak (_i.e. "Exists in attack dictionary", "Too short", etc._) was to use
|
||||||
|
[`cracklib`](https://github.com/cracklib/cracklib). Sadly, it's not the most
|
||||||
|
well-documented or fully-fledged application to fully determine password
|
||||||
|
strength though for my purposes it will be good enough (_I don't care to write
|
||||||
|
my own version of this, yet.._).
|
||||||
|
{{% admonition note Note %}}
|
||||||
|
I made this part of the script **optional**, as not every user would want to
|
||||||
|
install `cracklib` on their system.
|
||||||
|
{{% /admonition %}}
|
||||||
|
|
||||||
# TODO
|
This addition was made in the following order:
|
||||||
|
|
||||||
|
1. First, we need to find the executable **and** create _yet another_ useful
|
||||||
|
associative array for us to store the outputs (_a.k.a. messages_):
|
||||||
|
```bash
|
||||||
|
CRACKLIB=$(command -v cracklib-check)
|
||||||
|
declare -A pwscracklib
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Then a convenient function to iterate over all found passwords, safely
|
||||||
|
"expose" them, and run the check storing all **relevant** "outputs":
|
||||||
|
```bash
|
||||||
|
# Run through the global pws associative array and check for suggestions
|
||||||
|
checkcracklib()
|
||||||
|
{
|
||||||
|
for i in "${!pws[@]}"; do
|
||||||
|
msg=$(pass "$i" | awk 'FNR==1 {printf "%s", $0}' | $CRACKLIB | sed s/^.*:[\ \\t]*//)
|
||||||
|
if [[ ! "$msg" =~ "OK" ]]; then
|
||||||
|
pwscracklib["$i"]="$msg"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Done! It's _that_ easy.
|
||||||
|
|
||||||
|
# Have you been Pwned
|
||||||
|
The last, but **most important**, step was to add the actual check against the
|
||||||
|
`pwnedpass` API check! This gets a bit fun as we use
|
||||||
|
[Shell Parameter Expansion](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html)
|
||||||
|
to trim the first five, and everything _after_ the first five, characters of the
|
||||||
|
full SHA-1 string.
|
||||||
|
|
||||||
|
We need to get the full SHA-1 hash of each password, to then query the API using
|
||||||
|
**only the first 5 characters** of the SHA-1 hash! We will get a list of each
|
||||||
|
exposed (_"pwned"_) password's SHA-1 hash, and the amount of times they have
|
||||||
|
been leaked as a response. The prefix of the first 5 characters is dropped in
|
||||||
|
this list, thus we check for a match of our password using everything after the
|
||||||
|
first 5 characters of the SHA-1 hash and we're done!
|
||||||
|
```bash
|
||||||
|
# Check passwords against the HIBP password API (requires internet)
|
||||||
|
checkpwnapi()
|
||||||
|
{
|
||||||
|
for i in "${!pws[@]}"; do
|
||||||
|
# Check the pwnedpasswords API via hashing
|
||||||
|
pwsha="${pws[$i]}"
|
||||||
|
url="https://api.pwnedpasswords.com/range/${pwsha:0:5}"
|
||||||
|
res=$(curl -s "$url" | grep "${pwsha:5}")
|
||||||
|
if [ "$res" ]; then
|
||||||
|
pwunsafe["$i"]=$(printf "%s" "$res" | awk -F ':' '{printf "%d", $2}')
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! The left was to add some fun, colorful `printf`s as part of the final
|
||||||
|
output report. Feel free to look at the source code mentioned in the **Preface**
|
||||||
|
to see more details on this as it wasn't worth including in the write-up.
|
||||||
|
|
||||||
[^1]: [Have I Been Pwned](https://haveibeenpwned.com/Passwords)
|
[^1]: [Have I Been Pwned](https://haveibeenpwned.com/Passwords)
|
||||||
[^2]: [`pass` Extended Git Example](https://git.zx2c4.com/password-store/about/#EXTENDED%20GIT%20EXAMPLE)
|
[^2]: [`pass` Extended Git Example](https://git.zx2c4.com/password-store/about/#EXTENDED%20GIT%20EXAMPLE)
|
||||||
|
|||||||
Reference in New Issue
Block a user