Windows服务器中的组策略首选项(Group Policy Preferences,简称GPP)存在一个严重的密码存储漏洞:当管理员使用组策略首选项来部署本地用户账户、计划任务、服务或映射驱动器时,如果在设置中填入了密码,这些密码会以AES-256加密的形式存储在域控制器的SYSVOL共享文件夹中。问题在于,微软在2012年之前公开了加密所用的密钥,任何能够访问SYSVOL的域内用户都可以解密这些密码,直接获取明文。这意味着你以为安全的密码部署,实际上等于把密码写在了一张所有人都能看到的纸上,只是用了一层薄薄的纱盖着。

这个漏洞的核心在于GPP使用了一个固定的AES密钥来加密存储在XML文件中的密码字段。具体来说,密码被存储在SYSVOL目录下的Group Policy文件夹中,路径通常为:\\域名\SYSVOL\域名\Policies\{策略GUID}\Machine\Preferences\Groups\Groups.xml 或者类似的XML文件中。攻击者只需要获取这个文件,利用已知的默认密钥进行解密,就能拿到所有在该策略中配置的明文密码。

漏洞的具体技术原理

要理解这个漏洞,需要先搞清楚GPP的工作机制。组策略首选项是微软提供的一种扩展功能,允许管理员通过组策略来创建本地用户、部署软件、设置注册表项等。当你在组策略管理控制台中创建一个"本地用户和组"的首选项项目,并勾选"创建"、"更新"或"替换"操作时,如果你在密码字段中输入了密码,系统就会对这个密码进行加密处理。

加密过程使用的是AES-256算法,但密钥是固定的。微软在MS14-025安全公告中披露了这个默认密钥。该密钥的值为:4e 99 06 e8 fc b6 6c c9 fa f4 93 10 62 0f fe e8 f4 96 e8 06 cc 05 79 90 20 9b 09 a4 33 b6 6c 1b。任何知道这个密钥的人,都可以使用标准的AES解密工具还原出密码明文。

存储密码的XML文件结构大致如下,其中cpassword字段就是加密后的密码:

<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}">
  <User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="Administrator" image="2" changed="2023-01-15 10:30:00" uid="{GUID}">
    <Properties action="U" newName="" fullName="" description="" cpassword="AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA..." />
  </User>
</Groups>

看到cpassword字段中那一长串Base64编码的字符串了吗?那就是加密后的密码。用已知密钥一解密,明文就出来了。整个过程不需要任何高级攻击技术,一个域内的普通用户权限就足以完成。

谁能利用这个漏洞

这个漏洞的利用门槛极低。只要满足以下任一条件,攻击者就可以获取SYSVOL中的GPP XML文件:任何已加入域的普通用户、任何拥有域内有效凭据的账户、任何通过其他方式获得了域内低权限访问的攻击者。因为SYSVOL是域内所有经过身份验证的用户默认可读的共享文件夹,这意味着几乎每个域用户都有权限去读取这些文件。

一旦攻击者拿到了XML文件并解密出密码,后果可能非常严重。如果GPP策略中配置的是本地管理员账户的密码,攻击者就可以在任何域内机器上以管理员身份登录。如果配置的是服务账户密码,攻击者可能获得对关键业务系统的访问权限。如果配置的是计划任务中使用的凭据,攻击者可能获得执行任意代码的能力。

如何检测你的环境是否存在这个漏洞

检测方法其实很简单。你需要在域控制器上或者任何能访问SYSVOL的机器上,搜索包含cpassword字段的XML文件。具体操作步骤如下:首先打开命令提示符或者PowerShell,导航到SYSVOL的Policies目录;然后使用findstr或者Select-String命令搜索包含"cpassword"关键字的文件。

findstr /s /i "cpassword" C:\Windows\SYSVOL\domain\Policies\*.xml

如果找到了任何包含cpassword字段的文件,说明你的环境中存在使用GPP存储密码的策略,这些密码都是可以被解密的。另外,你也可以使用一些自动化工具来扫描,比如PowerSploit框架中的Get-GPPPassword模块,或者使用专门的审计工具如BloodHound来分析域内的攻击路径。

Import-Module .\Get-GPPPassword.ps1
Get-GPPPassword

这个PowerShell脚本会自动扫描SYSVOL中的所有GPP XML文件,尝试用已知密钥解密其中的密码,并以明文形式输出结果。运行之后你就能清楚地看到哪些账户的密码被暴露了。

修复和防御措施

