Windows服务器在IIS场景下被攻破,十次有八次是因为权限过大。一个普通的Web应用,却以管理员身份运行;一个只需要读取图片的目录,却开放了写入和执行权限。攻击者一旦通过SQL注入或文件上传漏洞拿到WebShell,就能直接控制系统。解决这个问题的核心方法就是严格执行权限最小化原则——只给完成任务所必需的最小权限,多一分都不给。
IIS应用程序池身份是权限控制的起点
应用程序池是IIS中隔离Web应用的进程容器,它的运行身份决定了工作进程w3wp.exe能做什么。默认情况下,IIS会使用内置的ApplicationPoolIdentity账户,这是一个动态创建的虚拟账户,权限很低。但很多运维人员为了方便,直接改成NetworkService甚至LocalSystem,这就埋下了巨大隐患。正确的做法是:每个站点使用独立的应用程序池,并且保持默认的ApplicationPoolIdentity身份。如果应用需要访问文件系统、数据库或网络资源,再针对性地授权。
文件系统权限的精细化配置
Web目录的NTFS权限配置是防御纵深的关键一层。一个典型的ASP.NET站点,IIS工作进程只需要对网站根目录及其子目录拥有读取和执行权限。只有那些需要写入的特定目录,比如上传文件夹、日志目录、模板编译缓存目录,才额外授予写入权限。但绝对不要授予修改和完全控制权限,更不要授予执行权限——除非那个目录确实需要运行可执行文件。配置时可以遵循这个清单:网站根目录给予IIS应用池身份读取和执行权限;上传目录给予读取和写入权限;bin目录只需要读取权限;App_Data目录给予读取和写入权限;其他静态资源目录只给读取权限。对于特别敏感的文件,如web.config和数据库连接字符串文件,还可以单独设置ACL,禁止IIS工作进程读取,改用受保护的配置机制。
执行权限必须严格限制
IIS中有一个容易被忽视的危险设置——处理程序映射和执行权限。在网站功能视图的“处理程序映射”中,可以控制哪些文件扩展名由什么程序处理。攻击者经常利用的一点是:上传一个.asp或.aspx文件到图片目录,然后直接访问执行。要阻止这种攻击,必须确保上传目录没有脚本执行权限。具体做法是在IIS中为上传目录单独设置处理程序映射,移除所有动态脚本的处理程序,只保留静态文件处理。或者在web.config中配置:
<configuration>
<system.webServer>
<handlers>
<remove name="ASPClassic" />
<remove name="ASP.NET-ISAPI-4.0_64bit" />
<remove name="ASP.NET-ISAPI-4.0_32bit" />
</handlers>
</system.webServer>
</configuration>这样即使攻击者成功上传了脚本文件,也无法通过Web访问执行,从根源上切断了WebShell的运行路径。
数据库访问权限的最小化
Web应用连接数据库的账户权限,是另一个重灾区。很多开发环境为了方便,直接使用sa或root账户,迁移到生产环境时也没有修改。正确的做法是:为每个应用创建独立的数据库登录账户,只授予对特定数据库的访问权限。在SQL Server中,应用账户通常只需要db_datareader和db_datawriter角色成员身份,只有需要执行存储过程时才授予执行权限。绝对不要授予db_owner或更高权限。连接字符串应该加密存储,不要在代码中硬编码。对于特别敏感的操作,比如修改数据库结构或批量删除数据,应该由单独的、权限更高的管理账户通过内部接口执行,而不是暴露给Web应用。
服务账户与计划任务的安全加固
Windows服务和应用池一样,存在身份配置问题。很多第三方组件安装后会以LocalSystem身份注册服务,这个身份拥有最高权限。应该逐一检查所有运行的服务,将不必要的服务停止或禁用,将必要的服务改为NetworkService或专门的低权限账户运行。计划任务也是同样的道理,不要使用管理员账户来执行Web相关的定时任务。可以创建专门的域账户或本地账户,只授予任务执行所需的最小权限。比如一个定时清理日志的脚本,只需要对日志目录有写入和删除权限,对系统其他地方完全不需要访问。
网络层面的权限隔离
Windows高级防火墙提供了出站和入站规则的精细控制。对于Web服务器,入站规则通常只需要开放80和443端口。出站规则往往被忽视,但同样重要。如果Web应用不需要主动访问外部网络,就应该在防火墙上阻止w3wp.exe的出站连接。如果应用需要调用内部API或访问数据库,应该只放行特定的目标IP和端口,而不是允许所有出站流量。这样即使攻击者拿到了WebShell,也无法反弹连接或下载恶意工具。可以通过以下PowerShell命令创建出站规则,限制IIS工作进程只能访问特定数据库服务器:
New-NetFirewallRule -DisplayName "IIS to DB Server" `
-Direction Outbound `
-Program "%SystemRoot%\System32\inetsrv\w3wp.exe" `
-RemoteAddress 192.168.1.100 `
-RemotePort 1433 `
-Protocol TCP `
-Action Allow用户权限分配与安全策略
通过本地安全策略(secpol.msc),可以进一步限制IIS相关账户的权限。在“用户权限分配”中,确保IIS应用池账户没有被授予“作为服务登录”之外的额外权限,特别是“替换进程级令牌”、“调整进程内存配额”这些敏感权限。在“安全选项”中,可以配置“网络访问:不允许SAM账户和共享的匿名枚举”来防止信息泄露。对于运行多个站点的服务器,还应该启用“用户账户控制:以管理员批准模式运行所有管理员”,防止权限提升攻击。
审核与监控是权限最小化的闭环
权限配置得再精细,如果没有审核机制,出了问题还是无从追溯。应该启用Windows高级审核策略,对敏感目录的访问失败事件进行记录。特别是对web.config、bin目录、App_Data目录的写入尝试,以及对系统目录的访问尝试。审核策略可以通过auditpol命令配置:
auditpol /set /subcategory:"File System" /success:enable /failure:enable
然后在需要监控的文件夹上设置SACL,记录IIS应用池账户的写入失败事件。这些日志会出现在安全事件日志中,可以通过事件查看器或集中日志系统进行分析。当看到大量来自w3wp.exe的拒绝访问事件时,要么是应用配置有问题,要么是正在遭受攻击。
自动化检查与持续合规
权限配置不是一劳永逸的事情。系统更新、应用上线、配置变更都可能引入新的权限问题。应该建立自动化检查机制,定期扫描IIS站点配置、应用程序池身份、NTFS权限、服务账户和防火墙规则。可以使用PowerShell脚本检查关键配置项,比如检查所有应用程序池的身份:
Import-Module WebAdministration Get-IISAppPool | Select-Object Name, ProcessModel
检查特定目录的ACL是否包含非预期账户,检查是否有应用程序池使用了LocalSystem身份。这些检查可以集成到CI/CD流水线或定期任务中,发现偏差立即告警。权限最小化是一个持续的过程,需要不断审视和调整,而不是一次配置就束之高阁。
