特殊 HTTP 头

Reading time: 15 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

字典 & 工具

用于修改来源/位置的 Headers

重写 IP 源

  • X-Originating-IP: 127.0.0.1
  • X-Forwarded-For: 127.0.0.1
  • X-Forwarded: 127.0.0.1
  • Forwarded-For: 127.0.0.1
  • X-Forwarded-Host: 127.0.0.1
  • X-Remote-IP: 127.0.0.1
  • X-Remote-Addr: 127.0.0.1
  • X-ProxyUser-Ip: 127.0.0.1
  • X-Original-URL: 127.0.0.1
  • Client-IP: 127.0.0.1
  • X-Client-IP: 127.0.0.1
  • X-Host: 127.0.0.1
  • True-Client-IP: 127.0.0.1
  • Cluster-Client-IP: 127.0.0.1
  • Via: 1.0 fred, 1.1 127.0.0.1
  • Connection: close, X-Forwarded-For (检查 hop-by-hop headers)

重写 位置

  • X-Original-URL: /admin/console
  • X-Rewrite-URL: /admin/console

Hop-by-Hop headers

Hop-by-hop header 是设计用来由当前处理请求的代理解析和消费的 header,与端到端 header 不同。

  • Connection: close, X-Forwarded-For

hop-by-hop headers

HTTP Request Smuggling

  • Content-Length: 30
  • Transfer-Encoding: chunked

HTTP Request Smuggling / HTTP Desync Attack

The Expect header

客户端可能会发送头 Expect: 100-continue,然后服务器可以返回 HTTP/1.1 100 Continue 以允许客户端继续发送请求体。然而,有些代理不太喜欢这个 header。

Expect: 100-continue 的有趣结果包括:

  • 向服务器发送带有 body 的 HEAD 请求,服务器没有考虑到 HEAD 请求不应有 body,导致连接保持打开直到超时。
  • 有些服务器在响应中返回奇怪的数据:从 socket 读取到的随机数据、密钥,甚至可以阻止前端移除某些 header 值。
  • 这还可能引发 0.CL desync,因为后端返回了 400 响应而不是 100 响应,但代理前端已经准备好发送初始请求的 body,于是发送了它,后端将其当作新请求处理。
  • 发送 Expect: y 100-continue 变体也引发过 0.CL desync。
  • 类似的错误中,后端返回 404 导致 CL.0 desync:恶意请求指示了一个 Content-Length,因此后端会把恶意请求和下一个请求(受害者)的 Content-Length 字节一起发送,这使得队列不同步 —— 后端为恶意请求发送了 404 响应加上受害者请求的响应,但前端认为只发送了 1 个请求,因此第二个响应被发给了第二个受害者请求,依此类推......

有关 HTTP Request Smuggling 的更多信息请参见:

HTTP Request Smuggling / HTTP Desync Attack

缓存相关 Headers

Server Cache Headers:

  • X-Cache 在响应中可能为 miss(未命中缓存)或 hit(已命中缓存)
  • 类似行为也会出现在 Cf-Cache-Status
  • Cache-Control 指示资源是否被缓存以及下一次缓存的时长:Cache-Control: public, max-age=1800
  • Vary 通常用于响应中,指示附加的 header 被作为 缓存键的一部分(即使这些 header 通常不被用作键)
  • Age 定义对象在代理缓存中存在的秒数
  • Server-Timing: cdn-cache; desc=HIT 也表明资源被缓存

Cache Poisoning and Cache Deception

Local Cache headers:

  • Clear-Site-Data: 指示应清除哪些缓存:Clear-Site-Data: "cache", "cookies"
  • Expires: 包含响应何时过期的日期/时间:Expires: Wed, 21 Oct 2015 07:28:00 GMT
  • Pragma: no-cache 等同于 Cache-Control: no-cache
  • Warning: 通用 HTTP header,包含有关消息状态可能问题的信息。响应中可能出现多个 Warning header。例:Warning: 110 anderson/1.3.37 "Response is stale"

条件请求

  • 使用这些 header 的请求:If-Modified-SinceIf-Unmodified-Since 仅在响应头 Last-Modified 包含不同时间时才返回数据。
  • 使用 If-MatchIf-None-Match 的条件请求使用 Etag 值,只有当数据(Etag)已更改时,web 服务器才会发送响应内容。Etag 来自 HTTP 响应。
  • Etag 值通常基于响应的内容计算。例如,ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI" 表示该 Etag 是 37 字节SHA1

Range 请求

  • Accept-Ranges:指示服务器是否支持 range 请求,以及可以用哪种单位表达范围。Accept-Ranges: <range-unit>
  • Range:指示服务器应返回文档的哪一部分。例如,Range:80-100 将返回原始响应的第 80 到 100 字节,并返回状态码 206 Partial Content。也请记得从请求中移除 Accept-Encoding header。
  • 这在获取包含任意反射 JavaScript 代码(否则会被转义)的响应时可能有用。但要滥用它,需要在请求中注入这些 header。
  • If-Range:创建一个有条件的 range 请求,只有在给定的 etag 或日期匹配远端资源时才会被满足。用于防止从资源的不兼容版本下载两个范围。
  • Content-Range:指示部分消息在完整消息中的位置。

消息体信息

  • Content-Length: 资源的大小,以十进制字节数表示。
  • Content-Type: 指示资源的媒体类型
  • Content-Encoding: 用于指定压缩算法。
  • Content-Language: 描述面向受众的人类语言,以便用户根据自己的偏好区分语言。
  • Content-Location: 指示返回数据的备用位置。

