加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.haoxinwen.cn/)- 应用程序、AI行业应用、CDN、低代码、区块链!
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

IIS权限总出错?这5个Windows安全盲区90%管理员都踩过

发布时间:2026-11-03 11:11:30 所属栏目:Windows 来源:DaWei
导读:  凌晨三点十七分,机房的冷风突然变大了——不是空调调低了,是新换的那台AHU在测试模式下漏气,嘶嘶地往静电地板缝里灌。我盯着屏幕右下角弹出来的第十七个匿名告警:/api/v2/report 500,IIS AppPool\\DefaultAppPool 已

  凌晨三点十七分,机房的冷风突然变大了——不是空调调低了,是新换的那台AHU在测试模式下漏气,嘶嘶地往静电地板缝里灌。我盯着屏幕右下角弹出来的第十七个匿名告警:/api/v2/report 500,IIS AppPool\\DefaultAppPool 已回收。DBA老张的手机响了一声没接,响得特别短,像被掐住脖子。我原以为又是回收阈值设太低,结果查Event Viewer发现是NT AUTHORITY\\IUSR试图读取C:\\inetpub\\wwwroot\\config\\appsettings.prod.json——这文件权限表里根本没它,只有IIS_IUSRS和SYSTEM。可IIS_IUSRS明明加了,也继承了,也刷了ACL缓存。我说不准是不是父目录的NoInherit标记又悄悄爬回来了……但这个我敢打包票:你删掉继承再重加一次,十次有九次它会自动把“删除子容器权限”也带进来,哪怕你手抖没勾——Windows ACL UI那个“高级”按钮下面的复选框,它记你上次操作时的心情。


  先扔结论:不是IIS配置错,是你对Windows安全主体的理解还停在Win2003时代。90%的权限报错不是因为漏加某个组,而是因为你默认信任了“身份”这个概念本身。比如,IIS_IUSRS在Win10/2016之后早就不直接参与token构建了,它只是个占位符;真正起作用的是Application Pool Identity对应的SID,而那个SID每次应用池重启都可能变——尤其是你动过“Identity”字段里的ApplicationPoolIdentity选项再切回LocalSystem又切回来的时候。后端小李上周把web.config里开了又关,结果IIS把临时生成的那个虚拟SID的访问令牌缓存在内存里,硬扛了四小时才释放。没人去查LSASS的TokenCache条目数,就盯着icacls /verify 说“权限肯定没错”。错了。错得离谱。


  对面工位的工程师今天换了双拖鞋,灰色绒面,左脚后跟开了线。他刚把IIS管理器最小化,切到PowerShell窗口敲Get-ChildItem -Path "IIS:\\AppPools" -Recurse | ?{$_.Name -match "report"} | ForEach-Object {Restart-WebAppPool $_.Name},敲完按回车前看了我一眼,我没点头也没摇头,他手指悬了三秒,按下去了。结果不是重启成功,是触发了ApplicationInitialization模块里一个已知bug——初始化页面引用了另一个未部署的虚拟目录,导致整个AppPool卡在Starting状态、不报错也不响应,连w3wp进程都不起来。这种事没法用日志定位。得进Process Monitor抓CreateFile,过滤“RESULT: NAME NOT FOUND”,然后翻三页才看到它其实是在尝试读取\\\\?\\C:\\Windows\\System32\\inetsrv\\config\\applicationHost.config.tmp~ 这个不存在的临时文件。我敢打包票,全网文档没一篇提过IIS7+的config缓存会在ApplicationInitialization失败时产生.tmp~文件残留,且残留物会干扰后续所有AppPool生命周期动作。但它就是发生了。三百七十二条告警里,十八秒内出现七次,全部归因于同一个.tmp~。


文章配图,仅供参考

  老板昨天下午拍桌子,不是因为线上挂了,是因为财务部报表导出超时——从平均八百毫秒变成五秒,监控没报警,但业务员打电话打爆了前台。他甩过来的截图里红色错误栏写的是“HTTP Error 500.19 - Internal Server Error”,详细错误代码是0x80070005,最下面一行写着“Cannot read configuration file due to insufficient permissions”。我们当场开IIS管理器、检查物理路径、检查web.config、检查AppPool身份……全对。最后是DBA老张随口问了一句:“你确认用的是.NET Core Hosting Bundle?不是自己编译的dotnet-hosting-.exe?”——结果真不是。公司镜像库里那版2.2.8的Hosting Bundle安装包,签名验证通过,但注册表HKLM\\SOFTWARE\\Microsoft\\ASPNETCoreModule\\V2\\aspnetcore.dll路径指向的是C:\\Program Files\\IIS\\AspnetCoreModule\\v2\\aspnetcore.dll,而这个目录根本不存在。IIS在加载模块时拿不到DLL,就退回到用Classic Mode跑,Classic Mode下Application Pool Identity压根不参与请求上下文构建——它用的是IUSR+匿名认证管道。所以你的web.config里写的形同虚设。我原以为是权限模型失效,结果是模块加载链第一环就断了。现在想想,那台服务器上周重装过驱动,顺便更新了Intel Management Engine固件——驱动签名时间戳比ASP.NET Core Hosting Bundle的签名时间还晚两天,证书链校验莫名跳过了中间CA。这事我说不准是不是普遍现象,但至少在我们三台同型号Dell R740上复现了两次。


  空调嗡的一声,不是启动,是停机。整个B区机柜温度开始缓缓往上飘。我起身去推机房门,听见走廊尽头值班表上磁贴掉落的声音——上周三夜班换成赵工,但他调休申请被驳回了,理由是“核心服务保障期无调休配额”。我站在门口没动,手里咖啡杯沿上还有一圈褐色咖啡渍,蹭到了工牌背面,擦不干净。现在想想,我们花三个月做零信任迁移,把所有外网API都套上mTLS,却让IIS_AppPoolIdentity账户永远活在Everyone可读的注册表项里(HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters\\ConfigurationConfigFile)。没人碰它,因为它看起来不重要。可一旦你在注册表编辑器里点开这个键,再点一下“权限”,就会发现“继承自父项”前面打了个×,而父项HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters根本没有显式设过ACL——它的ACL来自SYSTEM hive初始加载逻辑,只在系统启动时注入一次。这意味着,如果你手动改过这个key的权限,下次reboot之后,Windows会默默把你删掉的权限项加回去。我见过六个人试过,五个没注意到这个×,一个注意到了,但没看懂下面那行小字:“此权限由操作系统控制,修改后将在下次启动时恢复”。


  别折腾icacls了。今晚先去干件事:打开注册表,找到HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters,右键——权限——高级——把“替换子容器和对象的所有者”那个钩去掉,再把“替换所有子对象权限项”也去掉,保存。做完立刻重启AppPool(不是服务器)。如果还报500.19,那就不是权限的事,是你没删干净bin目录下的web.config.bak。我自己漏删过两次。最后一次,是把bak文件名改成_web.config.bak才躲过IIS的自动加载机制——它只识别.web.config.这类通配。至于为什么它会加载bak,我也说不准。可能是ApplicationInitialization的预热逻辑在找不到main config时会fallback扫描backup patterns。也可能不是。反正我现在看见.web.config开头的文件就手动rm -force。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!