Here’s an overview of the various breaches that have been consolidated into this Have I Been Pwned. These are accessible programmatically via the HIBP API and via the RSS feed.

I would like to thank Troy Hunt, a Microsoft Regional Director and Most Valuable Professional awardee for Developer Security, blogger at troyhunt.com for this resource.

HIBP API Advantages

  • Provides a service to the public
  • Analyzing the breach data helps victims learn of compromises of their accounts
  • Highlights the severity of the risks of online attacks on today’s internet

In this article, I have attached a PowerShell script that takes the details of the given Azure AD Users as input and analyze the breaches that you can share with AAD admins and users.

Prerequisites

Note - This code has not been optimized and is for demo purpose. You might need to modify the code as per your requirements.

PowerShell Script

$requiredProfileProperties = "id,displayName,userPrincipalName,userType"
$hibpApiEndpoint = "https://haveibeenpwned.com/api/v3"
$hibpApiKey = "[your key]"
$global:auditOutput = @()

$resultDir = "Output"
$executionDir = $PSScriptRoot
$outputDir = "$executionDir/$resultDir"
$outputFilePath = "$outputDir/$(get-date -f yyyyMMdd-HHmmss)-haveibeenpwned-breaches-outcome.csv"

function AddBreach {
    param (
        [Parameter(Mandatory = $false)] [string] $Name,
        [Parameter(Mandatory = $false)] [string] $BreachDate,
        [Parameter(Mandatory = $false)] [string] $Description,
        [Parameter(Mandatory = $false)] [bool] $IsVerified
    )

    $audit = New-Object -TypeName PSObject

    $audit | Add-Member -MemberType NoteProperty -Name "Name" -Value $Name
    $audit | Add-Member -MemberType NoteProperty -Name "BreachDate" -Value $BreachDate
    $audit | Add-Member -MemberType NoteProperty -Name "Description" -Value $Description
    $audit | Add-Member -MemberType NoteProperty -Name "IsVerified" -Value $IsVerified

    $global:auditOutput += $audit
}

$users = m365 aad user list --properties $requiredProfileProperties -o json | ConvertFrom-Json -AsHashtable
$usersCount = $users.Count
Write-Host "Number of users found : $usersCount"

ForEach ($user in $users) {
    if ($user.userType -eq "Member") {
        $userPrincipalName = $user.userPrincipalName
        Write-Host "Processing : $userPrincipalName"

        $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
        $headers.Add("hibp-api-key", $hibpApiKey)
        $breaches = (Invoke-RestMethod -Uri "$hibpApiEndpoint/breachedaccount/$userPrincipalName?truncateResponse=false" -Headers $headers)

        ForEach ($breach in $breaches) {
            $breachData = $breach | ConvertFrom-Json -AsHashtable
            
            $breachName = $breachData.Name
            $breachDate = $breachData.BreachDate
            $breachDescription = $breachData.Description
            $IsBreachVerified = $breachData.IsVerified
            AddBreach $breachName $breachDate $breachDescription $IsBreachVerified
        }
    }
}

$global:auditOutput | Export-Csv -Path "$outputFilePath" -NoTypeInformation
Write-Host "Open $outputFilePath to review analysis outcomes report."

Sample breach response

[
  {
    "Name": "Adobe",
    "Title": "Adobe",
    "Domain": "adobe.com",
    "BreachDate": "2013-10-04",
    "AddedDate": "2013-12-04T00:00Z",
    "ModifiedDate": "2013-12-04T00:00Z",
    "PwnCount": 152445165,
    "Description": "In October 2013, 153 million Adobe accounts were breached with each containing an internal ID, username, email, <em>encrypted</em> password and a password hint in plain text. The password cryptography was poorly done and <a href=\"http://stricture-group.com/files/adobe-top100.txt\" target=\"_blank\" rel=\"noopener\">many were quickly resolved back to plain text</a>. The unencrypted hints also <a href=\"http://www.troyhunt.com/2013/11/adobe-credentials-and-serious.html\" target=\"_blank\" rel=\"noopener\">disclosed much about the passwords</a> adding further to the risk that hundreds of millions of Adobe customers already faced.",
    "DataClasses": [
      "Email addresses",
      "Password hints",
      "Passwords",
      "Usernames"
    ],
    "IsVerified": true,
    "IsFabricated": false,
    "IsSensitive": false,
    "IsRetired": false,
    "IsSpamList": false,
    "LogoPath": "https://haveibeenpwned.com/Content/Images/PwnedLogos/Adobe.png"
  },
  {
    "Name": "BattlefieldHeroes",
    "Title": "Battlefield Heroes",
    "Domain": "battlefieldheroes.com",
    "BreachDate": "2011-06-26",
    "AddedDate": "2014-01-23T13:10Z",
    "ModifiedDate": "2014-01-23T13:10Z",
    "PwnCount": 530270,
    "Description": "In June 2011 as part of a final breached data dump, the hacker collective &quot;LulzSec&quot; <a href=\"http://www.rockpapershotgun.com/2011/06/26/lulzsec-over-release-battlefield-heroes-data\" target=\"_blank\" rel=\"noopener\">obtained and released over half a million usernames and passwords from the game Battlefield Heroes</a>. The passwords were stored as MD5 hashes with no salt and many were easily converted back to their plain text versions.",
    "DataClasses": ["Passwords", "Usernames"],
    "IsVerified": true,
    "IsFabricated": false,
    "IsSensitive": false,
    "IsRetired": false,
    "IsSpamList": false,
    "LogoPath": "https://haveibeenpwned.com/Content/Images/PwnedLogos/BattlefieldHeroes.png"
  }
]

I hope this script has been helpful, and I would love to know your thoughts. Please do post them in the comments section below.