目录
[🧠 权限中文释义](#🧠 权限中文释义)
[🔬 权限底层原理详解](#🔬 权限底层原理详解)
[🛠️ 内网渗透中的实战滥用原理与步骤](#🛠️ 内网渗透中的实战滥用原理与步骤)
[详细滥用步骤(以 PowerView 为例)](#详细滥用步骤(以 PowerView 为例))
[🎯 攻击价值与链式利用](#🎯 攻击价值与链式利用)
[🛡️ 检测与防御建议](#🛡️ 检测与防御建议)

🔐 ForceChangePassword 权限深度解析与实战滥用说明
🧠 权限释义
ForceChangePassword(用户强制更改密码扩展权限)是 Active Directory 中一种极为危险的对象级别权限。
-
核心含义:允许持有者在完全不知道目标用户当前密码 的前提下,强制重置该用户的新密码。
-
危险程度:一旦滥用,等同于直接接管目标用户身份,无需任何密码破解过程。
-
常见来源:ACL 配置不当、权限过度委派、历史遗留权限或 GenericAll/AllExtendedRights 继承而来。
-
适用对象:主要针对用户对象(User Class),也可出现在计算机账户等场景。
🔬 权限底层原理详解
ForceChangePassword 本质上是 Active Directory 的扩展访问控制权限(Extended Right),其 GUID 为:
00299570-246d-11d0-a768-00aa006e0529
底层核心机制
-
Active Directory 用户密码存储在 unicodePwd 属性中,该属性只写不读(write-only),普通 LDAP 查询无法读取。
-
正常用户自行改密(Change Password)需要:
-
提供旧密码(验证旧值)。
-
拥有对自身 unicodePwd 的"User-Change-Password"控制访问权。
-
通过 LDAP Modify 操作替换旧密码。
-
-
强制重置密码(Reset/Force Change)则完全不同:
-
不需要旧密码。
-
域控只检查调用者是否拥有目标用户对象的User-Force-Change-Password 扩展权限。
-
拥有该权限后,可直接通过 LDAP 写入 unicodePwd 新值。
-
域控内部会强制失效旧密码,并应用新密码。
-
-
关键对比:
-
普通改密 → 需要旧密码 + 自有权限。
-
ForceChangePassword → 绕过旧密码验证,仅靠 ACL 权限直接写 unicodePwd。
-
-
为什么危险:相当于域控"信任"你有权直接重写该用户的身份凭证,而不走任何验证流程。
权限授予方式
-
直接授予:Security Descriptor 中的 ACE(Access Control Entry)允许"Control Access" + 该 GUID。
-
间接授予:通过 GenericAll(完全控制)或 AllExtendedRights(所有扩展权限)间接继承该能力。
🛠️ 内网渗透中的实战滥用原理与步骤
在红队/渗透测试中,ForceChangePassword 是典型的权限提升 与横向移动利器,常出现在 BloodHound 路径分析中。
滥用本质
-
攻击者通过该权限重置目标密码 → 获得明文凭据 → 以目标用户身份登录/认证 → 利用目标原有权限继续渗透。
-
不触发"密码修改"事件,而是"密码重置"事件(Event ID 4724)。
推荐滥用工具与方法对比
-
不推荐:net.exe / net user
-
命令:
net user 目标用户名 新密码 /domain -
缺点:日志明显(命令行记录)、易触发 EDR 告警、需要当前上下文具备权限。
-
-
强烈推荐:PowerView 的 Set-DomainUserPassword
- 优势:支持替代凭据、行为像正常 LDAP 操作、OPSEC 友好、可在非特权会话执行。
详细滥用步骤(以 PowerView 为例)
-
导入 PowerView 在 PowerShell 会话中加载 PowerView 脚本(Invoke-WebRequest 下载或本地导入)。
-
准备替代凭据(如果当前不是有权限用户)
cpp# 1. 将明文密码转为 SecureString $SecPassword = ConvertTo-SecureString 'Password@123!' -AsPlainText -Force # 2. 创建 PSCredential 对象(使用有 ForceChangePassword 权限的账户) $Cred = New-Object System.Management.Automation.PSCredential('DOMAIN\privileged_user', $SecPassword) -
准备新密码
cpp# 将要设置的新密码转为 SecureString $NewPass = ConvertTo-SecureString 'NewStrongPass123!' -AsPlainText -Force -
执行强制改密
cpp/* --------------------- Set-DomainUserPassword 参数1:-Identity(目标用户 sAMAccountName 或 DistinguishedName) 参数2:-AccountPassword(新密码 SecureString) 参数3:-Credential(可选,替代凭据 PSCredential) 1. 通过 LDAP 连接到域控 2. 验证调用者是否有 User-Force-Change-Password 权限(GUID 检查) 3. 构造 LDAP Modify 请求,直接写入 unicodePwd 属性 4. 域控应用新密码并失效旧凭据 5. 无需目标用户在线或知道旧密码 ---------------- */ Set-DomainUserPassword -Identity targetuser -AccountPassword $NewPass -Credential $Cred -
验证与利用 使用新密码登录目标用户 → RDP/WinRM/横向移动 → 继续滥用该用户持有的其他 ACL。
其他滥用工具(补充)
-
Impacket:
impacket-changepasswd domain/user@dc-ip -newpass 新密码 -reset -
BloodyAD / ldap_shell 等 Linux 工具也可实现类似操作。
🎯 攻击价值与链式利用
-
直接获得明文凭据 → 绕过哈希传递限制。
-
登录目标用户有权限的服务器(RDP、SMB 等)。
-
利用目标用户对其他对象的ACL 权限(如 GenericAll、Owns 等)继续提权。
-
常见链路:普通用户 → 有 ForceChangePassword 到高价值用户 → 接管管理员/服务账户 → 域控。
🛡️ 检测与防御建议
-
检测:监控域控 Event ID 4724(尝试重置密码)、PowerShell 执行日志、LDAP 异常写入 unicodePwd。
-
防御:定期审计 ACL、使用 BloodHound 扫描异常委派、遵循最小权限原则、禁用不必要的扩展权限。
总结 :ForceChangePassword 不是密码破解,而是身份重写的钥匙。在内网渗透中,它往往是通向更高权限的捷径,一旦发现,必须立即修复 ACL。