修复这个漏洞需要从多个层面入手,不能只做一件事就以为安全了。以下是完整的修复方案,按优先级排列。

第一步,立即删除所有包含敏感密码的GPP策略。打开组策略管理控制台(GPMC),检查所有使用"本地用户和组"、"计划任务"、"服务"、"数据源"、"打印机"等首选项项目的策略,找到其中包含密码设置的项目,直接删除或者重新配置为不使用密码的方式。删除后,强制刷新组策略让所有客户端同步更新。

第二步,安装微软的安全更新MS14-025。这个补丁虽然不能修复已经泄露的密码,但它会阻止未来新创建的GPP策略使用那个已知的默认密钥进行加密。不过需要注意,这个补丁只是一个缓解措施,并不是根本解决方案,因为它只是换了一个密钥,如果新密钥再次泄露,问题依然存在。

第三步,修改所有已经被暴露的密码。这是最关键的一步。既然密码已经可能被攻击者获取,你必须假设它们已经泄露。立即更改所有在GPP策略中配置过的账户密码,包括本地管理员账户、服务账户、计划任务账户等。而且不是改一次就够了,建议改完之后观察一段时间,确认没有异常登录行为后再稳定下来。

第四步,从根本上避免在GPP中存储密码。微软官方的建议是不要使用组策略首选项来部署包含密码的本地用户账户。如果确实需要批量管理本地管理员密码,应该使用微软的LAPS(Local Administrator Password Solution)工具。LAPS会为每台机器自动生成随机的、唯一的本地管理员密码,并将其安全地存储在Active Directory中,只有授权用户才能读取。

# 安装LAPS的PowerShell命令
Install-WindowsFeature -Name RSAT-LAPS
Set-AdmPwdComputerSelfPermission -OrgUnit "OU=Servers,DC=domain,DC=com"

第五步,限制SYSVOL的访问权限。虽然这不能完全解决问题,但可以增加攻击者获取文件的难度。确保只有必要的账户和服务才能访问SYSVOL共享,定期审计访问日志,监控是否有异常的文件读取行为。

为什么这个漏洞到现在还在被利用

尽管这个漏洞早在2014年就被微软公开并发布了补丁,但在实际环境中,大量企业仍然存在这个问题。原因主要有几个方面:很多老旧的组策略是多年前创建的,管理员早就忘了里面配置了什么;一些企业的IT团队缺乏安全审计意识,从来没有检查过SYSVOL中的文件;还有一些企业因为业务需要,不得不继续使用GPP来部署密码,明知有风险也只能硬着头皮用。

更深层的原因在于,很多组织对组策略的管理非常松散。策略创建之后就没人管了,没有定期审查机制,没有变更记录,没有安全基线检查。这种管理上的缺失,比技术漏洞本身更危险。一个已经打了补丁的系统,如果管理不到位,依然会出问题。

扩展:其他类似的密码存储风险

GPP密码漏洞并不是Windows环境中唯一的密码存储问题。类似的风险还存在于其他地方。比如,Windows任务计划程序中存储的凭据、IIS应用程序池中的身份凭据、Windows凭据管理器中保存的密码、以及一些第三方管理工具在本地存储的加密凭据。这些都可能因为加密方式不当或者密钥管理不善而被攻击者获取。

特别值得注意的是,很多企业使用的第三方运维工具、自动化部署工具,会在本地存储数据库连接字符串、API密钥等敏感信息。这些信息如果使用了硬编码的加密密钥或者弱加密算法,同样面临被破解的风险。建议企业建立统一的密钥管理体系,使用专业的密钥管理服务(KMS)或者硬件安全模块(HSM)来保护所有敏感凭据。

总结和行动建议

Windows服务器GPP密码存储漏洞是一个典型的"设计缺陷加管理疏忽"导致的安全问题。技术上,它源于微软使用了固定密钥进行加密;管理上,它源于企业缺乏对组策略的定期审计和安全审查。要彻底解决这个问题,需要技术修复和管理改进双管齐下。

立即行动清单:今天就去检查SYSVOL中有没有包含cpassword的XML文件;如果有,立刻删除相关策略并更改所有涉及的密码;部署LAPS替代GPP进行本地密码管理;建立每季度一次的组策略安全审计机制;对所有IT管理员进行安全意识培训,明确禁止在GPP中存储任何敏感密码。安全不是一次性的工作,而是持续的过程。这个漏洞虽然老,但只要你的环境里还有它,它就依然是一颗定时炸弹。