Last Bad Password with PowerShell
Password spraying attacks are often difficult to pinpoint without an advanced detection system to correlate event logs. An attacker will often only try one password per user at a time, then wait for a while, and try another. For example, we'd try "Password123" first, wait 30 minutes, then "Password123!", wait 30 minutes, try "Password123#", and so on. Automated tools make it easy for attackers to create an attack profile, kick it off, and walk away - the fact that it takes hours or days isn't important.
The "low and slow" methodology ensures that legitimate accounts don't get locked out and create suspicion. There aren't multiple login attempts at one time for a user so it will appear like a simple mistaken password entry or "fat finger". However, if we see that same bad logon event for a thousand users all within a couple minutes something is obviously wrong. That's where the correlation comes in - one user's bad attempt is OK. A thousand user's bad attempts all in series aren't OK.
There's an easy way for our defenders to see the last bad logon attempt for Active Directory users with PowerShell. We can either output a formatted table in the PowerShell window or use the export-csv cmdlet to create a file. There is a caveat - the script must be run on an Active Directory Domain Controller (DC). Here's the script:
Get-ADUser -Filter * -Properties LastBadPasswordAttempt,BadPwdCount | select SamAccountName,LastBadPasswordAttempt,BadPwdCount | Sort-Object -Property LastBadPasswordAttempt -Descending
Our script pulls all Active Directory users on the DC, gets the two extra properties we're looking for, selects the three columns we want to see, and sorts by the LastBadPasswordAttempt timestamp. Here's a normal, non-password spraying log of users:
A couple users have bad password attempts but not enough to lock out their accounts. Most users don't appear to have any. The timestamps are all spread out and they only occur within working hours. The output of this script passes the "smell test" for normal user activity. I left the first letter of the username unblurred and you'll understand why in a moment. Now, here's an active password spraying attack:
Everything about this looks suspect. First, look at the timestamps - so many logons within the same couple seconds! There's no possible way that's coincidence. Second, check out the number of bad passwords - all users have exactly one failed logon. Finally, look at the first letter of the username - they're in alphabetical order. Someone obviously got a list of usernames, sorted them alphabetically, and is using it in an attack.