Auditing Passwords with Active Directory Properties

0

Posted on August 28, 2015 by

Have you ever been looking through Active Directory and notice something strange in one of the fields?  Maybe the Organization or Description field has a weird string of letters, numbers, and characters.  You think, “Huh, that kind of looks like a password.”

Ding! Ding! Ding!

Yes, it happens.  Either through lack of understanding or just laziness, sometimes passwords get put into the plain text fields in AD.  This is dangerous because those fields are readable by everyone on the domain.

So how do you know if any of these fields are being used to store passwords?  I managed to cobble together a PowerShell script that can help.

The script will run through a given OU and grab a given property within each account (by default, it uses Description).  It then uses that property as the password and tries to log in as the account.  It excludes inactive accounts and accounts where the property is blank.  Any accounts found with a password matching the given property are exported to the CVS file specified.

NOTE: This will register as one failed login attempt.  So don’t go running this script multiple times in succession or it could result in lockouts.

The script is below.  Just save it as a PS1 file and run it from a PowerShell command line.

param
(
    [string]$csvOutputFile = $(throw "-csvOutputFile is required."),
    [string]$searchBase = $(throw "-searchBase is required.  EX. OU=USA,DC=fabrikam,DC=com"),
    [string]$adProperty = "description"
)

[array]$users = Get-ADUser -filter 'enabled -eq $true -and $adProperty -like "*"' -searchbase "$searchBase" -SearchScope Subtree -Properties givenname,sn,mail,title,department,samaccountname,displayname,description
Write-Host "Count of Active users with $($adProperty.ToString().ToUpper()) NOT Null: $($users.count)"

# Get short domain name from the local computer
$shortDomain = (Get-ADDomain -Identity (Get-WmiObject Win32_ComputerSystem).Domain).NetBIOSName
$i=1
foreach ($user in $users)
{
    $userLogon = "$shortDomain\$($user.samaccountname)"
    # Display progress bar
    Write-Progress -Activity "Processing Users" -status "User: $userLogon" -percentComplete ($i / $users.count*100)
    # Test username/password combo.  If successful, TRUE will be returned.
    if ((new-object directoryservices.directoryentry "",$userLogon,$user.$adProperty).psbase.name -ne $null)
    {
        Write-Host "$userLogon,$($user.$adProperty)"

        $exportToCSV = New-Object System.Object
        $exportToCSV | Add-Member -Name username -Value $userLogon -MemberType NoteProperty
        $exportToCSV | Add-Member -Name $adProperty -Value $user.$adProperty -MemberType NoteProperty
        $exportToCSV | export-csv .\$csvOutputFile -NoTypeInformation -Append
    }
    $i++
}

The script has 3 parameters and can be passed:

-csvOutputFile [Required]

-searchBase [Required]

-adProperty [Optional.  Default value is “Description”]

The scrip can be called from a PowerShell command line.  Without passing anything to “-adProperty”, the script will use the “Description” field as the password for each account.

.\script.ps1 -csvOutputFile MyExport.csv -searchBase 'OU=Users,OU=NY,OU=US,DC=fabrikam,DC=com'

If a value is passed to “-adProperty”, that property will be used instead of Description as the password for each account.  In the example below, the Organization property will be used as the password.

.\script.ps1 -csvOutputFile MyExport.csv -searchBase 'OU=Users,OU=NY,OU=US,DC=fabrikam,DC=com' -adProperty 'organization'

Let me know how this script works for you and feel free to give me feedback and suggestions.

Leave a Reply

Your email address will not be published. Required fields are marked *