Public/Get-PrivilegedGroupReport.ps1
|
function Get-PrivilegedGroupReport { <# .SYNOPSIS Audits membership of privileged Active Directory groups. .DESCRIPTION Reports on membership of high-privilege AD groups including Domain Admins, Enterprise Admins, Schema Admins, Administrators, and custom groups. Flags accounts that may be a risk: - Service accounts in admin groups - Accounts with passwords that never expire - Accounts that haven't logged in recently - Nested group memberships .PARAMETER AdditionalGroups Additional group names to include in the audit beyond the defaults. .PARAMETER DaysInactive Threshold to flag inactive privileged accounts. Defaults to 30 days. .EXAMPLE Get-PrivilegedGroupReport .EXAMPLE Get-PrivilegedGroupReport -AdditionalGroups "SQL-Admins","Backup Operators" -DaysInactive 14 #> [CmdletBinding()] param( [string[]]$AdditionalGroups, [int]$DaysInactive = 30 ) $defaultGroups = @( 'Domain Admins', 'Enterprise Admins', 'Schema Admins', 'Administrators', 'Account Operators', 'Server Operators', 'Backup Operators', 'Print Operators' ) $groupsToAudit = $defaultGroups if ($AdditionalGroups) { $groupsToAudit += $AdditionalGroups } $inactiveThreshold = (Get-Date).AddDays(-$DaysInactive) foreach ($groupName in $groupsToAudit) { try { $group = Get-ADGroup -Identity $groupName -Properties Members -ErrorAction Stop } catch { Write-Verbose "Group not found: $groupName" continue } $members = Get-ADGroupMember -Identity $groupName -Recursive -ErrorAction SilentlyContinue $memberDetails = foreach ($member in $members) { if ($member.objectClass -eq 'user') { $user = Get-ADUser -Identity $member -Properties LastLogonDate, PasswordLastSet, PasswordNeverExpires, Enabled, Description, WhenCreated $flags = [System.Collections.Generic.List[string]]::new() if ($user.PasswordNeverExpires) { $flags.Add('PasswordNeverExpires') } if (-not $user.Enabled) { $flags.Add('Disabled') } if ($user.LastLogonDate -and $user.LastLogonDate -lt $inactiveThreshold) { $flags.Add('Inactive') } if (-not $user.LastLogonDate) { $flags.Add('NeverLoggedIn') } if ($user.Description -match 'svc|service') { $flags.Add('PossibleServiceAccount') } [PSCustomObject]@{ MemberName = $user.Name SAMAccountName = $user.SAMAccountName Type = 'User' Flags = $flags -join '; ' } } elseif ($member.objectClass -eq 'group') { [PSCustomObject]@{ MemberName = $member.Name SAMAccountName = $member.SAMAccountName Type = 'NestedGroup' Flags = 'NestedGroup' } } } [PSCustomObject]@{ GroupName = $groupName MemberCount = @($members).Count Members = $memberDetails Flags = @($memberDetails | Where-Object Flags -ne '').Count } } } |