请求路径¶
通过清理与过滤防范基于路径的攻击
Traefik 在处理传入的请求路径时实施多层安全防护。 其中包括清理路径以规范化潜在危险序列,以及过滤编码字符以防止利用 URL 编码实施攻击。 了解 Traefik 如何处理请求路径,对于维护安全的路由基础设施至关重要。
Traefik 如何处理请求路径¶
收到 HTTP 请求后,Traefik 会通过以下几个面向安全的阶段处理请求路径:
1. 编码字符过滤¶
Traefik 检查路径中是否存在潜在危险的编码字符;除非显式允许,否则会拒绝包含这些字符的请求。
以下编码字符默认允许使用:
| 编码字符 | 对应字符 |
|---|---|
%2f 或 %2F |
/(斜杠) |
%5c 或 %5C |
\(反斜杠) |
%00 |
NULL(空字符) |
%3b 或 %3B |
;(分号) |
%25 |
%(百分号) |
%3f 或 %3F |
?(问号) |
%23 |
#(井号) |
2. 路径规范化¶
Traefik 会解码以百分号编码的非保留字符,以规范化请求路径, 因为这些字符与其未编码形式等价(参见 rfc3986#section-2.3); 同时将百分号编码中的字母转换为大写(参见 rfc3986#section-6.2.2.1)。
3. 路径清理¶
Traefik 通过从 URL 中移除 ..、. 和重复斜杠片段来清理请求路径,
防止常见攻击手段(参见 rfc3986#section-6.2.2.3)。
路径安全配置¶
Traefik 提供了两种主要的路径安全机制,它们相互配合以保护应用。
路径清理¶
路径清理默认启用,通过规范化请求路径帮助防止目录遍历攻击。 可以在入口点的 HTTP 配置部分设置它:
entryPoints:
websecure:
address: ":443"
http:
sanitizePath: true # Default: true (recommended)[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http]
sanitizePath = true--entryPoints.websecure.address=:443
--entryPoints.websecure.http.sanitizePath=true清理行为:
./foo/bar→/foo/bar(移除相对当前目录片段)/foo/../bar→/bar(解析父目录遍历)/foo/bar//→/foo/bar/(移除重复斜杠)/./foo/../bar//→/bar/(组合上述全部规范化操作)
编码字符过滤¶
编码字符过滤通过拒绝潜在危险的 URL 编码字符,提供额外一层防护。 可以在入口点的 HTTP 配置部分设置它。
过滤发生在路径清理之前,可拦截使用编码绕过其他安全控制的攻击尝试。
所有编码字符过滤默认关闭(true 表示允许该编码字符)。
安全注意事项
当后端未完全遵循 RFC 3986,尤其是会解码请求路径中已编码的保留字符时,
建议将这些选项设为 false,以避免代理与后端对路径的理解不一致,并帮助防止路径遍历或其他绕过安全控制的恶意尝试。
entryPoints:
websecure:
address: ":443"
http:
encodedCharacters:
allowEncodedSlash: false # %2F - Default: true
allowEncodedBackSlash: false # %5C - Default: true
allowEncodedNullCharacter: false # %00 - Default: true
allowEncodedSemicolon: false # %3B - Default: true
allowEncodedPercent: false # %25 - Default: true
allowEncodedQuestionMark: false # %3F - Default: true
allowEncodedHash: false # %23 - Default: true[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http.encodedCharacters]
allowEncodedSlash = false
allowEncodedBackSlash = false
allowEncodedNullCharacter = false
allowEncodedSemicolon = false
allowEncodedPercent = false
allowEncodedQuestionMark = false
allowEncodedHash = false--entryPoints.websecure.address=:443
--entryPoints.websecure.http.encodedCharacters.allowEncodedSlash=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedBackSlash=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedNullCharacter=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedSemicolon=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedPercent=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedQuestionMark=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedHash=false按路由过滤编码字符
如果需要为不同路由分别配置编码字符过滤,可以使用 EncodedCharacters 中间件。
具体实现方法与配置选项请参阅 EncodedCharacter 中间件文档。