跳到正文
Træfɪk

具有别名名称的请求头

防止利用请求头名称别名进行请求头伪造

Go 只按连字符对请求头名称进行规范化,因此它会将 X-Auth-User、X_Auth_User 和 X.Auth.User 视为三个不同的请求头。

许多后端会根据请求头名称生成变量名(CGI、WSGI、PHP、NGINX 等):它们将请求头名称转换为大写, 并把所有既非字母也非数字的字符替换为下划线。 对这些后端来说,上面的三个名称都对应同一个 HTTP_X_AUTH_USER 变量。

受影响的字符不只有下划线和点号。除字母、数字及连字符外, HTTP 还允许在请求头名称中使用以下字符:

!  #  $  %  &  '  *  +  .  ^  _  `  |  ~

这类后端会把这些字符全部转换为下划线,因此每个字符都能构造别名: X_Auth_User、X.Auth.User、X!Auth!User、X~Auth~User 和 X+Auth+User 都会被读取为 X-Auth-User。 只有字母、数字和连字符保持不变,所以仅使用连字符的形式不存在歧义。

因此,客户端可以将 Traefik 所管理请求头的别名绕过相应中间件, 让这类后端读取伪造值,而不是 Traefik 确认的值。

配置

入口点的 aliasHeadersStrategy 选项可以缓解这类伪造攻击。 它决定在路由之前如何处理名称互为别名的请求头:

  • keep(默认值):原样转发具有别名名称的请求头。
  • delete:如果请求头名称包含既非字母、数字也非连字符的字符,则从请求中静默删除该请求头。
  • reject:如果请求携带的请求头名称包含既非字母、数字也非连字符的字符,则以 400 Bad Request 响应拒绝整个请求。

合法请求头也会被丢弃

delete 和 reject 策略会作用于所有请求头,而不只限于 Traefik 管理的请求头: 它们无法区分伪造尝试与名称恰好包含这类字符的合法请求头。 例如,依赖 X_Request_Id 请求头的应用在使用 delete 时将无法再收到它, 使用 reject 时相关请求则会被拒绝。

实际使用中,请求头名称通常只由字母、数字和连字符组成,IANA 注册表中的请求头 也不包含其他字符。启用此选项前,应检查后端是否有意使用了这类名称 (NGINX 默认配置已经会丢弃带下划线的请求头)。

安全注意事项

当入口点后方的后端会规范化请求头名称时,强烈建议将 aliasHeadersStrategy 设置为 delete 或 reject。 管理请求头的中间件(ForwardAuth 的 authResponseHeaders、BasicAuth 和 DigestAuth 的 headerField、 PassTLSClientCert、Headers 的 customRequestHeaders、StripPrefix、ReplacePath 等) 只管理它们设置的请求头的规范形式,需要依靠本选项防止别名名称造成的伪造。

对于未配置本选项的每个入口点,Traefik 都会在启动时记录一条警告。

entryPoints:
  websecure:
    address: ":443"
    http:
      aliasHeadersStrategy: delete  # Default: keep
[entryPoints.websecure]
  address = ":443"

  [entryPoints.websecure.http]
    aliasHeadersStrategy = "delete"
--entryPoints.websecure.address=:443
--entryPoints.websecure.http.aliasHeadersStrategy=delete

已弃用选项

underscoreHeadersStrategy 选项已弃用,请改用 aliasHeadersStrategy。 后者处理所有可产生别名的字符,而不仅仅是下划线。 更多详情请参阅功能弃用通知。


版权所有 © 头文件软件工作室

文档由 HeadFile Studio 翻译。

Traefik v3.7 中文快照 · 原文版权归 Traefik Labs 及贡献者所有 · MIT 许可证