https重定向易受host注入攻击,因nginx默认不校验host头且常误用$host等客户端变量构造跳转地址;应改用$server_name、固定域名或白名单校验,并配合default_server拦截非法host请求。

HTTPS 重定向过程中,Host 头部若未严格校验,极易成为 Host 注入攻击的突破口。Nginx 本身不自动验证 Host 头合法性,它只按 server_name 匹配路由;而重定向(如 HTTP → HTTPS 跳转、或后端返回 301/302 Location)常会动态拼接 $host 或 $http_host,一旦这些变量被恶意篡改,重定向地址就会指向攻击者控制的域名。
为什么 HTTPS 重定向特别容易出问题
常见配置中,HTTP 端口做 301 跳转到 HTTPS 时,常写成:
-
return 301 https://$host$request_uri;—— 这里$host来自客户端请求头,可被任意伪造 -
proxy_redirect default;或proxy_redirect http://$proxy_host/ https://$host/;—— 若后端返回含Location: http://evil.com/...,又未清洗,Nginx 可能直接透传或错误重写 - 使用
$http_host构造跳转链接(如登录成功后跳回原域名),等同于把攻击面完全开放给客户端
安全的 HTTPS 重定向配置方式
核心原则:重定向目标中的域名必须来自可信源,不能依赖客户端输入。
- 固定跳转域名(推荐):
return 301 https://www.example.com$request_uri;
适用于单域名场景,彻底规避 Host 变量风险 - 用
$server_name替代$host:return 301 https://$server_name$request_uri;$server_name是配置中显式声明的合法域名,不可被客户端覆盖 - 若需支持多域名,用白名单校验后再跳转:
if ($host ~* ^(www\.example\.com|example\.com|app\.example\.com)$) {<br> return 301 https://$host$request_uri;<br>}
不匹配则直接return 403,不跳转
配合 proxy_pass 场景下的 Host 头处理
当 Nginx 作为 HTTPS 入口反向代理后端时,重定向还涉及后端响应头的处理:
- 禁止透传原始 Host:
proxy_set_header Host $proxy_host;(推荐)或proxy_set_header Host backend.example.com;,避免后端误用恶意 Host 生成跳转地址 - 强制重写后端返回的 Location 头:
proxy_redirect ~^http://[^/]+(.*)$ https://$server_name$1;
将后端所有 HTTP 重定向强制转为当前 HTTPS 域名 - 移除危险响应头:
proxy_hide_header Location;(慎用,需确认业务是否依赖)或配合add_header重置关键跳转逻辑
必须启用的兜底防御:default_server + 白名单拦截
仅靠重定向配置不够,必须在协议入口层堵住非法 Host 请求:
- 定义明确的
default_server,监听 443 端口:server { listen 443 ssl default_server; server_name _; return 444; } - 所有合法业务 server 块显式列出
server_name,包括主域名、www 子域、常用别名 - 禁用下划线域名解析(防绕过):
underscores_in_headers off;(默认即关闭,但建议显式声明) - 空 Host 或 IP 直连也应拒绝:
在 default_server 中统一处理,不留给任何 fallback 机会