从 pentest 的角度看这些信息通常“没用”,但如果资源被 401 或 403 保护且你能找到某种方式去获取这些信息,这可能很有趣。
例如,RangeEtag 在 HEAD 请求中的组合可以通过 HEAD 请求 leak 页面内容:

  • 带有头 Range: bytes=20-20 的请求且响应包含 ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y",泄露出字节 20 的 SHA1 是 ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y

服务器信息

  • Server: Apache/2.4.1 (Unix)
  • X-Powered-By: PHP/5.3.3

控制相关

  • Allow: 该 header 用于指示资源可处理的 HTTP 方法。例如,Allow: GET, POST, HEAD 表示该资源支持这些方法。
  • Expect: 客户端用来传达服务器在处理请求时需要满足的期望。一个常见用例是 Expect: 100-continue,表示客户端打算发送大量数据负载。客户端会等待 100 (Continue) 响应再继续发送,从而优化网络使用。

下载

  • HTTP 响应中的 Content-Disposition header 指示文件是应内联显示(inline,页面内)还是作为附件(attachment,下载)处理。例如:
Content-Disposition: attachment; filename="filename.jpg"

这意味着名为 "filename.jpg" 的文件应被下载并保存。

安全标头

内容安全策略 (CSP)

Content Security Policy (CSP) Bypass

Trusted Types

通过在 CSP 中强制使用 Trusted Types,应用可以免受 DOM XSS 攻击。Trusted Types 确保只有符合既定安全策略、专门构造的对象才能用于危险的 web API 调用,从而默认保护 JavaScript 代码。

javascript
// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
// Name and create a policy
const policy = trustedTypes.createPolicy('escapePolicy', {
createHTML: str => str.replace(/\</g, '&lt;').replace(/>/g, '&gt;');
});
}
javascript
// Assignment of raw strings is blocked, ensuring safety.
el.innerHTML = "some string" // Throws an exception.
const escaped = policy.createHTML("<img src=x onerror=alert(1)>")
el.innerHTML = escaped // Results in safe assignment.

X-Content-Type-Options

此响应头可防止 MIME 类型嗅探,这种做法可能导致 XSS 漏洞。它确保浏览器遵守服务器指定的 MIME 类型。

X-Content-Type-Options: nosniff

X-Frame-Options

为防止 clickjacking,该 header 限制文档在 <frame><iframe><embed><object> 标签中的嵌入方式,建议所有文档显式指定其嵌入权限。

X-Frame-Options: DENY

跨源资源策略 (CORP) 和 跨源资源共享 (CORS)

CORP 对于指定网站可以加载哪些资源至关重要,有助于缓解跨站 leaks。另一方面,CORS 允许更灵活的跨源资源共享机制,在某些条件下放宽同源策略。

Cross-Origin-Resource-Policy: same-origin
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

跨源嵌入策略 (COEP) 和 跨源打开策略 (COOP)

COEP 和 COOP 对于启用跨源隔离至关重要,可显著降低类似 Spectre 的攻击风险。它们分别控制跨源资源的加载和与跨源窗口的交互。

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin-allow-popups

HTTP Strict Transport Security (HSTS)

最后,HSTS 是一项安全功能,强制浏览器仅通过安全的 HTTPS 连接与服务器通信,从而增强隐私和安全性。

Strict-Transport-Security: max-age=3153600

Header Name Casing Bypass

HTTP/1.1 将 header 字段名定义为 不区分大小写(RFC 9110 §5.1)。然而,经常能发现自定义中间件、安全过滤器或业务逻辑在比较接收到的字面 header 名称时没有先规范化大小写(例如 header.equals("CamelExecCommandExecutable"))。如果这些检查是区分大小写地执行,攻击者可以只需使用不同的大小写发送相同的 header 来绕过它们。

Typical situations where this mistake appears:

  • Custom allow/deny lists that try to block “dangerous” internal headers before the request reaches a sensitive component.
  • In-house implementations of reverse-proxy pseudo-headers (e.g. X-Forwarded-For sanitisation).
  • Frameworks that expose management / debug endpoints and rely on header names for authentication or command selection.

利用该绕过

  1. 识别在服务器端被过滤或校验的 header(例如通过阅读源代码、文档或错误信息)。
  2. 发送 相同但大小写不同的 header(混合大小写或全大写)。因为 HTTP 堆栈通常只在用户代码运行之后才规范化 header,故可跳过易受影响的检查。
  3. 如果下游组件以不区分大小写的方式处理 header(大多数如此),它将接受攻击者控制的值。

示例:Apache Camel exec RCE (CVE-2025-27636)

在易受影响的 Apache Camel 版本中,Command Center 路由尝试通过移除 CamelExecCommandExecutableCamelExecCommandArgs 这两个 header 来阻止不受信任的请求。比较操作使用了 equals(),因此只有完全相同(大小写一致)的名称会被移除。

bash
# Bypass the filter by using mixed-case header names and execute `ls /` on the host
curl "http://<IP>/command-center" \
-H "CAmelExecCommandExecutable: ls" \
-H "CAmelExecCommandArgs: /"

这些 header 未被过滤直接到达 exec 组件,导致以 Camel 进程的权限执行远程命令。

检测与缓解

  • 将所有 header 名称规范化为单一大小写(通常为小写),并在执行 allow/deny 比较之前完成该规范化。
  • 拒绝可疑的重复:如果同时存在 Header:HeAdEr:,将其视为异常。
  • 使用正向 allow-list,并在规范化 之后 强制执行。
  • 通过身份验证和网络分段保护管理端点。

References

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks