Scripting: Fetching Passwords from HaveIBeenPwned.com
HaveIBeenPwned.com contains email addresses associated with Internet database breaches. It also contains a database of passwords used in those breaches, so it is possible to check the “quality” of a password by its incidence in the database. For example, “123456” is used very frequently and is therefore a very poor password which should never be used.
To use the API to fetch information requires passing the hash of the password, which can be achieved as follows:
- Determine the hash of the password in question. Windows does not contain a function which can determine the hash of an arbitrary string, but it can determine the hash of a file. So output the desired password to a file. However, just using echo is not suitable for this purpose as an echo command will append a line break/carriage return to the file which causes an incorrect hash to be calculated. Therefore a different syntax is required:
echo|set /p="%PasswordLookup%"> %temp%\Hash.tmp
for /f "skip=1 tokens=1-20 delims=: " %%a in ('certutil -hashfile %temp%\Hash.tmp') do if /i '%%a NEQ 'certutil set Hash=%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t
echo Hash is %Hash%
This will return b2e98ad6f6eb8508dd6a14cfa704bad7f05f6fb1.
(CertUtil returns the hash differently for different versions of Windows. Windows 10 returns the hash in one string; earlier versions show 20 2-character hexademical values. Hence the need to concatenate 20 items parsed from the output. Thus, on Windows 10, only the first parameter “%%a” has a value, but this syntax works on all versions.)
- Next, query the HaveIBeenPwned.com service with the first five characters of the hash. This returns a page containing all of the hashes that match:
powershell.exe (new-object System.Net.WebClient).DownloadFile('https://api.pwnedpasswords.com/range/%Hash:~0,5%','%temp%\Hash.tmp')
(%Hash:~0,5% returns the first five characters of %Hash%.)
This will return a list which contains the remainder of the hashes (without the first five characters):
- Now parse the results for the specific hash (without the first five characters) and extract the occurrences:
for /f "skip=2 tokens=1,* delims=:" %%x in ('find /i "%Hash:~5%" %temp%\Hash.tmp') do set OccurrencesFound=%%y
if defined OccurrencesFound (echo '%PasswordLookup%' was found %OccurrencesFound% times) else (echo '%PasswordLookup%' was not found)