From 2f4893e60f5e261acd974fd242256086f557753a Mon Sep 17 00:00:00 2001 From: Hugh <8828244+hkelley@users.noreply.github.com> Date: Sun, 16 Apr 2023 20:45:26 -0400 Subject: [PATCH] Added cmdlet for API-based check against haveibeenpwned.com --- HelperFuncs.ps1 | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ demo.ps1 | 4 +++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/HelperFuncs.ps1 b/HelperFuncs.ps1 index 8be89cc..787bc63 100644 --- a/HelperFuncs.ps1 +++ b/HelperFuncs.ps1 @@ -18,6 +18,11 @@ Function Format-NTHash { [Parameter(Mandatory)] $NTHash ) + if([string]::IsNullOrEmpty($NTHash)) + { + return $null + } + return [System.BitConverter]::ToString($NTHash).Replace("-","") } @@ -273,7 +278,57 @@ function Test-HashesAgainstList { } } +function Test-HashesAgainstPwndPasswords +{ + [CmdletBinding()] + param( + [Parameter(Mandatory)] $TestSet # from Get-ADHashes + ) + + $hashCache = @{} + + # Get only the values we haven't already marked + $testSubset = $TestSet.Values.GetEnumerator() | ?{$null -eq $_.Condition } + + foreach($user in $testSubset) + { + [string] $hash = Format-NTHash -NTHash $user.Replica.NTHash + + if($hashCache[$hash] -eq $true) + { + $user.Condition = "leaked" + $user.Context = "api.pwnedpasswords.com" + } + elseif ($hashCache[$hash] -eq $false) + { + # Hash has already been checked and was not matched + continue + } + else + { + $hashRange = $hash.Substring(0,5) + $hashRemainder = $hash.Substring(5,$hash.Length - 5) + $url = "https://api.pwnedpasswords.com/range/{0}?mode=ntlm" -f $hashRange + if($rangeMatches = Invoke-RestMethod -Uri $url) + { + # find a match for our remainder + $rangeMatches = $rangeMatches -split '\r\n' + if($rangeMatches | ?{$_ -like "${hashRemainder}:*" }) + { + $hashCache[$hash] = $true + $user.Condition = "leaked" + $user.Context = "api.pwnedpasswords.com" + } + else + { + $hashCache[$hash] = $false + } + } + } + } + +} function Test-HashesForPasswordReuse { [CmdletBinding()] diff --git a/demo.ps1 b/demo.ps1 index 1092776..839d109 100644 --- a/demo.ps1 +++ b/demo.ps1 @@ -15,7 +15,9 @@ Test-HashesWithHashcat -TestSet $testset -ShowOutput -HashcatDir " ## Second, check for the presence on a banned list -Test-HashesAgainstList -TestSet $testset -BadHashesSortedFile E:\Utils\haveibeenpwned.com\pwned-passwords-ntlm-ordered-by-hash-v7.txt +#Test-HashesAgainstList -TestSet $testset -BadHashesSortedFile E:\Utils\haveibeenpwned.com\pwned-passwords-ntlm-ordered-by-hash-v7.txt +# or new method +Test-HashesAgainstPwndPasswords -TestSet $testset ## Third, look for accounts that re-use the same password between manager and report (lazy IT people who use same password for admin ID) Test-HashesForPasswordSharing $testset