Account Lockout

needed some guidance for the account lockout query that ive been able to achieve till now. This really helps to find out the machine from which the bad password (4771 events) come from.but the csv data i get is so huge, i dont know how to show it meaningfully. currently the csv data is almost 64 MB in size. the out put sample i get is at bottom. Would love to hear feedbacks and more suggestions on this. I learned a lot of the xml filtering from Ashley Mcglone’s account lockout forensics and been trying to replicate it meaningully in my large environment.

steps used

  1. enabled powershell remoting on domain controllers
  2. set up event log subscription on a toolbox server to receive the 4771 events into the “forwarded events” log
  3. setup script below to parse the forwarded event log to get the 4771 event data
#script begin
Import-Module activedirectory

$counts = get-content C:\count.txt

foreach($count in $counts){

$date = get-date
$LockedOutUsers = (Search-ADAccount -LockedOut -server ).samAccountName
write-host "Current locked out user list at $date are $lockedoutusers"

foreach($user in $LockedOutUsers)

write-host "$count"

#define xml query targetting the forwarded event log
[xml]$FilterXML = @"

and *[EventData[(Data[@Name='TargetUserName'] = '$user') ]] 


$eventdata = Get-WinEvent -FilterXml $filterxml | Select-Object @{Name="User";Expression={($_.Properties[0].Value) } },`
             Resolve-DnsName (($_.Properties[6].Value) -replace '::ffff:')  | select -ExpandProperty namehost } },@{Name="NonResolvedIP";Expression={($_.Properties[6].Value) -replace '::ffff:'} },TimeCreated 

             $eventdata = $eventdata | Sort-Object Timecreated,User,DNSresolvedname,NonresolvedIP -Unique 
             #"Users locked during $date are $LockedOutUsers" | out-file D:\nara\BadPasswordData\BadPasswordData-name.csv -append
             $eventdata | out-file D:\Nara\badpassworddata\BadPasswordData-name.csv -Append

#script end 

What are you expecting to get back from your script? How many records, etc? Are you getting legitimate, (good), data in your CSV?

And then, what does “meaningfully” mean for you? How are you trying to present the data, to whom, etc.

So i have a very huge environment, and the data i receive is legitimate.

I pull back the below fields

User DNSResolvedName NonResolvedIP TimeCreated

blah 11/9/2016 09:00:am

325732 lines of correct data in 10 hours time in the csv

I want to present the huge data, maybe with an option to search for the ‘samaccountname’ to the helpdesk (ultimate goal)

Wow… ok, cool! And I’m assuming you want them to be able to run this whenever they get a phone call about locked account, etc. Have you looked at using Out-GridView? I’m not where I can really play with it and test it, but I believe that you can search on it. I know that you can sort columns that way.

Another option may be to dump the data to Convert-ToHtml and display it as web page. It takes some work, but you could build any kind of static page you want, (or even include whatever client-side scripting you choose).

And then, depending on what you want to see, you could create a PowerShell GUI that asks for a username, for example, and then searches the CSV in the background. That way you only display the data related to the user you’re looking for. Depending on how “tech savvy” your audience is, you could even do that as a script with CLI results.

I haven’t had an opportunity/excuse to build a PowerShell GUI, but that is probably the route I would take in your scenario. You could have a script that launches a GUI with a button that kicks off the discovery script and then comes back and asks for criteria to search for in the newly produced CSV.

Also, depending on how long the discovery script runs, could you just include your search criteria to the discovery script so that it only returns records for the user you’re searching for? I imagine that script takes quite a while to run, especially in your environment, but thought I’d throw it out there.

This runs in the background and keeps on appending to the csv file. We cannot use the script to run when needed, because the forwarded event log can hold a maximum of 1GB of data. and overwritten as soon as it reaches that level.

So i need to keep dumping this to the csv and appending it and once someone opens the file and searches, they can see the forensics of the lockout/bad password happening from different machines or same machine.

Your options are way above my skill level, but just posting to see if any experts had some good examples/suggestions.

Definitely above your skill level! You just haven’t done it yet!

Can you just do something as simple as this?

$csv = Import-CSV C:\Temp\csvfile.csv
$csv | Where-Object User -eq "user1"

You could turn that into a script pretty easily so that whatever personnel would just have to run the script with the username as an argument, (Get-Lockout.ps1 -Username “user1”).

let me try that out… thank you for all your prompt replies…really appreciate that

That really works well and gives me lot of ideas to start with… thanks so much

Here is another question i had which i forgot to ask.

The way bad passwords work are also tricky. so in the csv , there are sources where the lockout source is shown as “Domain controller” and then the next one shows as “the actual client” doing it. Is there a way i can filter out the ones which are actually domain controllers. Is there ways to filter out the output does not contains anything from this list “domain-controller-list.txt”

Because the out put should actually contain only the client sources and not the Domain controller.

That info is in the Message field, right? In order to do that, you’d have to do some string filtering on that field. It will be slow, but not impossible. I would probably add another Where-Object to the pipeline after narrowing down the results to only the events related to a particular user. Again, that’s a lot of filtering on text, so speed is pretty bad. Someone else may have a better option for you…

You would want to change “DCName” here to as much detail on that line as you can to make sure you don’t filter out stuff you want. I don’t have a DC I can look at here, so I don’t know exactly what one of these events looks like.

$csv | Where-Object User -eq "user1" | Where-Object Message -notcontains "DCName"

Understood your points, im not doing the string filtering under message because it will kill my query ( speed is the need) . I was trying to filter it out of the csv file that gets generated… trying to filter multiple values specified by a text file