Public/Security/Find-SuspiciousGroupMemberships.ps1
|
function Find-SuspiciousGroupMemberships { [CmdletBinding()] param( [Parameter(Mandatory)] [object[]]$Groups, [object[]]$Users, [hashtable]$ApprovedMembers = @{ "Domain Admins" = @("Administrator") "Enterprise Admins" = @("Administrator") "Schema Admins" = @("Administrator") }, [int]$NewAccountThresholdDays = 30 ) $suspiciousFindings = @() # Get all privileged groups and their known patterns $privilegedGroups = @{ "Domain Admins" = @{ MaxMembers = 5 RequiredNaming = "admin" RiskLevel = "Critical" } "Enterprise Admins" = @{ MaxMembers = 3 RequiredNaming = "admin" RiskLevel = "Critical" } "Schema Admins" = @{ MaxMembers = 2 RequiredNaming = "admin" RiskLevel = "Critical" } "Backup Operators" = @{ MaxMembers = 5 RiskLevel = "High" } } foreach ($group in $Groups) { if ($privilegedGroups.ContainsKey($group.Name)) { $groupConfig = $privilegedGroups[$group.Name] $approvedList = $ApprovedMembers[$group.Name] # Check total member count if ($group.Members.Count -gt $groupConfig.MaxMembers) { $suspiciousFindings += [PSCustomObject]@{ GroupName = $group.Name Finding = "Excessive Members" Details = "Group has $($group.Members.Count) members, expected max $($groupConfig.MaxMembers)" RiskLevel = $groupConfig.RiskLevel TimeDetected = Get-Date } } foreach ($memberDN in $group.Members) { $member = $Users | Where-Object { $_.DistinguishedName -eq $memberDN } if ($member) { # Check if member is approved if (-not ($approvedList -contains $member.SamAccountName)) { $finding = [PSCustomObject]@{ GroupName = $group.Name MemberName = $member.SamAccountName Finding = "Unauthorized Member" Details = "Member not in approved list" RiskLevel = $groupConfig.RiskLevel TimeDetected = Get-Date } # Additional checks for suspicious patterns if ($member.Created -gt (Get-Date).AddDays(-$NewAccountThresholdDays)) { $finding.Finding = "Recently Created Account in Privileged Group" $finding.RiskLevel = "Critical" } if ($member.Enabled -eq $false) { $finding.Finding = "Disabled Account in Privileged Group" } $suspiciousFindings += $finding } } } } } return $suspiciousFindings } |