Last active
August 3, 2022 20:28
-
-
Save mrik23/e8efe6dc9cdfe62c9d0bb84dc25288fa to your computer and use it in GitHub Desktop.
PowerShell script to check password against leaked password database from https://haveibeenpwned.com/ using the Pwned Passwords V2 API. Only the first 5 characters of the password string hash is checked against the API (k-anonymity). More info on the HIBP API at https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -version 4 | |
<# | |
.SYNOPSIS | |
Check password against leaked password database from https://haveibeenpwned.com/ using the Pwned Passwords V2 API https://api.pwnedpasswords.com/range/<hashPrefix>. | |
.DESCRIPTION | |
Only the first 5 characters of the password string hash is checked against the API (k-anonymity). The API returns a list of all passwords matching the hash prefix, then the script checks if the suffix is present or not. | |
More info on the HIBP API at https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/. | |
.PARAMETER Password | |
Enter the password to check. | |
.PARAMETER SecurePassword | |
Switch to enable secure prompt for password. | |
.EXAMPLE | |
.\Test-LeakedPasswordHIBP.ps1 -password "P@ssw0rd" | |
#> | |
[CmdletBinding()] | |
Param( | |
[Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] | |
[string]$Password, | |
[Parameter(Mandatory=$False)] | |
[switch]$SecurePassword | |
) | |
if ($SecurePassword) { | |
$Credentials = Get-Credential -Message "Enter the password to test" -UserName "dummy" | |
$Password = $credentials.GetNetworkCredential().Password | |
} else { | |
if ($Password -eq "") { | |
$Password = Read-Host -Prompt "Enter the password to test" | |
} | |
} | |
#Force TLS 1.2 | |
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 | |
#Create SHA-1 hash from string | |
Function Get-StringHash() | |
{ | |
[CmdletBinding()] | |
Param ( | |
[Parameter(Mandatory=$True)] | |
[String]$inputString | |
) | |
$Private:outputHash = [string]::Empty | |
$hasher = New-Object -TypeName "System.Security.Cryptography.SHA1CryptoServiceProvider" | |
$hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($inputString)) | ForEach-Object { $outputHash += $_.ToString("x2") } | |
$outputHash.ToUpper() | |
} | |
$stringHash = Get-StringHash -inputString $Password | |
$hashPrefix = $stringHash.Substring(0, 5) | |
$hashSuffix = $stringHash.Substring(5, ($stringHash.Length - 5)) | |
try { | |
$response = Invoke-RestMethod -Uri "https://api.pwnedpasswords.com/range/$($hashPrefix)" -Method Get -ErrorVariable errorRequest | |
} | |
catch { | |
Write-Output "Error with the request!" | |
Write-Output $errorRequest | |
break | |
} | |
if ($response -ne $null) { | |
$findHashSuffix = $response.Contains($hashSuffix) | |
if ($findHashSuffix -eq $true) { | |
$result = $response.Substring($response.IndexOf($hashSuffix), $response.IndexOf([System.Environment]::NewLine, $response.IndexOf($hashSuffix)) - $response.IndexOf($hashSuffix)) | |
$resultCount = ($result.Split(":"))[1] | |
Write-Output "Your password has been found $($resultCount) times!" | |
} | |
else { | |
Write-Output "Your password has not been found." | |
} | |
} | |
else { | |
Write-Output "No occurence of the hash prefix found." | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If anyone comes across the same issue: The script unfortunately fails on non-Windows machines, e.g. using PSCore on Linux. The failing line is 92, and related to the
Substring
.The reason is that
[System.Environment]::NewLine
returns back following:\r\n
\n
But as the HIBP API reports back the hashes splitted by the Windows line-endings, the
IndexOf
/Substring
at line 92 fails. The fix is quite simple: Just replace[System.Environment]::NewLine
on line 92 with`r`n
.