php防御主机头注入的关键是拒绝不可信host值,须硬编码白名单校验$_server['http_host'](去端口)和$_server['server_name'],任一不匹配即403终止;禁用动态拼接host构造url;清除\r\n\0等控制字符;配合nginx/apache服务器层白名单拦截。

PHP 防御主机头注入(Host Header Injection),关键不是“过滤”,而是“拒绝不可信的 Host 值”。攻击者篡改请求中的 Host 头,可导致密码重置劫持、缓存污染、开放重定向甚至 SSRF。防御必须在代码层强制校验,并配合服务器配置兜底。
白名单校验 HTTP_HOST 和 SERVER_NAME
永远不要信任 $_SERVER['HTTP_HOST'] 的原始值。应维护一个明确、硬编码的域名白名单,并严格比对:
- 检查
HTTP_HOST是否存在且属于白名单(注意:需去除端口,如example.com:8080→ 提取example.com) - 同时校验
$_SERVER['SERVER_NAME'],因某些反向代理或虚拟主机配置下两者可能不一致 - 若任一不匹配,立即返回 403 并终止执行,不进入后续业务逻辑
禁用动态拼接 Host 构造跳转地址
任何基于 Host 头生成 URL 的行为都极其危险,例如:"https://" . $_SERVER['HTTP_HOST'] . "/callback"。这类写法直接将攻击者控制的输入嵌入响应中:
- 登录后跳转、OAuth 回调地址、邮件模板中的链接等,一律禁止拼接
HTTP_HOST - 固定域名优先:用
https://app.example.com/这类硬编码地址 - 如需多域名支持,必须从白名单中精确匹配后选择对应协议+域名,而非字符串拼接
PHP 层清除控制字符与标准化处理
即使做了白名单,也要防范含换行符(\r、\n)或空字节的畸形 Host 值绕过校验:
- 在比对前,先用
str_replace(["\r", "\n", "\0"], '', $_SERVER['HTTP_HOST'])清除非法字符 - 使用
filter_var($host, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)验证是否为合法域名格式(PHP 7.1+) - 避免使用
parse_url()解析 Host,它不校验合法性,仅做结构拆分
Web 服务器层强制约束(Nginx / Apache)
PHP 层失效时,服务器配置是最后一道防线:
- Nginx:在 server 块中设置
server_name example.com www.example.com;,并添加默认 server 拦截非法 Host:server { listen 80 default_server; return 444; } - Apache:在虚拟主机中设
ServerName example.com,并用<if> Require all denied </if>(Apache 2.4+) - 所有入口点统一通过 HTTPS + HSTS,防止中间人篡改 Host 头
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











