fatihpurtas/PwdNeverExpires-audit

GitHub: fatihpurtas/PwdNeverExpires-audit

一个基于 PowerShell 的 Active Directory 安全审计脚本,用于检测并导出设置了密码永不过期标志的账户报告。

Stars: 3 | Forks: 0

# 密码永不过期分析器 此 PowerShell 脚本会枚举所有启用了 **“密码永不过期”** 标志的 **Active Directory 用户和计算机账户**,并将结果导出到 CSV 文件。 ## 目的 Active Directory 中的 **“密码永不过期”** 标志会带来重大的安全风险,因为这些账户: - 永远不需要更改密码,可能会无限期地使用弱密码或已泄露的密码 - 可能代表被遗忘的服务账户、废弃的用户账户或配置错误的系统 - 可能被攻击者用作持久化机制,一旦他们攻破了这些账户 - 通常具有提升的权限,但缺乏适当的监控 定期审查和修复具有非过期密码的账户,对于降低持久化威胁风险至关重要。 ## 主要特性 - 检测所有具有 **非过期密码** 的 AD 账户(用户和计算机) - 无需 **Active Directory PowerShell 模块** 即可工作。它仅使用内置的 **System.DirectoryServices** 类,因此可以在无法安装额外模块的受限环境中运行 - 可以在 **没有管理员权限** 的情况下运行;只需要对 AD 的读取权限 - 可以使用 `-Server` 参数指定 **特定的域控制器** - 分页 LDAP 查询(每页 1000 个对象),适用于大型域 - 将结果导出为 CSV,包含: - 名称 - 类型(用户 / 计算机) - 已启用(账户已启用或已禁用) - 创建日期 - 上次登录 - 密码上次设置时间 - 可分辨名称 - CSV 中的所有时间戳均以 **UTC** 格式写入,使用可排序的 `yyyy-MM-dd HH:mm:ss` 格式 - 导出后打印摘要(总计、已禁用的账户、无记录登录或密码设置日期的账户) ## 工作原理 1. **域检测**:自动检测当前域或接受手动输入(域名或 DN) 2. **LDAP 查询构建**:构建匹配 `userAccountControl` 中 `DONT_EXPIRE_PASSWORD` (65536) 位的 LDAP 过滤器 3. **数据收集**:在单个分页搜索中检索名称、DN、创建时间戳、上次登录、密码上次设置时间和账户状态,无需逐个对象进行往返查询 4. **日期处理**:将 FileTime 和 GeneralizedTime 值转换为可读的 UTC 时间戳 5. **CSV 导出**:生成使用 UTF-8 编码的报告 **注意**:如果未指定 `-IncludeUsers` 或 `-IncludeComputers`,则默认两者都包含。 ## 参数 | 参数 | 描述 | |-----------|-------------| | `-DomainInput` | 域名 (`example.com`) 或可分辨名称 (`DC=example,DC=com`)。省略时提示输入,默认为当前域。 | | `-Server` | 可选的直接查询的域控制器 (`dc01.example.com` 或 `dc01.example.com:636`)。 | | `-OutputPath` | CSV 输出路径。默认为 `.\PwdNeverExpires_.csv`。 | | `-IncludeUsers` | 仅查询用户账户。 | | `-IncludeComputers` | 仅查询计算机账户。 | ## 用法 ### 交互模式 提示选择域并包含所有账户类型: ``` .\PwdNeverExpires.ps1 ``` ### 特定域分析 ``` .\PwdNeverExpires.ps1 -DomainInput "example.com" ``` ### 仅用户 ``` .\PwdNeverExpires.ps1 -IncludeUsers -OutputPath "C:\Audit\UsersNeverExpire.csv" ``` ### 仅计算机 ``` .\PwdNeverExpires.ps1 -IncludeComputers -DomainInput "subsidiary.company.com" ``` ### 跨域分析 ``` .\PwdNeverExpires.ps1 -DomainInput "DC=remote,DC=domain,DC=com" -IncludeUsers ``` ### 查询特定域控制器 ``` .\PwdNeverExpires.ps1 -DomainInput "example.com" -Server "dc01.example.com" ``` ## 示例输出 | 名称 | 类型 | 已启用 | 创建时间 | 上次登录 | 密码上次设置时间 | 可分辨名称 | |------|------|---------|----------|-----------|------------|-------------------| | ServiceAccount | User | True | 2020-01-15 08:30:00 | 2025-01-20 14:22:15 | 2020-01-15 08:30:00 | CN=ServiceAccount,OU=Service_Accounts,DC=company,DC=com | | LegacyApp | User | False | 2018-05-10 12:00:00 | | 2018-05-10 12:00:00 | CN=LegacyApp,OU=Applications,DC=company,DC=com | | AdminUser | User | True | 2019-03-20 09:15:30 | 2025-01-25 11:45:22 | 2019-03-20 09:15:30 | CN=AdminUser,OU=Administrators,DC=company,DC=com | | TestComputer$ | Computer | True | 2021-07-08 16:20:00 | 2024-12-15 10:30:45 | 2021-07-08 16:20:00 | CN=TestComputer,OU=Workstations,DC=company,DC=com | ## 要求与注意事项 - **PowerShell 5.1 或更高版本**(使用 .NET DirectoryServices 类) - **加入域的机器**或与目标域的网络连接 - 对 Active Directory 的 **读取权限**(通常 Domain Users 足矣) - 端口 389(或 LDAPS 使用 636)上的 **LDAP 连接** - `lastLogon` 不会在域控制器之间复制;`lastLogonTimestamp`(优先使用)会被复制,但可能比实际的上次登录时间滞后最多 14 天 ## 安全影响 ### 常见攻击场景 针对密码永不过期账户的攻击者通常遵循以下模式: 1. **服务账户攻陷**:通过凭证填充或密码喷洒,以具有永不过期密码的服务账户为目标 2. **休眠账户利用**:发现废弃的账户,将其作为进入环境的后门 3. **横向移动**:使用被攻陷的永不过期账户遍历网段 4. **建立持久化**:通过不需要更改密码的账户维持长期访问权限 这造成了一个长期保持稳定的 **持久化攻击面**。 ### 缓解措施与最佳实践 - 为所有服务账户进行 **定期密码轮换**(尽可能使用组托管服务账户) - **账户生命周期管理**,以识别和禁用休眠账户: ``` $Results = Import-Csv .\PwdNeverExpires_example_com.csv $StaleAccounts = $Results | Where-Object { -not $_.LastLogon -or [datetime]$_.LastLogon -lt (Get-Date).AddDays(-90) } ``` - **权限审查**,确保账户具有所需的最低权限 - **实施监控**,针对这些账户的异常登录模式: - 为永不过期账户在非工作时间登录设置警报 - 监控服务账户上的多次失败登录尝试 - 跟踪这些账户的提权尝试 - 与组织密码策略保持 **合规性一致** - 尽可能实施 **组托管服务账户 (gMSA)**,以完全消除静态密码
标签:Active Directory, AI合规, Checkov, IPv6, LDAP查询, Libemu, MSSQL, Plaso, PowerShell, Terraform 安全, 多人体追踪, 密码策略审计, 系统运维