如何用PowerShell审核AD安全组事件4728/4729并检测组策略异常?
可行方案:结合PowerShell事件查询与组配置快照对比
一、先获取两组基准数据
1. 导出安全组的既定默认配置
用AD模块命令导出目标安全组的原始成员,保存为基准文件:
# 替换为你的目标安全组名称,支持通配符 $targetGroups = "SG-*", "Finance-*" Get-ADGroupMember -Identity $targetGroups -Recursive | Select-Object @{Name="GroupName"; Expression={$_.Parent}}, SamAccountName, ObjectClass | Export-Csv -Path "C:\AD_SecurityGroups_Baseline.csv" -NoTypeInformation -Encoding UTF8
2. 提取周末的组变更事件
查询目标域控制器的安全日志,解析4728(添加成员到组)和4729(从组移除成员)事件,还原周末的组操作记录:
# 替换为实际的周末时间段 $startTime = Get-Date "2024-05-18 00:00:00" $endTime = Get-Date "2024-05-19 23:59:59" # 查询指定域控制器的安全事件 $events = Get-WinEvent -LogName Security -ComputerName "DC01" -FilterHashtable @{ Id = 4728, 4729 StartTime = $startTime EndTime = $endTime } | ForEach-Object { $eventXml = [xml]$_.ToXml() [PSCustomObject]@{ TimeCreated = $_.TimeCreated GroupName = ($eventXml.Event.EventData.Data | Where-Object Name -eq "TargetUserName")."#text" MemberName = ($eventXml.Event.EventData.Data | Where-Object Name -eq "MemberName")."#text" Operation = if ($_.Id -eq 4728) { "Added" } else { "Removed" } } } $events | Export-Csv -Path "C:\AD_GroupChanges_Weekend.csv" -NoTypeInformation -Encoding UTF8
二、对比数据找出未恢复的异常
1. 对比基准与当前组状态
导出当前安全组的成员,和基准文件对比,找出新增的未移除成员:
# 导出当前目标安全组成员 Get-ADGroupMember -Identity $targetGroups -Recursive | Select-Object @{Name="GroupName"; Expression={$_.Parent}}, SamAccountName, ObjectClass | Export-Csv -Path "C:\AD_SecurityGroups_Current.csv" -NoTypeInformation -Encoding UTF8 # 导入数据并对比差异 $baseline = Import-Csv -Path "C:\AD_SecurityGroups_Baseline.csv" $current = Import-Csv -Path "C:\AD_SecurityGroups_Current.csv" # 筛选基准中没有、但当前存在的成员(即未恢复的临时添加) $unremovedMembers = Compare-Object -ReferenceObject $baseline -DifferenceObject $current -Property GroupName, SamAccountName | Where-Object SideIndicator -eq "=>" $unremovedMembers | Format-Table GroupName, SamAccountName, ObjectClass -AutoSize
2. 结合事件验证临时操作是否未恢复
从周末的事件记录中,筛选出只添加未移除的操作,确认异常来源:
$groupChanges = Import-Csv -Path "C:\AD_GroupChanges_Weekend.csv" # 找出有添加记录但无后续移除记录的操作 $tempAddsWithoutRemoval = $groupChanges | Where-Object Operation -eq "Added" | ForEach-Object { $addEvent = $_ $hasRemoval = $groupChanges | Where-Object { $_.GroupName -eq $addEvent.GroupName -and $_.MemberName -eq $addEvent.MemberName -and $_.Operation -eq "Removed" -and $_.TimeCreated -gt $addEvent.TimeCreated } if (-not $hasRemoval) { $addEvent } } $tempAddsWithoutRemoval | Format-Table TimeCreated, GroupName, MemberName, Operation -AutoSize
三、关键注意事项
- 确保执行PowerShell的账号拥有域控制器安全日志读取权限和AD组读取权限
- 多域控制器环境下,需遍历所有目标DC执行事件查询,避免遗漏
- 安全日志存在滚动覆盖风险,建议定期备份或启用事件集中转发
- 嵌套组需使用
-Recursive参数,确保获取全层级成员
内容的提问来源于stack exchange,提问作者nathann18
相关产品推荐
相关产品推荐

