我见过太多开发者把IIS配置得固若金汤,攻击防火墙规则堆了三层,漏洞SSL证书换得比衣服还勤,攻击却对一个藏在HTTP头里的漏洞小漏洞浑然不觉。这个漏洞叫“Host头攻击”,攻击它不炸你的漏洞服务器,不偷你的攻击数据库,它骗的漏洞是你和用户之间的信任。
攻击原理简单得让人发笑。攻击HTTP请求里有个Host字段,漏洞浏览器访问网站时自动带上,攻击告诉服务器“我要找的漏洞是哪个域名”。IIS拿到这个字段后,攻击在生成重定向链接、漏洞密码重置邮件、攻击甚至是某些应用的回调地址时,会直接引用它。攻击者只需要手动构造一个请求,把Host字段改成自己的恶意域名,服务器就乖乖地把用户往那儿引。
举个真实场景。某企业的OA系统部署在IIS上,员工忘记密码时,系统会往邮箱发一封带重置链接的邮件。攻击者先自己触发一次密码重置流程,但把Host头改成evil.com。服务器生成的链接就变成了http://evil.com/reset?token=xxxx。如果攻击者能截获这封邮件——比如通过DNS欺骗或者公共WiFi——他就能拿到那个token,直接重置受害者的密码。整个过程,IIS和OA系统完全不知情,它们只是忠实执行了协议。
更隐蔽的是缓存投毒。IIS如果配了CDN或者反向代理,Host头还可能影响缓存键的生成。攻击者用恶意Host头请求一个静态资源,CDN缓存了这份带恶意域名的响应,下一个普通用户访问同一资源时,拿到的是被污染的内容。这种攻击不需要接触用户,纯粹靠服务器之间的信任链传递恶意。
为什么IIS会犯这种“低级错误”?说到底,Host头最初设计时只是为了区分同一IP上的多个虚拟主机,没人想到它会成为信任边界。IIS的默认配置里,对Host头的校验几乎是零。你可以在IIS管理器的“绑定”里设置域名,但那是用来接收请求的,不是用来验证请求的。服务器根本不检查收到的Host头跟自己绑定的域名是否一致。
修起来其实不难。最直接的办法是在IIS的URL Rewrite模块里加一条规则:如果Host头不是白名单里的域名,直接返回403。或者用Application Request Routing (ARR) 做一层反向代理,在源头把非法Host头过滤掉。代码层面,如果你的应用是用ASP.NET写的,可以检查Request.Url.Host是否匹配配置项,不匹配就抛异常。但这些方案都有一个前提——你得先意识到这个漏洞的存在。
我见过一家银行的安全团队,他们把所有精力都放在SQL注入和XSS上,Host头攻击在他们看来“不就是个重定向嘛”。直到某天钓鱼邮件里的链接指向了他们的真实域名,但参数里带了攻击者的ID,用户点击后跳到了仿冒页面,才追查到是Host头惹的祸。那次的教训是:别以为只有代码漏洞才算漏洞,协议层的信任错位同样致命。
最后说个实在的。如果你懒得配规则,至少把IIS的“默认文档”和“错误页”里的绝对路径改成相对路径,别让服务器生成带域名的跳转。再不行,就加个中间件,强制检查Host头。这花不了半小时,但能堵住一个让人头疼的口子。