If you haven’t heard of Have I Been Pwned, firstly what are you doing? It’s a site created by fellow Aussie Troy Hunt. Troy aggregates data breaches as they become public into a searchable database. One of the primary goals of Have I Been Pwned is to raise security awareness around data breaches to the public.
As a bit of a learning exercise to myself, I created a PowerShell Module that leverages the haveibeenpwned.com APIs. The module contains five Functions, Get-PwnedAccount, Get-PwnedBreach, Get-PwnedDataClass, Get-PwnedPassword, and Get-PwnedPasteAccount. I like to think of the HaveIBeenPwned PowerShell Module as an Enabler. By itself it does nothing more than what the haveibeenpwned.com site does. But by leveraging the Power of PowerShell and returning the results in object format the data can be easily manipulated for many other purposes.
Installing and using the Module and Functions is very simple. Ideally you will be running PowerShell 5 or above which will allow you to easily download and install from the PowerShellGallery. If you’re not on PowerShell 5 I’d highly recommend you download the WMF 5.1 (Windows Management Framework) which includes PowerShell 5.
Installing the module is simply a matter of typing the following.
PS F:\Code> Install-Module -Name HaveIBeenPwned
Once installed you can view all the Functions available with the following command.
PS F:\Code> Get-Command -Module haveibeenpwned CommandType Name Version Source ----------- ---- ------- ------ Function Get-PwnedAccount 1.1 HaveIBeenPwned Function Get-PwnedBreach 1.1 HaveIBeenPwned Function Get-PwnedDataClass 1.1 HaveIBeenPwned Function Get-PwnedPassword 1.1 HaveIBeenPwned Function Get-PwnedPasteAccount 1.1 HaveIBeenPwned
The two main Functions are Get-PwnedAccount and Get-PwnedPassword.
The first, Get-PwnedAccount, will enumerate if an account, based off an email address, has been found in the Have I Been Pwned list of data breaches.
PS F:\Code> Get-PwnedAccount -EmailAddress [email protected]
In the above example all breaches are listed where the account used [email protected] as the email address. Which is huge by the way.
The second and slightly more controversial, Get-PwnedPassword, will take a password and confirm if it has been identified in a data breach. Get-PwnedPassword will accept a password in three different formats. Plain text, Secure String, and SHA1 hash.
PS F:\Code> Get-PwnedPassword -SHA1 AB87D24BDC7452E55738DEB5F868E1F16DEA5ACE
In the above example a SHA1 hash was generated offline using Quick Hash GUI. Get-PwnedPassword will then send that Password or SHA1 hash in the body of a HTTPS request to Have I Been Pwned. Now, obviously, what can been see as the controversial part off this is not only do you have to trust Have I Been Pwned but also this PowerShell Function.
All Functions come with Help and Examples which can be view using Get-Help. For example.
PS F:\Code> Get-Help Get-PwnedPassword -Examples
The Module and all Functions can be found in the PowerShellGallery for download. The Module can also been found in my public GitHub Project https://github.com/originaluko/haveibeenpwned. All code can been view and sanity checked and is free to consume.
Lastly, I thought I might show how you can go one step further from simply enumerating an individual account. Many organisation’s IT departments create and manage accounts for their staff. They also provide security awareness training in protecting online accounts. An organisation could take a CSV list of their staff’s email addresses, import that list into PowerShell, and run it against the Get-PwnedAccount Function and identify if any of their staff have been involved in a data breach.
In the below example I import a small CSV file I have created with a list of email addresses. Then using half a dozen lines of code I iterate through the CSV list of email addresses and identify all the accounts that have been involved in a data breach. Using this information I can pro-actively notify staff to review these accounts.
$emails = Import-Csv F:\email_list.csv foreach ($email in $emails) { $email = $email.accounts $results = Get-PwnedAccount -EmailAddress $email if ($results.status -ne 'Good') { foreach ($result in $results) { $breach = $result.title Write-Output "Email address $email has been found in a $breach breach" } } Start-Sleep -Milliseconds 1500 }
And sample output after running the above code.
Email address [email protected] has been found in a Yahoo breach Email address [email protected] has been found in a Youku breach Email address [email protected] has been found in a Zomato breach Email address [email protected] has been found in a 000webhost breach Email address [email protected] has been found in a 17 breach Email address [email protected] has been found in a Adobe breach Email address [email protected] has been found in a Bell (2017 breach) breach
Also read the follow up post on new additions
HaveIBeenPwned PowerShell Module Updates -- https://blog2.ukotic.net/2019/05/28/haveibeenpwned-powershell-module-updates/
Download Links
PowerShellGallery: https://www.powershellgallery.com/packages/HaveIBeenPwned/
GitHub: https://github.com/originaluko/haveibeenpwned
Doesn’t work on emails containing “-”
example: [email protected]
Error output:
Get-PwnedAccount : Cannot validate argument on parameter ‘EmailAddress’. The argument “[email protected]” does not matc
h the “(\w+@[]a-zA-Z_]+?\.[a-zA-Z]{2,6})” pattern. Supply an argument that matches “(\w+@[]a-zA-Z_]+?\.[a-zA-Z]{2,6})”
and try the command again.
Thanks for letting me know. I’ll look to allow it.
Excuse my lack of programming skills but can’t seem to get this working:
Error:
Get-PwnedAccount : Cannot validate argument on parameter ‘EmailAddress’. The argument “” does not match the “(\w+@[]a-zA-Z_]+?\.[a-zA-Z]{2,6})” pattern. Supply an argument that matches
“(\w+@[]a-zA-Z_]+?\.[a-zA-Z]{2,6})” and try the command again.
At line:3 char:47
+ $results = Get-PwnedAccount -EmailAddress $email
+ ~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-PwnedAccount], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Get-PwnedAccount
I have created a .csv with the emails and imported the csv using: $emails = Import-Csv c:\mycsv.csv
when i check $emails i see the list of emails, however when i run the script it does not seem to be working “”.
Thanks
Have something changed on https://haveibeenpwned.com/.
If i check my emailadress with your module I do not get any result anymore. If I check the website I am pwnd 🙁
The password-check works but not the account-check
PS C:\Users\anno\OneDrive – ELON Group AB\Powershell\Script> Get-PwnedAccount -EmailAddress ‘[email protected]’
PS C:\Users\anno\OneDrive – ELON Group AB\Powershell\Script> Get-PwnedPassword -Password ‘Password01’
C464AF817287343305CBD6493C593885695DF531
WARNING: Password pwned 12274 times!
Have something changed with the module.
I cannot get the account-check to work.
I installed the module with Install-module but when I run the account-check I get no result. The website shows that I am pwnded 🙁
The passwordcheck works.
PS C:\Users\anno\OneDrive – ELON Group AB\Powershell\Script> Get-PwnedAccount -EmailAddress ‘[email protected]’
PS C:\Users\anno\OneDrive – ELON Group AB\Powershell\Script> Get-PwnedPassword -Password ‘Password01’
C464AF817287343305CBD6493C593885695DF531
WARNING: Password pwned 12274 times!
Version: 1.30.2 (user setup)
Commit: 61122f88f0bf01e2ac16bdb9e1bc4571755f5bd8
Date: 2019-01-07T22:54:13.295Z
Electron: 2.0.12
Chrome: 61.0.3163.100
Node.js: 8.9.3
V8: 6.1.534.41
OS: Windows_NT x64 10.0.17134
Thanks for letting me know Anders. I’ve updated the module and Get-PwnedAccount.
You can get the latest version and try it out with Update-Module -Name HaveIBeenPwned
Get-PwnedAccount : Forbidden – no user agent has been specified in the request.
At line:1 char:1
I believe this is due to APIv2 including a requirement to define the user-agent for the API poll.
Thanks for the heads up. I’ve updated the module to now use a UserAgent for Get-PwnedAccount.
Great module Mark – thanks
Since the upgrade to the new API at haveibeenpwned it requires an agentstring though as per messages above.
I edited get-pwnedaccount.ps1 on line 50 to read:
$Request = Invoke-RestMethod -Uri $URI -UserAgent “HaveIBeenPwned Powershell Module”
and all worked again!
Thanks Buddy
I’ve updated the module and Get-PwnedAccount to now allow specifying a UserAgent.
For lack on knowing what to call the default UserAgent I’ve used your suggestion.
could you not set it so that you could reference the local file that you can download from hibp… instead of going out to the API?
Unlikely buddy. I haven’t tried downloading the file but it’s huge.
You would no doubt have to import it into a database to actually be able to do anything with it.
Troy does all the hard work. I’ve just created a PowerShell module to leverage his APIs.
I’m getting the following when trying to look up an email. I have updated the module. Ideas?
Get-PwnedAccount : Forbidden – no user agent has been specified in the request.
Hi Christian,
A few people are still receiving this error after updating. I’m not quite sure why as I’m not receiving this error on any of my workstations and it’s also working for most other people.
Can you try using the UserAgent parameter and see if that helps. eg
Get-PwnedAccount -EmailAddress [email protected] -UserAgent “Chrome”
Could you provide me with the output of $PSVersionTable please? Also do you have a proxy server set?
THanks
Interestingly enough, I tried it today and it now works. The only thing that I can think of that changed was that I hadn’t closed and re-opened Powershell since installing the module yesterday.
is there a specific format for the .csv file of emails? i have a single column with just email addresses – each on a new line and get the following error:
Get-PwnedAccount : Cannot validate argument on parameter 'EmailAddress'. Exception calling ".ctor" with "1" argument(s): "The parameter 'address' cannot be an empty string.
Parameter name: address"
At line:4 char:47
+ $results = Get-PwnedAccount -EmailAddress $email
+ ~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-PwnedAccount], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Get-PwnedAccount
Hey Jason, The first line in the .csv file should represent the column name. After that you can have all your email addresses on a separate line. In my example I used ‘accounts’ and then you’ll see I referenced that column after import using $email.accounts
Trying to use the Export-CSV at the end but not going to well, which way would you do this?
I put at the end
Export-CSV .\Pwnedusers.csv and not having any luck
I keep receiving an error that the rate limit has been reached. I use sleep 2000 milliseconds. Is this only supposed to work for a few users? I am using “get-aduser” instead of a csv file to pull my users that have an email address.
Get-PwnedAccount : Too many requests – the rate limit has been exceeded.
At C:\Scripts\HaveIBeenPwned.ps1:33 char:16
+ … $results = Get-PwnedAccount -EmailAddress $emailaddress -UserAgent ” …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-PwnedAccount
When i want to check my email [email protected] which was breached i have iformation: Serwer zdalny zwrócił błąd: (404) Nie znaleziono.
What i can do with this problem? :/
This is actually normal. The email was found in an ‘unverified’ breach. The version 2 API doesn’t return ‘unverified’ breaches by default. In the next version of the PowerShell module using the version 3 API it will return ‘unverified’ breaches. Unfortunately the version 3 API will require authentication (you need to pay for a key) when Troy cuts over to this.
Late Aug 2019, getting this error:
This version of the API has been discontinued, please use V3: https://www.troyhunt.com/authentication-and-the-have-i-been-pwned-api/
Unfortunately the latest version of the API now requires authorization. This means that you have to pay for an API key / token from Troy. Then supply that in your request to the service.
The currently published PowerShell module in the Gallery doesn’t support this yet. My latest version in my GitHub repo has been updated for the v3 API and to accept an API key input. I have not done full testing as of yet so I am looking for feedback. https://github.com/originaluko/haveibeenpwned
Thanks, new API keys have been temporarily disabled from HIBP, but I’ll check this out. What I want is to compare the date of the last breach the user account was listed in to the date of a user’s last password change in our systems.