Blog: SANS Audit Advice & Resources

Blog: SANS Audit Advice & Resources

Identifying Inactive and Unnecessary User Accounts in Active Directory (with Powershell!!!)

A common question in an audit of information resources is whether or not accounts for users are being properly managed. One aspect of that is determining whether or not the accounts created are needed while another is looking for evidence that accounts for terminated users are being disabled or deleted in a timely fashion. An easy way to answer both of these questions is through the use of Active Directory queries! This screencast demonstrates exactly how to do just that.

While it's true that the information that we're looking for can be obtained directly from the Active Directory using tools like DSQuery and DSGet, in the long term I think it's far wiser to learn a little bit of basic scripting that will allow you to perform just about any kind of query you'd ever want to in Active Directory, even if your admins have customized the Active Directory Schema!

Learning to write Powershell scripts, though, can seem daunting. Not only will we have to face the differences between different versions of Powershell and the .NET requirements that sometimes lead to software conflicts when we're still using some legacy code, but some Powershell scripts just look downright confusing! Not to worry.

Rather than trying to learn everything that there is to know about Powershell and directory queries, there's a great deal of value in learning some basic "recipes" that can be used to extract useful data using a script. Once we've got a good handle on the recipe, it's much easier to just adjust the "ingredients", if you will, to get at what we're looking for.

In the various classes that I teach for Auditors, whenever there's an opportunity to do so, I strongly recommend that auditors take some time to learn some basic scripting. This screencast is a perfect example. Once you've got a few of the basics in the script, you can easily modify the script to look for just about anything you'd want to. Not only that, you can make those modifications without ever really getting a deep understanding of exactly what an Active Directory Search object is and how it works!

To get you started, I've included the source code written in the screencast that goes with this posting. This code will determine your current domain and then extract all objects that are of class "User" (which includes computers, by the way) and give you CSV format output of the fully distinguished name, the SAM account name and the date of the last logon. To use this code, just create a new Powershell script file as described in the screencast and have at it!

$Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$ADSearch = New-Object System.DirectoryServices.DirectorySearcher
$ADSearch.PageSize = 100
$ADSearch.SearchScope = "subtree"
$ADSearch.SearchRoot = "LDAP://$Domain"

$ADSearch.Filter = "(objectClass=user)"


$userObjects = $ADSearch.FindAll()
foreach ($user in $userObjects)
$dn = $user.Properties.Item("distinguishedName")
$sam = $user.Properties.Item("sAMAccountName")
$logon = $user.Properties.Item("lastLogonTimeStamp")
if($logon.Count -eq 0)
$lastLogon = "Never"
$lastLogon = [DateTime]$logon[0]
$lastLogon = $lastLogon.AddYears(1600)


David Hoelzer teaches several full week courses ranging from basic security through to advanced exploitation and penetration testing. For a thorough treatment of this specific issue and a discussion of controls to mitigate this and similar issues, consider attending thefull week course on Advanced System & Network Auditing. More information can be found here:AUD 507 course. AUD 507 gives both auditors and security professionals powerful tools to automate and manage security over time.


Posted April 24, 2012 at 7:58 PM | Permalink | Reply


Weve been using the freeware version of netwrix inactive users tracker ( for a while it automatically scans all users in the domain and reports on users who have not logged in for a specified number of days.

Posted April 25, 2012 at 11:07 PM | Permalink | Reply

Active Directory Audit Tools


Thanks for the compliment, I am glad you like to the comments. Keep it up always.....

Posted May 10, 2012 at 10:13 PM | Permalink | Reply


hay, This is what I was looking for ages. and there you are with the simple yet very useful script. Thank you for sharing this with us. I will follow you from today onwards.


Posted February 13, 2013 at 11:58 AM | Permalink | Reply


This script works, but does not solve the following challenge: We have several users that have an extranet/Citrix account or share point account and never logon to a computer. As such, the logon count stays to Never or at best a very old date. These are all very active users, but not from this script perspective. How can the script be altered to count any type of AD authentication vs. user logon count?

Posted August 13, 2012 at 9:08 PM | Permalink | Reply


Hello, I just wanted to first say Thank you for this very informative knowledge on powershell and the script for auditing.
I tested the script on one of my servers and it runs beautifully. i just had a side question, how do i make it export out to a .csv to view outside of powershell? Thank you!! Ben

Posted December 05, 2012 at 11:08 AM | Permalink | Reply

Anthony Lee

You can try using Corporate Directory. Its an <a href="

Posted January 04, 2013 at 6:50 AM | Permalink | Reply


Hi David,
Really good article!

I have just one question about the $ADSearch,

$ADSearch.SearchScope = "subtree"
$ADSearch.SearchRoot = "LDAP://$Domain"

How can i Specify what OU i want to search in ?

Thank you,

Posted February 01, 2013 at 5:00 PM | Permalink | Reply


I was excited to run across this for PCI. Once I looked it over, put it on a 2003 domain controller, verified the execution policy, and ran it. It returned all users as "never" logged in.

After tinkering w/ it, using ds* utils, adfind, etc, I could not get it to work. I then tried it on on a 2008R2 DC in another domain, and again, it showed everyone as "never" logging in. I also tried on another servers in the second domain, and still failed.

An associate of mine, looked over the code, and were perplexed. He then put it on his workstation in the second domain, and low-and-behold, it worked!

Any idea why, this code will not run from what appears to be any version of Windows servers, but fine from a workstation?

Posted March 01, 2013 at 6:56 AM | Permalink | Reply


Try this third party tools to get inactive user reports and so on..

Posted June 27, 2013 at 6:52 PM | Permalink | Reply

Francisco De Jesus

I need a script to display "last log on" for all users in all domain controllers.
The challenge:
I have to display all last log on of all users accross more than one forest! (on 7 domain controllers)
Any script for that?
Problem is that the last log on date is different on each forest.

Posted October 30, 2013 at 6:10 AM | Permalink | Reply


ASN AD Inactive Account Tracker helps the Administrators to find all the users and computers that are currently not able to access the Active Directory resources. Administrators can easily track the inactive accounts such as locked users, disabled users, account expired users, password expired users, deleted users, disabled computers using the simple user interface and can make actions such as unlock, enable, reset password, extend the account expire date on the selected bulk records.

Post a Comment

* Indicates a required field.