如何解决PHP+Apache防范Host Header Injection时无尾斜杠路径失效问题
问题根因
你遇到的现象本质是Web服务器默认的目录重定向逻辑优先级高于PHP代码执行:当访问不带尾部斜杠的目录路径时,Apache/Nginx会直接返回301/302重定向到带斜杠的路径,这个过程不会触发你的PHP代码,导致恶意Host头被带入重定向地址,防护失效。
优先选择服务器配置方案(更可靠,性能更高)
服务器层面的配置可以覆盖所有请求场景,包括还没走到PHP执行的重定向请求,是首选方案:
- Nginx配置:
- 严格配置
server_name为你允许的Host列表,禁止使用_、*这类模糊匹配规则 - 新增默认server块,所有未匹配到合法
server_name的请求直接返回403,避免恶意Host命中你的站点配置 - 目录补斜杠逻辑固定使用配置的
server_name生成跳转地址,示例配置:if (-d $request_filename) { rewrite ^([^/]*)$ $scheme://$server_name$1/ permanent; }
- 严格配置
- Apache配置:
- 开启
UseCanonicalName On,同时设置ServerName为你允许的主域名,添加ServerAlias配置其余允许的Host - 配置默认虚拟主机,未匹配到合法Host的请求直接拒绝访问
开启上述配置后,服务器重定向时会使用你预设的固定域名,不会读取用户提交的Host头,从根源避免重定向阶段的Host注入风险。
- 开启
代码调整作为补充防护
服务器配置是第一层防护,你可以调整PHP代码做二次校验,补全覆盖场景:
- 现有
in_array校验添加第三个参数true开启严格匹配,避免弱类型匹配绕过:$allowed_hosts = [ "127.0.0.1", "localhost", "10.x.x.28" ]; if (isset($_SERVER['HTTP_HOST']) && !in_array($_SERVER['HTTP_HOST'], $allowed_hosts, true)) { http_response_code(403); die(); } if (isset($_SERVER['SERVER_NAME']) && !in_array($_SERVER['SERVER_NAME'], $allowed_hosts, true)) { http_response_code(403); die(); } - 可在PHP层面提前处理目录补斜杠逻辑,在Host校验通过后再返回重定向,替代服务器默认的重定向逻辑,确保所有跳转都经过Host校验。
内容的提问来源于stack exchange,提问作者Satnam Singh
相关产品推荐
相关产品推荐

