Skip to content

Instantly share code, notes, and snippets.

@steve-ross
Created October 30, 2025 16:13
Show Gist options
  • Save steve-ross/310a0f7e9b6ea7efdc5b4b3ec9d9c814 to your computer and use it in GitHub Desktop.
Save steve-ross/310a0f7e9b6ea7efdc5b4b3ec9d9c814 to your computer and use it in GitHub Desktop.
# Active Directory Account Investigation Script
# Purpose: Investigate gb12359 and hj03694 for identity contamination causes
# Run this on a Windows server with Active Directory PowerShell module
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host "ACTIVE DIRECTORY IDENTITY CONTAMINATION INVESTIGATION" -ForegroundColor Cyan
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host ""
$user1 = "gb12359"
$user2 = "hj03694"
# Function to display section headers
function Write-Section {
param([string]$Title)
Write-Host "`n" -NoNewline
Write-Host "=" * 80 -ForegroundColor Yellow
Write-Host $Title -ForegroundColor Yellow
Write-Host "=" * 80 -ForegroundColor Yellow
}
# Function to compare two values and highlight differences
function Compare-Values {
param(
[string]$Property,
$Value1,
$Value2
)
if ($Value1 -ne $Value2) {
Write-Host " *** MISMATCH DETECTED ***" -ForegroundColor Red
Write-Host " $user1 ${Property}: $Value1" -ForegroundColor Red
Write-Host " $user2 ${Property}: $Value2" -ForegroundColor Red
}
}
#------------------------------------------------------------------------------
# 1. BASIC ACCOUNT INFORMATION
#------------------------------------------------------------------------------
Write-Section "1. BASIC ACCOUNT INFORMATION"
try {
$account1 = Get-ADUser $user1 -Properties *
$account2 = Get-ADUser $user2 -Properties *
Write-Host "`n$user1 Account:" -ForegroundColor Green
Write-Host " SamAccountName: $($account1.SamAccountName)"
Write-Host " UserPrincipalName: $($account1.UserPrincipalName)"
Write-Host " DistinguishedName: $($account1.DistinguishedName)"
Write-Host " Enabled: $($account1.Enabled)"
Write-Host " WhenCreated: $($account1.WhenCreated)"
Write-Host " WhenChanged: $($account1.WhenChanged)"
Write-Host "`n$user2 Account:" -ForegroundColor Green
Write-Host " SamAccountName: $($account2.SamAccountName)"
Write-Host " UserPrincipalName: $($account2.UserPrincipalName)"
Write-Host " DistinguishedName: $($account2.DistinguishedName)"
Write-Host " Enabled: $($account2.Enabled)"
Write-Host " WhenCreated: $($account2.WhenCreated)"
Write-Host " WhenChanged: $($account2.WhenChanged)"
# Check if WhenChanged is recent (around Sept 26 or Oct 27)
Write-Host "`n*** CRITICAL: Check if WhenChanged matches contamination dates ***" -ForegroundColor Magenta
Write-Host "Contamination occurred on: 2025-09-26 and 2025-10-27" -ForegroundColor Magenta
} catch {
Write-Host "ERROR: Failed to retrieve basic account info: $_" -ForegroundColor Red
exit 1
}
#------------------------------------------------------------------------------
# 2. ACCOUNT RELATIONSHIPS & REFERENCES
#------------------------------------------------------------------------------
Write-Section "2. ACCOUNT RELATIONSHIPS (CRITICAL CHECK)"
Write-Host "`nChecking if $user1 has ANY references to $user2..." -ForegroundColor Yellow
# Check all proxy addresses
Write-Host "`nProxy Addresses ($user1):"
if ($account1.proxyAddresses) {
foreach ($proxy in $account1.proxyAddresses) {
Write-Host " $proxy"
if ($proxy -match $user2) {
Write-Host " *** FOUND REFERENCE TO $user2 IN PROXY ADDRESS ***" -ForegroundColor Red
}
}
} else {
Write-Host " (none)"
}
# Check alternate security identities
Write-Host "`nAlternate Security Identities ($user1):"
if ($account1.altSecurityIdentities) {
foreach ($altId in $account1.altSecurityIdentities) {
Write-Host " $altId"
if ($altId -match $user2) {
Write-Host " *** FOUND REFERENCE TO $user2 IN ALT SECURITY ID ***" -ForegroundColor Red
}
}
} else {
Write-Host " (none)"
}
# Check manager relationship
Write-Host "`nManager/Assistant Relationships:"
Write-Host " $user1 Manager: $($account1.Manager)"
Write-Host " $user2 Manager: $($account2.Manager)"
if ($account1.Manager -match $user2) {
Write-Host " *** $user1 HAS $user2 AS MANAGER ***" -ForegroundColor Red
}
# Check if accounts share the same objectGUID or objectSID
Write-Host "`nUnique Identifiers (should be different):"
Write-Host " $user1 ObjectGUID: $($account1.ObjectGUID)"
Write-Host " $user2 ObjectGUID: $($account2.ObjectGUID)"
Compare-Values "ObjectGUID" $account1.ObjectGUID $account2.ObjectGUID
Write-Host " $user1 SID: $($account1.SID)"
Write-Host " $user2 SID: $($account2.SID)"
Compare-Values "SID" $account1.SID $account2.SID
#------------------------------------------------------------------------------
# 3. CRITICAL ATTRIBUTES COMPARISON
#------------------------------------------------------------------------------
Write-Section "3. CRITICAL ATTRIBUTES COMPARISON"
$criticalAttrs = @(
'sAMAccountName',
'mail',
'givenName',
'sn',
'cn',
'displayName',
'employeeID',
'employeeNumber'
)
Write-Host "`nComparing attributes that appear in CAS logs:"
foreach ($attr in $criticalAttrs) {
$val1 = $account1.$attr
$val2 = $account2.$attr
Write-Host "`n $attr"
Write-Host " $user1: $val1"
Write-Host " $user2: $val2"
}
# Check for custom attributes that might contain cross-references
Write-Host "`nCustom Attributes:"
$customAttrs = @('extensionAttribute1', 'extensionAttribute2', 'extensionAttribute3',
'extensionAttribute4', 'extensionAttribute5')
foreach ($attr in $customAttrs) {
if ($account1.$attr) {
Write-Host " $user1 $attr = $($account1.$attr)"
if ($account1.$attr -match $user2) {
Write-Host " *** FOUND REFERENCE TO $user2 ***" -ForegroundColor Red
}
}
}
#------------------------------------------------------------------------------
# 4. LDAP QUERY TEST
#------------------------------------------------------------------------------
Write-Section "4. LDAP DIRECT QUERY TEST"
Write-Host "`nTesting LDAP queries for $user1..."
# Test if sAMAccountName query returns exactly one result
$ldapFilter = "(sAMAccountName=$user1)"
Write-Host "Filter: $ldapFilter"
$results = Get-ADUser -LDAPFilter $ldapFilter
$count = ($results | Measure-Object).Count
Write-Host "Results returned: $count"
if ($count -eq 1) {
Write-Host " ✓ Correct - exactly one account returned" -ForegroundColor Green
} else {
Write-Host " *** PROBLEM: Multiple accounts returned! ***" -ForegroundColor Red
foreach ($result in $results) {
Write-Host " - $($result.SamAccountName) : $($result.DistinguishedName)" -ForegroundColor Red
}
}
#------------------------------------------------------------------------------
# 5. SEARCH FOR DUPLICATE OR ORPHANED ACCOUNTS
#------------------------------------------------------------------------------
Write-Section "5. DUPLICATE/ORPHANED ACCOUNT CHECK"
Write-Host "`nSearching for any accounts with similar names or IDs..."
# Search by email domain
if ($account2.mail) {
$email = $account2.mail
Write-Host "`nAccounts with email $email or similar:"
Get-ADUser -Filter "mail -eq '$email'" -Properties SamAccountName, mail, Enabled |
Format-Table SamAccountName, mail, Enabled -AutoSize
}
# Search by givenName + surname combination
Write-Host "`nAccounts with similar name to $user2:"
$givenName = $account2.GivenName
$surname = $account2.Surname
if ($givenName -and $surname) {
Get-ADUser -Filter "GivenName -eq '$givenName' -and Surname -eq '$surname'" -Properties SamAccountName, mail, Enabled |
Format-Table SamAccountName, mail, Enabled -AutoSize
}
#------------------------------------------------------------------------------
# 6. ACCOUNT HISTORY & MODIFICATIONS
#------------------------------------------------------------------------------
Write-Section "6. RECENT ACCOUNT MODIFICATIONS"
Write-Host "`nChecking recent modifications around contamination dates..."
Write-Host "Contamination dates: 2025-09-26, 2025-10-27"
Write-Host "`n$user1 modification history:"
Write-Host " Created: $($account1.WhenCreated)"
Write-Host " Last Modified: $($account1.WhenChanged)"
Write-Host " Password Last Set: $($account1.PasswordLastSet)"
Write-Host "`n$user2 modification history:"
Write-Host " Created: $($account2.WhenCreated)"
Write-Host " Last Modified: $($account2.WhenChanged)"
Write-Host " Password Last Set: $($account2.PasswordLastSet)"
# Check for account renames
if ($account1.msDS-PrincipalName) {
Write-Host "`n$user1 previous principal names: $($account1.'msDS-PrincipalName')"
}
#------------------------------------------------------------------------------
# 7. GROUP MEMBERSHIPS
#------------------------------------------------------------------------------
Write-Section "7. GROUP MEMBERSHIP COMPARISON"
Write-Host "`nGroup memberships ($user1):"
$groups1 = $account1.MemberOf
Write-Host " Total groups: $($groups1.Count)"
Write-Host "`nGroup memberships ($user2):"
$groups2 = $account2.MemberOf
Write-Host " Total groups: $($groups2.Count)"
# Find common groups
$commonGroups = $groups1 | Where-Object { $groups2 -contains $_ }
Write-Host "`nCommon groups: $($commonGroups.Count)"
if ($commonGroups.Count -gt 0) {
foreach ($group in $commonGroups | Select-Object -First 10) {
Write-Host " - $group"
}
}
#------------------------------------------------------------------------------
# 8. EXPORT FULL ATTRIBUTES TO FILES
#------------------------------------------------------------------------------
Write-Section "8. EXPORTING DETAILED ACCOUNT DATA"
$outputPath = "C:\Temp\AD_Investigation"
New-Item -ItemType Directory -Force -Path $outputPath | Out-Null
$account1 | Format-List * | Out-File "$outputPath\${user1}_full_attributes.txt"
$account2 | Format-List * | Out-File "$outputPath\${user2}_full_attributes.txt"
Write-Host "`nFull account details exported to:"
Write-Host " $outputPath\${user1}_full_attributes.txt"
Write-Host " $outputPath\${user2}_full_attributes.txt"
# Create a comparison report
$comparison = @"
ACCOUNT COMPARISON REPORT
Generated: $(Get-Date)
Account 1: $user1
Account 2: $user2
CRITICAL CHECKS:
- Do accounts share any identifiers? $(if ($account1.ObjectGUID -eq $account2.ObjectGUID) { 'YES - PROBLEM!' } else { 'No' })
- Does $user1 reference $user2 in proxy addresses? $(if ($account1.proxyAddresses -match $user2) { 'YES - PROBLEM!' } else { 'No' })
- Modified near contamination dates?
$user1 last modified: $($account1.WhenChanged)
$user2 last modified: $($account2.WhenChanged)
Contamination dates: 2025-09-26, 2025-10-27
RECOMMENDATIONS:
1. Review the full attribute files for any cross-references
2. Check if $user1 was renamed or migrated around Sept 26, 2025
3. Verify LDAP query returns exactly one result
4. Look for stale referrals or orphaned objects
5. Check AD replication health for the dates in question
"@
$comparison | Out-File "$outputPath\comparison_report.txt"
Write-Host "`nComparison report: $outputPath\comparison_report.txt"
#------------------------------------------------------------------------------
# SUMMARY
#------------------------------------------------------------------------------
Write-Section "INVESTIGATION SUMMARY"
Write-Host "`n1. Check the exported files in: $outputPath" -ForegroundColor Cyan
Write-Host "2. Look for ANY cross-references between accounts" -ForegroundColor Cyan
Write-Host "3. Verify account modification dates match contamination timeline" -ForegroundColor Cyan
Write-Host "4. If no obvious issues found, check AD replication and LDAP server logs" -ForegroundColor Cyan
Write-Host "`nNext: Review exported files and search for '$user2' in $user1 attributes`n" -ForegroundColor Yellow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment