Windows服务器权限最小化不是装个杀毒软件或者改个管理员密码那么简单,它本质上是在回答一个问题:这个系统里每一个账户、每一个服务、每一个进程,到底需要多大的权力才能完成自己的工作。大多数被攻破的Windows服务器,攻击者之所以能快速横向移动或植入后门,往往不是因为漏洞本身有多高级,而是因为初始权限给得太宽。一个Web应用漏洞打进去,发现当前账户是本地管理员,甚至直接就是SYSTEM,后面的事情就变得异常简单。所以权限最小化的核心思路很直接:默认全部拒绝,只开放完成业务所必需的那一部分。
先从一个最容易被忽略的地方说起——服务账户。Windows服务器上跑着大量系统服务和第三方应用服务,很多服务默认以Local System账户运行。Local System是Windows里权限最高的账户之一,比Administrator还要高,它能直接访问绝大部分系统资源。如果你的IIS应用池、数据库服务、中间件服务全都跑在Local System下,任何一个服务被攻破,攻击者就直接拿到了系统最高权限。正确做法是:为每一个服务创建独立的低权限域账户或本地账户,只授予该服务运行所需的最小权限。比如SQL Server服务账户只需要对数据库数据目录有读写权限,对注册表特定键有访问权限,不需要成为管理员组成员。配置时可以用sc.exe命令或者服务管理单元里的“登录”选项卡来指定服务账户,同时通过NTFS权限和注册表权限把访问范围锁死。
文件系统权限是第二个重点。Windows默认的NTFS权限继承机制经常导致权限扩散。比如你在D盘根目录给某个业务账户开了修改权限,默认情况下这个权限会一路继承到所有子目录和文件。如果这个目录下后来放了备份文件、配置文件、日志文件,那个业务账户就全都能碰了。最小化的做法是:在根目录只给“读取和执行”或“列出文件夹内容”,然后在真正需要写入的具体子目录上单独授予修改权限,并断开不需要的继承。用icacls命令可以很精细地完成这件事。举个例子,假设你的Web应用只需要写入D:\WebApp\uploads目录,那么D:\WebApp对IIS工作进程账户只给读取权限,D:\WebApp\uploads再单独给修改权限。命令大致如下:
icacls "D:\WebApp" /inheritance:r /grant:r "IIS AppPool\MyApp":(OI)(CI)RX icacls "D:\WebApp\uploads" /grant "IIS AppPool\MyApp":(OI)(CI)M
这里/inheritance:r会移除原有继承,避免父目录的宽松权限传导下来。OI和CI分别表示对象继承和容器继承,RX是读取执行,M是修改。这样即使Web应用被拿下,攻击者能写的范围也被限制在了uploads目录,无法篡改Web.config或应用代码。
本地用户和组管理同样需要收紧。很多服务器装完系统后,Administrators组里除了默认的Administrator,还会被加入各种安装人员、运维人员、第三方服务账户。时间一长,这个组里可能有十几个账户,每一个都有完全控制权。最小化配置要求:Administrators组只保留极少数核心管理账户,其他人员一律使用普通账户,需要管理操作时通过Run As或者临时提权。另外要检查Power Users、Backup Operators、Remote Desktop Users这些内置组的成员。Power Users在旧版Windows里权限接近管理员,虽然在新版系统里被削弱了,但依然有较高权限。Backup Operators可以绕过文件权限读取所有文件,这个组的成员必须严格审查。Remote Desktop Users决定了谁能远程登录,如果不需要远程桌面,直接把这个组清空,或者通过组策略限制只允许特定用户登录。
注册表权限是很多人完全没碰过的地方,但恰恰是权限最小化里非常关键的一环。Windows的很多安全配置、服务参数、自启动项都在注册表里。默认情况下,普通用户对HKLM(HKEY_LOCAL_MACHINE)下的大部分键只有读取权限,但某些软件安装时会把键值权限放宽,比如给Everyone完全控制。攻击者如果能修改某些服务对应的注册表键,就可以改变服务启动路径,实现提权或持久化。你需要用regedit或者PowerShell定期检查关键注册表路径的ACL,特别是HKLM\SYSTEM\CurrentControlSet\Services下面每个服务对应的键。正常服务账户只需要读取权限,不需要写入。如果发现某个服务键Everyone有写权限,立刻收紧。PowerShell里可以用Get-Acl命令查看:
Get-Acl "HKLM:\SYSTEM\CurrentControlSet\Services\MyService" | Format-List
然后用Set-Acl或者regini工具修改权限。这个操作要谨慎,先备份注册表再动手,避免把系统服务搞挂。
用户权限分配(User Rights Assignment)是另一个层面的控制。它和NTFS权限不同,控制的是账户能执行哪些系统级操作,比如“作为服务登录”、“本地登录”、“从网络访问此计算机”、“关闭系统”、“调试程序”等。这些设置在本地安全策略的“安全设置”->“本地策略”->“用户权限分配”里。默认情况下,“作为服务登录”这个权限可能授予了多个账户甚至组,最小化配置应该只保留那些真正需要运行服务的账户。“从网络访问此计算机”默认包含Everyone,这意味着任何账户都能通过网络尝试连接,建议改成只包含需要远程访问的账户或组。“允许通过远程桌面服务登录”只给需要远程管理的账户。“调试程序”这个权限非常危险,默认只给Administrators,但如果有人手动加过其他账户,要立即移除。还有“备份文件和目录”和“还原文件和目录”,这两个权限可以绕过文件系统ACL,必须严格控制。
组策略和本地安全策略里的安全选项也要同步调整。比如“账户:管理员账户状态”可以禁用内置Administrator账户,改用重命名的自定义管理账户。“账户:来宾账户状态”必须禁用。“网络访问:本地账户的共享和安全模型”建议设为“经典 - 对本地用户进行身份验证,不改变其本来身份”,避免匿名连接。“网络访问:不允许匿名枚举SAM账户和共享”要启用。“交互式登录:不显示上次登录的用户名”启用,减少信息泄露。这些安全选项虽然看起来琐碎,但组合起来能显著降低攻击面。
还有一个经常被忽视的环节:计划任务。Windows计划任务可以以指定账户身份运行,而且很多计划任务默认以最高权限运行。攻击者特别喜欢利用计划任务做持久化,因为计划任务可以设置成系统启动时运行,且运行账户可能是SYSTEM。最小化配置要求:定期审查计划任务列表,删除不必要的任务,确认每个任务的运行账户是最小权限账户,而不是SYSTEM或Administrator。用schtasks命令可以导出所有计划任务:
schtasks /query /fo LIST /v
重点看“要运行的任务”和“运行方式用户”这两项。如果某个任务运行的是PowerShell脚本或者可执行文件,检查该文件所在目录的权限,确保普通用户不能替换这个文件。因为如果计划任务以SYSTEM运行,而脚本目录普通用户可写,攻击者就能替换脚本内容,等任务下次运行时以SYSTEM执行恶意代码。
网络层面也要配合权限最小化。Windows防火墙出站和入站规则默认可能比较宽松,尤其是服务器上装了各种业务软件后,厂商往往会要求关闭防火墙或者开放大量端口。最小化配置要求:入站只开放业务必须的端口,比如80、443、数据库专用端口,而且最好绑定到特定IP或网段。出站规则同样要限制,很多恶意软件需要外联,如果出站全放行,攻击者很容易把数据传出去。用netsh advfirewall或者PowerShell的New-NetFirewallRule命令可以精细配置。另外要检查“远程桌面”是否只允许特定IP访问,可以在防火墙规则里设置远程地址范围,而不是对全网开放3389。
审计和监控是权限最小化的验证手段。配置完权限之后,必须开启必要的审计策略,否则出了问题都不知道哪里被突破了。在本地安全策略的“高级审核策略配置”里,建议至少开启:登录/注销审计、账户管理审计、对象访问审计(针对敏感目录)、策略更改审计、特权使用审计。审计日志要定期检查,尤其是安全日志里的事件ID 4624(登录成功)、4625(登录失败)、4672(特殊权限登录)、4720(创建账户)、4732(成员添加到安全组)等。如果发现异常登录或者权限变更,立即排查。可以用wevtutil命令导出安全日志:
wevtutil epl Security C:\logs\security.evtx
然后配合事件查看器或者PowerShell筛选分析。审计日志本身也要保护,限制只有管理员能读取和清除日志,防止攻击者入侵后抹掉痕迹。
最后要强调一点:权限最小化不是一次性工作,而是一个持续的过程。业务系统会不断更新,新装的软件、新加的用户、新改的配置都可能重新放大权限。建议把权限最小化纳入日常运维流程,每次变更后都要检查权限是否仍然符合最小化原则。可以用脚本定期导出关键权限配置,和基线做对比,发现偏差及时修正。比如每周用PowerShell导出本地管理员组成员、服务账户列表、计划任务列表、关键目录ACL,和上一周的版本做差异对比。这样即使有人误操作或者被攻击者添加了后门账户,也能快速发现。
权限最小化的本质是假设系统一定会被攻破,然后让攻破后的损失降到最低。Windows服务器上每一个多余的权限,都是给攻击者递过去的一把钥匙。把钥匙收回来,锁上门,再装个监控,这才是真正有效的安全配置。
