Windows服务器上很多安全问题的根源不是漏洞没打补丁,而是服务账号权限给得太高。一个普通的IIS应用池、一个SQL Server代理作业、一个计划任务,往往在安装或部署时被习惯性地塞进本地管理员组,甚至直接使用域管理员账号运行。短期内系统能跑通,但一旦这个服务被攻破,攻击者就直接获得了管理员权限,横向移动、凭据窃取、持久化后门都会变得极其容易。降低服务账号权限不是简单的“最小权限原则”口号,而是一套可以落地的权限梳理、配置和持续管控方法。
先搞清楚服务账号到底需要什么权限很多管理员觉得降权麻烦,是因为不清楚某个服务账号具体需要访问哪些文件、注册表项、系统对象和网络资源。盲目降权会导致服务启动失败、功能异常,最后只能又加回管理员组。正确的做法是先做权限审计。Windows自带的Process Monitor可以记录服务启动和运行过程中的所有访问请求,包括文件读写、注册表访问、进程创建和网络连接。让服务在测试环境正常运行一段时间,用Process Monitor抓取日志,筛选出“ACCESS DENIED”的记录,这些就是服务真正需要但当前被拒绝的权限。根据这些记录去配置NTFS权限、注册表权限和系统对象权限,比凭经验猜测要准确得多。
如果服务账号是域账号,还可以使用Active Directory的“有效访问”功能来查看该账号在某个文件或文件夹上的实际权限组合。在文件属性-安全-高级-有效访问中,输入服务账号名称,系统会计算出该账号最终生效的权限,包括通过组成员关系继承的部分。这个功能在排查“为什么服务账号能访问这个目录”时非常有用,也能帮助发现隐藏的权限放大路径。
用内置虚拟账号和服务账号替代真实账号Windows Server 2008 R2之后引入了托管服务账号(MSA)和虚拟账号。虚拟账号是系统自动管理的本地账号,名称格式为“NT SERVICE\服务名”,例如IIS应用池默认使用的“NT SERVICE\MSSQLSERVER”或“NT SERVICE\W3SVC”。虚拟账号不需要手动设置密码,系统会自动维护,而且它的权限范围被限制在本地计算机上,无法用于网络认证。对于不需要访问网络共享资源的服务,优先使用虚拟账号是最省事也最安全的做法。
如果服务确实需要访问网络资源,比如从NAS读取配置文件或向远程数据库写入数据,可以考虑使用组托管服务账号(gMSA)。gMSA是域级别的托管账号,密码由域控制器自动轮换,管理员不需要知道密码,也无法用这个账号交互式登录。gMSA可以配置为只在特定的计算机上运行,并且可以授予访问网络共享的权限。在域环境中,gMSA是目前最推荐的服务账号方案。配置gMSA需要域功能级别至少为Windows Server 2012,创建命令如下:
Add-KdsRootKey -EffectiveTime (Get-Date).AddHours(-10) New-ADServiceAccount -Name svc_sqlagent -DNSHostName svc_sqlagent.contoso.com -PrincipalsAllowedToRetrieveManagedPassword "SQLSERVER01$"
然后在目标服务器上安装并测试gMSA:
Install-ADServiceAccount -Identity svc_sqlagent Test-ADServiceAccount -Identity svc_sqlagent
最后将服务的“登录身份”设置为“域\svc_sqlagent$”,密码留空即可。gMSA的密码轮换由域控自动完成,即使某个服务账号的密码哈希被窃取,攻击者也无法在轮换后继续使用。
针对常见服务做专项降权IIS应用池是权限过高的重灾区。默认情况下,IIS应用池使用“ApplicationPoolIdentity”虚拟账号,这个账号本身权限很低,但很多部署脚本会把它改成管理员账号,或者给网站目录授予过宽的NTFS权限。正确的做法是保持ApplicationPoolIdentity不变,只给网站根目录授予该应用池账号的“读取和执行”、“列出文件夹内容”、“读取”权限。如果网站需要写入日志、上传文件或生成缓存,再针对具体的子目录单独授予“修改”权限。不要对整个网站目录给“完全控制”,更不要给C盘根目录或Windows目录任何权限。
SQL Server服务账号同样需要梳理。SQL Server数据库引擎服务默认使用“NT SERVICE\MSSQLSERVER”虚拟账号,这个账号权限已经足够。但很多企业在安装时习惯用域管理员账号,或者在后期为了某些脚本能执行xp_cmdshell而把SQL Server服务账号加入本地管理员组。SQL Server服务账号只需要对数据库文件目录、备份目录和错误日志目录有读写权限,对注册表中的SQL Server相关键值有读取权限。如果业务确实需要执行外部命令,应该通过SQL Server代理的代理账号来限制执行范围,而不是提升整个服务账号的权限。
计划任务的服务账号也经常被忽略。很多计划任务使用管理员账号运行,只因为脚本需要访问某个受保护的目录或者调用某个管理接口。实际上,计划任务可以单独配置“以最高权限运行”选项,这个选项只影响该任务的令牌权限,不需要把账号本身加入管理员组。如果脚本只需要访问特定目录,给该目录配置NTFS权限即可。对于需要交互式桌面访问的计划任务,可以单独设置“只在用户登录时运行”,并指定一个低权限的专用账号。
用安全策略强制约束服务账号权限权限配置得再好,如果其他管理员可以随意修改服务配置或者把账号加回管理员组,降权效果就会打折扣。Windows本地安全策略中的“用户权限分配”可以限制哪些账号能够作为服务登录、哪些账号能够修改服务配置。打开secpol.msc,在“本地策略-用户权限分配”中,找到“作为服务登录”,把不需要的账号移除,只保留系统服务、虚拟账号和明确需要的服务账号。找到“更改系统时间”、“关闭系统”、“从远程系统强制关机”等敏感权限,同样移除不必要的账号。
还可以通过“受限制的组”策略来防止服务账号被加入管理员组。在组策略中配置“受限制的组”,指定本地管理员组只能包含特定的账号和组,其他账号即使被手动加入,也会在下次组策略刷新时被自动移除。这个策略在域环境中非常有效,可以防止运维人员为了方便而临时提权后又忘记降权。
监控和审计服务账号的权限变化降权不是一次性的工作,需要持续监控。Windows安全日志中的事件ID 4732(成员被添加到安全启用的本地组)、4733(成员从安全启用的本地组中移除)、4728(成员被添加到安全启用的全局组)等可以记录组员变化。开启这些审计策略后,任何将服务账号加入管理员组的操作都会被记录下来。配合日志收集工具,可以设置告警规则,当检测到服务账号被加入高权限组时自动通知安全团队。
对于服务账号的登录行为,事件ID 4624(登录成功)和4625(登录失败)可以记录服务账号的登录时间和来源。如果某个服务账号在非预期的时间或从非预期的计算机登录,可能意味着账号被滥用或服务配置被篡改。通过分析这些日志,可以发现潜在的安全威胁。
另外,定期使用AccessChk等工具检查服务账号的实际权限也是一个好习惯。AccessChk可以列出某个账号对文件、目录、注册表项和服务控制管理器的权限。将检查结果与基线对比,可以快速发现权限漂移。例如,如果某个服务账号突然对系统目录有了写权限,说明有人修改了NTFS权限或者账号被加入了某个高权限组。
降权过程中常见的坑和应对方法第一个坑是服务降权后启动失败,报错“登录失败:未授予用户在此计算机上的请求登录类型”。这是因为服务账号没有被授予“作为服务登录”权限。在本地安全策略中把该账号加入“作为服务登录”列表即可。如果使用虚拟账号或gMSA,系统会自动授予这个权限,不需要手动配置。
第二个坑是服务账号需要访问网络共享,但虚拟账号无法进行网络认证。虚拟账号只能在本机使用,如果服务需要访问远程文件服务器,必须使用域账号或gMSA。有些管理员为了省事,直接把服务账号改成域管理员,这是最危险的做法。正确做法是创建一个普通域账号,只授予它访问特定共享目录的权限,并且限制该账号只能从特定计算机登录。
第三个坑是服务账号需要访问加密的配置文件或者证书私钥。很多服务在启动时需要读取加密的连接字符串或证书私钥,这些文件默认只允许管理员和SYSTEM账号访问。如果服务账号权限太低,就会报“拒绝访问”错误。解决办法是把服务账号加入证书私钥的ACL中,或者使用Windows的凭据管理器来存储加密凭据,而不是直接给服务账号提权。
第四个坑是某些第三方软件安装时强制要求服务账号具有管理员权限。遇到这种情况,先尝试在安装完成后手动降权,观察软件功能是否正常。如果软件确实因为权限不足而无法运行,可以联系软件厂商确认最小权限要求,或者使用Process Monitor找出具体需要访问的资源,针对性地授予权限。不要因为软件厂商说“需要管理员权限”就无条件接受,很多情况下这只是厂商为了减少支持成本而给出的保守建议。
建立服务账号权限基线和变更流程降权工作要形成制度,否则过一段时间权限又会慢慢膨胀。建议为每个服务账号建立权限基线文档,记录账号类型、所属组、文件权限、注册表权限、服务登录权限和网络访问权限。当服务需要新增权限时,走变更审批流程,由安全团队评估权限申请的合理性,确认最小权限范围后再实施。变更完成后更新基线文档,并保留审计日志。
对于新部署的服务,在部署脚本和配置管理工具中直接使用低权限账号,从源头避免权限过高。例如在Ansible、Chef或PowerShell DSC中,明确指定服务账号为虚拟账号或gMSA,并配置好所需的NTFS权限和注册表权限。这样即使部署人员没有安全意识,也不会因为默认配置而引入高权限账号。
Windows服务器服务账号降权是一个需要耐心和细致的工作,但它对整体安全态势的提升非常明显。通过审计实际权限需求、使用虚拟账号和gMSA、针对常见服务做专项配置、用安全策略强制约束、持续监控权限变化,以及建立基线和变更流程,可以把服务账号被攻破后的影响面降到最低。攻击者即使拿下了某个服务,也会发现这个账号什么都做不了,既读不到敏感文件,也改不了系统配置,更无法横向移动到其他服务器。这才是真正有效的纵深防御。
