fatihpurtas/AdminSDHolder-scanner

GitHub: fatihpurtas/AdminSDHolder-scanner

PowerShell 脚本,用于扫描 Active Directory 中受 AdminSDHolder 保护的账户(adminCount=1),检测权限提升风险并导出 CSV 审计报告。

Stars: 1 | Forks: 0

# AdminSDHolder 用户分析脚本 此 PowerShell 脚本用于识别具有 `AdminSDHolder` 保护(`adminCount=1`)的 **Active Directory** 用户,分析其组成员关系以进行高权限检测,过滤掉系统账户和禁用的账户,并将结果导出为 **CSV 报告**。 ## 目的 在 Active Directory 中,具有 `adminCount=1` 的用户通常是**受保护组**(例如,Domain Admins、Enterprise Admins)的成员。 即使用户已从这些组中移除,`adminCount=1` 标志通常也会保留。这意味着该账户将继续受到 AdminSDHolder 的保护,保留其以前具有特权时继承的 ACL。 - 检测这些用户并分析其当前的权限状态。 - 根据组成员关系分析对用户进行分类。 - 排除 `krbtgt`、`Administrator`、计算机账户(以 `$` 结尾)和禁用的账户。 - 将剩余需要审查的账户导出为 **CSV 文件**。 ## 工作原理 1. 使用启用了**分页**(每页 1000 个对象)的 `DirectorySearcher` 查找所有 `adminCount=1` 的用户,即使是在大型域中也能生效。 2. 收集用户属性: - **Name**(姓名) - **SamAccountName** - **AdminCount** - **DistinguishedName** - **Group Memberships**(组成员关系) - **UserAccountControl** 3. 分析组成员关系以确定权限状态: - **True**:确认是高权限组的成员(见下方列表) - **False**:具有组成员身份,但没有任何高权限组 - **No Group Membership**:未找到直接组成员关系(需要手动检查嵌套权限) 4. 评估 `userAccountControl` 以排除被禁用的用户。 5. 排除系统账户(`krbtgt`、`Administrator`、计算机对象),因为这些是默认或服务账户,不代表需要进行安全审查的真实用户账户。 6. 将过滤后的用户导出为 **CSV** 文件。 ## 高权限检测逻辑 脚本从每个 `memberOf` 的可分辨名称中提取 `CN`,并将其(精确、不区分大小写)与以下已知的高权限/操作员组进行比较: - **Domain Admins**、**Enterprise Admins**、**Schema Admins** - **Administrators** - **Account Operators**、**Backup Operators**、**Server Operators**、**Print Operators** - **Key Admins**、**Enterprise Key Admins** 精确的 CN 匹配避免了子字符串匹配可能产生的误报(例如,名称仅包含 "Admins" 的自定义组)。 **重要限制:** - 仅检测**直接组成员关系**(不包含嵌套的组关系)。 - 标记为 "No Group Membership" 的用户可能仍具有以下权限: - 嵌套组成员关系 - 主组设置 - 特殊权限或角色 - 历史权限分配 ## 输出 脚本会将摘要信息打印到控制台: - **找到的用户总数** - **需要审查的用户** - **CSV 文件名** CSV 文件命名为: ``` adminsdholder_users_.csv ``` 示例:`adminsdholder_users_fatih_local.csv` ### CSV 列 - **Name**:用户的显示名称 - **SamAccountName**:登录名 - **HighPrivilege**:权限状态(True/False/No Group Membership) - **DistinguishedName**:完整的 AD 路径 - **Groups**:组成员关系列表(或 "No Groups") - **UserAccountControl**:账户控制标志 - **AdminCount**:AdminSDHolder 标志值 ## 示例 CSV 输出 ## | Name | SamAccountName | HighPrivilege | DistinguishedName | Groups | UserAccountControl | AdminCount | |---------------|----------------|----------------------|---------------------------------------------------------|-------------------------------------------|-------------------|------------| | Fatih Purtaş | fpurtas | True | CN=Fatih Purtaş,OU=Users,OU=IT,DC=fatih,DC=local | CN=Domain Admins,CN=Users,DC=fatih,DC=local; CN=Enterprise Admins,CN=Users,DC=fatih,DC=local; CN=IT-Admin,OU=Groups,DC=fatih,DC=local| 66048 | 1 | | Kevin Mitnick | kmitnick | False | CN=Kevin Mitnick,OU=Support,OU=Groups,DC=fatih,DC=local | CN=Help Desk,OU=Groups,DC=fatih,DC=local; CN=IT Support,OU=Groups,DC=fatih,DC=local; CN=File Share Users,OU=Groups,DC=fatih,DC=local | 512 | 1 | | Bruce Schneier| bschneier | No Group Membership | CN=Bruce Schneier,OU=Former\_Employees,DC=fatih,DC=local| No Groups | 512 | 1 | | Terry Davis | tdavis | True | CN=Terry Davis,OU=Admins,OU=IT,DC=fatih,DC=local | CN=Schema Admins,CN=Users,DC=fatih,DC=local; CN=Exchange Organization Admins,OU=Exchange,DC=fatih,DC=local| 512 | 1 | | Marcus Hutchins| mhutchins | False | CN=Marcus Hutchins,OU=Marketing,OU=Users,DC=fatih,DC=local| CN=Marketing Team,OU=Groups,DC=fatih,DC=local; CN=Sales Access,OU=Groups,DC=fatih,DC=local; CN=VPN Users,OU=Groups,DC=fatih,DC=local | 66048 | 1 | ## 用法 在 PowerShell 中运行脚本: ``` .\AdminSDHolder.ps1 ``` 可选参数: ``` # 查询特定的 domain controller 并选择输出路径 .\AdminSDHolder.ps1 -Server dc01.example.com -OutputPath C:\Audit\adminsd.csv # 将搜索范围限定到特定的 OU .\AdminSDHolder.ps1 -SearchBase "OU=IT,DC=example,DC=com" ``` | Parameter | Description | |-----------|-------------| | `-Server` | 直接查询的域控制器(`dc01.example.com` 或 `:636`)。默认为当前域。 | | `-SearchBase` | 用于限制搜索范围的可分辨名称。默认为域的默认命名上下文。 | | `-OutputPath` | CSV 输出路径。默认为 `.\adminsdholder_users_.csv`。 | 如果 PowerShell 执行策略阻止了脚本运行,您可以暂时绕过它们: ``` powershell -ExecutionPolicy Bypass -File "C:\Path\To\AdminSDHolder.ps1" ``` ## 示例输出 ``` === ADMINSDHOLDER USER ANALYSIS === Total accounts with adminCount=1: 15 Accounts requiring review: 3 - Confirmed high privilege: 1 - No group membership (nested?): 1 CSV file saved (Unicode): .\adminsdholder_users_example_com.csv ``` ## 要求与说明 - 不需要额外的 PowerShell 模块。脚本使用**内置的 .NET 类**运行。 - 必须在**加入域**的机器上执行。 - 应手动审查生成的账户,以验证它们是否具有特权访问权限。 - 标记为 "No Group Membership" 的用户需要**进一步调查**其嵌套权限。 ## 安全影响 ### 为什么这很重要 **AdminSDHolder** 机制旨在通过每 60 分钟应用一次静态访问控制列表(ACL)来保护特权账户(例如,Domain Admins)。 任何具有 `adminCount=1` 的账户都将继承这些保护,使其具有很高的权限并且能够抵抗委派更改。 ### 攻击者如何利用它 破坏了低权限账户的攻击者可能会: - 将该账户添加到受保护组中(例如,Domain Admins)。 - 结果,该账户获得 `adminCount=1` 并继承 AdminSDHolder 保护。 - 即使该账户后来从组中被移除,该标志(`adminCount=1`)通常仍会保持设置状态,从而使该账户具有**持续提升的权限**。 这为攻击者在 AD 环境中创建了一种**隐蔽的持久化机制**。 ### 分析结果解读 - **True**:紧急安全问题 - 用户已确认具有高权限。 - **False**:优先级较低 - 用户具有组成员身份,但未检测到高权限。 - **No Group Membership**:**手动审查的高优先级** - 用户可能具有: - 脚本未检测到的嵌套组权限 - 需要清理的历史权限 - 特殊权限或主组设置 ### 缓解措施与最佳实践 - **定期审计**具有 `adminCount=1` 的账户(将此脚本作为安全检查的一部分)。 - 为不再属于特权组的账户**重置 adminCount 值**。 - 这可以通过删除属性并重新应用正常的 ACL 继承来完成。 - 方法 1:使用 PowerShell(需要 AD 模块) - Set-ADUser -Identity "username" -Clear adminCount - 方法 2:使用 ADSI Edit - 打开 ADSI Edit → 连接到默认命名上下文 - 导航到该用户对象 - 右键单击 → 属性 → 找到 "adminCount" 属性 - 删除 adminCount 属性或将其设置为 0 - **手动调查**状态为 "No Group Membership" 的用户,以排查嵌套权限。 - 将受保护组的成员资格**限制**在所需的最低限度内。 - 使用 SIEM 或 AD 审计工具**监控组更改**,以检测可疑的权限提升尝试。 - **实施分层管理**,以减少高价值账户的暴露风险。
标签:Active Directory, AI合规, Libemu, Plaso, Terraform 安全, Windows PowerShell, 多人体追踪, 权限分析, 特权账号发现