- Activate BitLocker with manage-bde, PowerShell, or WMI - Wed, Sep 20 2023
- Join Azure Active Directory with Windows 11 - Tue, Sep 12 2023
- Manage enhanced security mode in Microsoft Edge using Group Policy - Fri, Sep 8 2023
It's easy to find lists containing vast numbers of hacked passwords on the Internet. These credentials are easily accessible and can be exploited by malicious actors for brute force attacks.
To check whether Active Directory users are utilizing compromised passwords, you can query HaveIBeenPwned.com. This website contains a database of hundreds of millions of stolen passwords.
Consulting HaveIBeenPwned
The website provides a form for interactive usage where you can input a password for verification. This proves useful, for instance, when you want to determine whether a password has been compromised before assigning or changing it.
For administrators looking up passwords from Active Directory in the lists of HaveIBeenPwned, however, this function is rendered useless because AD passwords are stored as hashes.
Invoke API function
Nonetheless, the website offers an API for this task, where you provide the first five characters of a hash. As a result, you receive all hashes from the database that start with this character sequence, truncated by the initial five characters.
For the hash
198ffc97717b69d5b8227a1dde33bada
you would call the function as follows:
https://api.pwnedpasswords.com/range/198ff?mode=ntlm
The response would then contain c97717b69d5b8227a1dde33bada if the password were compromised.
Retrieving hashes from AD
The initial challenge lies in the fact that neither the GUI tools nor the PowerShell module for Active Directory provides direct access to password hashes stored in AD. Some guides suggest dumping the AD database using a shadow copy for this purpose.
A more elegant approach is available using the DSInternals PowerShell module. It contains the Get-ADReplAccount cmdlet, which generates a replica of the AD database via MS-DRSR. Therefore, you must invoke it with the credentials of an account owning the necessary replication rights.
Installing DSInternals and configuring replication users
The first step is to install DSInternals using the following command:
Install-Module DSInternals
Subsequently, provide the account you intend to use for this task with the required permissions. While a domain admin could be used for this purpose, it's not recommended in production environments.
For this task, open the properties from the context menu of the domain in AD Users and Computers and navigate to the Security tab.
Then grant the desired user or group the Replicating Directory Changes All and Replicating Directory Changes permissions.
Now, you can retrieve an account's password hash and pass the first five characters to the API function of HaveIBeenPwned.
However, you have to overcome another hurdle because the hash is not available as a string but rather as a byte array of decimal numbers. These need to be converted to hexadecimal format and then combined into a string.The complete script is as follows:
Import-Module DSInternals # Get users who have changed their password after a certain date $user = Get-ADUser -Properties PasswordLastSet -Filter "PasswordLastSet -gt '08/21/2023'" # Request the credentials of the user who will fetch the password hashes $cred = Get-Credential $user | foreach{ $hash="" "`nChecking password for: " + $_.SamAccountName $r = Get-ADReplAccount -SamAccountName $_.SamAccountName -Domain contoso -Server dc1 -Credential $cred -Protocol TCP #Turn byte array into a hex string $r.NTHash |foreach{ $hash += ([Convert]::ToString($_,16)).padleft(2,"0") } #Calling Web API passing the first five chars of the hash $pwned = Invoke-WebRequest -UseBasicParsing -Uri ("https://api.pwnedpasswords.com/range/" + $hash.substring(0,5) + "?mode=ntlm") #Look up hash in the response from haveIbeenpwned if($pwned.Content.ToLower().contains($hash.substring(5))){ "`nPassword for " + $r.DisplayName + " is compromised!" }}
The script identifies all users who have changed their passwords since a specific date, such as the beginning of the current month, and checks whether the new password has been compromised.
Summary
Given that access to Active Directory often relies on just a username and password, it's crucial to employ secure passwords. Administrators can ensure this, to a certain extent, through the password policy.
However, to prevent the use of compromised passwords, external services need to be consulted. HaveIBeenPwned maintains an extensive collection of stolen passwords that can be utilized for this purpose. By calling an API function using PowerShell, one can determine whether passwords have been compromised.
Very useful, thank you.
This sounds sketchy. Doesn’t this require you to trust HaveIBeenPwned? One may argue that you didn’t give them the entire hash but if they reply with a match that would be a hash try whether it is a valid match or not.
Since you don’t have to register with the service, they don’t even know who you are.
You can also download the entire 613 million hashes from the website and check your hashes against the hibp hashes offline
As an additional safety measure I’d recommend not connecting to the service with an which can be tracked back to your institution.
It makes me wonder, where did they get their list of emails and passwords in the first place. Foreign contractors, Microsoft’s Foreign force, disgruntle employees, or the maybe a federal government? I would not give anyone any clues as to the users in my domain. You might as well be saying: “Hi Conner here is a list of my users. Put them in your database, please. And then sell them to your comrades.”
It’s foolware at best but let’s just presume they really do mean good, what happens when they are hacked? And they will be.
Do you know where the site is hosted? What country? Is it on a dedicated colocation server with little security, is it a VM server on a big tech Cloud ready to be copied, or are they simply spammers looking to build an easy spam list? Maybe it’s the MI6 or KGB, the CIA tally whackers, or is it the NWO monkeys. The point is, avoid it like the plague as some @*%$#$^ will eventually hack it one way or the other. Solar winds, and Amazon should be a huge lesson to any IT professional.
If you want security, get off the public clouds, traditionally known as web hosts, and create a secure private cloud with military grade Authentication using 2FA and smartcards at a minimum. Again avoid all big tech companies as much as possible. Big tech is not, and never was, your friend. Specifically after the federal antitrust shakedown that happened before 9/11. I miss my “paid for” relatively secure Windows 7.
I am close to finishing a book with Apress on “Building Secure Private Clouds”. Stay tuned.
Be Smart and Safe,
Andy
Andy, I think you didn’t understand properly how HIBP works.
> I would not give anyone any clues as to the users in my domain.
You don’t. You only send an anonymous HTTP request containing the first 5 chars of a password hash, but no user names. As a response you get a list of hashes (without the leading 5 chars). Your hash may be included in the list or not.
> Do you know where the site is hosted? What country? Is it on a dedicated colocation server with little security, is it a VM server on a big tech Cloud ready to be copied, or are they simply spammers looking to build an easy spam list?
The site is run by this guy, who seems to be quit trustworthy:
https://haveibeenpwned.com/About
> The point is, avoid it like the plague as some @*%$#$^ will eventually hack it one way or the other.
And why would this matter to you? What impact would that have on your API call? In the worst case some useless results.
there is similar software that downloads the hashes to the local
I would put a link, but it would get blocked prob “Specops password auditor”
You can get a 1 year free Lic as well
Hi, there’s an easier way, DSInternals contains a function “passwordquality”
See https://github.com/MichaelGrafnetter/DSInternals/blob/master/Documentation/PowerShell/Test-PasswordQuality.md#test-passwordquality