
Gitea restore-repo file:// स्थानीय फ़ाइल समावेशन (CWE-73) के लिए प्रूफ-ऑफ-कॉन्सेप्ट जो अविश्वसनीय डंप के बाहर सिमलिंक लक्ष्यों को रिलीज़ अटैचमेंट में कॉपी करता है।
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitea-restore-file-open
राइट-अप: https://abraxaslabs.tech/research/gitea-restore-file-open
Gitea 1.27.3 - Gitea
CVE-2026-59765 ने OpenWithClient पर एक hostmatcher HTTP क्लाइंट लगाया। file:// शाखा उस क्लाइंट को अनदेखा करती है और os.Open को कॉल करती है। डंप के रिस्टोर में कोई DownloadFunc नहीं होता। इसके बाद gitea_uploader.go पुनर्लिखित file:// URL को खोलता है। os.Open एक डंप-साइड सिमलिंक का अनुसरण करता है। जॉइन डंप के अंतर्गत ही रहता है। सिमलिंक नहीं रहता।
किसी अविश्वसनीय डंप का ऑपरेटर रिस्टोर सिमलिंक लक्ष्य को एक रिलीज़ अटैचमेंट में कॉपी कर देता है। Gitea uid के रूप में, वह कोई भी फ़ाइल है जिसे सेवा खाता पढ़ सकता है।
| ID | अभी तक कोई CVE नहीं |
| CWE | CWE-73 |
| CVSS | मध्यम: 4.2 CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:N |
| उत्पाद | Gitea |
| प्रभावित | v1.27.3 (146cc3e) तक; स्थानीय ऑपरेटर gitea restore-repo |
| प्रमाणीकरण | किसी अविश्वसनीय डंप का स्थानीय ऑपरेटर रिस्टोर |
| लाइसेंस | GNU Affero GPL v3.0 |
| लैब | केवल 127.0.0.1 |
किसी एडमिन को एक अविश्वसनीय डंप (एक "बैकअप" निर्देशिका, किसी अविश्वसनीय रिमोट से रिस्टोर) सौंपें जिसमें डंप के अंतर्गत जॉइन किए गए पथ के नीचे एक सिमलिंक हो। रिस्टोर लक्ष्य फ़ाइल को रिस्टोर किए गए रेपो पर एक रिलीज़ अटैचमेंट में कॉपी कर देता है। जो भी उस रेपो को पढ़ सकता है, वह उसे डाउनलोड कर लेता है।
यदि डंप लेखक app.ini का नाम देता है, तो वह क्रेडेंशियल चोरी है (INTERNAL_TOKEN, SECRET_KEY, JWT, DB पासवर्ड)। लैब ओरेकल एक रोपित गवाह फ़ाइल थी, app.ini नहीं। यह OS LPE नहीं है। यह अनप्रमाणित नहीं है। यह डंप-रूट जॉइन एस्केप नहीं है। GitHub/GitLab/Gitea से लाइव माइग्रेट DownloadFunc सेट करता है और हमलावर के file:// को os.Open नहीं करता।
दो रिस्टोर मैप बची हुई तालिका पर पड़े थे। मैंने पहले स्पष्ट वाले पर लैब किया।
फाइंडिंग 8 डंप-रूट जॉइन एस्केप थी: release.yml में एक एब्सोल्यूट DownloadURL डालें, उम्मीद करें कि FilePathJoinAbs डंप प्रीफ़िक्स को उसी तरह गिरा देगा जैसे भोला filepath.Join(base, "/etc/passwd") करता है। 1.27.3 पर यह नहीं करता। प्रत्येक sub filepath.Clean("/"+s) है फिर filepath.Join(base, cleaned)। /tmp/dump + /tmp/GITEA-JOIN-OUTSIDE का रेप्लिका जॉइन /tmp/dump/tmp/GITEA-JOIN-OUTSIDE ही रहा। रिस्टोर ने डंप के अंतर्गत file:// को पुनर्लिखित किया और open ...: no such file or directory पर विफल रहा। यह इस टैग पर जॉइन-एस्केप नहीं है।
फाइंडिंग 9 वही है जो सफल हुई। मैंने डंप के बाहर एक गवाह फ़ाइल रोपित की, डंप के अंतर्गत जॉइन किए गए पथ पर एक सिमलिंक रखा, gitea restore-repo चलाया। रिस्टोर rc=0। रिस्टोर किए गए रिलीज़ अटैचमेंट में GITEA-FILE-OPEN-WITNESS था।
पहले से दर्ज गलत रास्ते: एक एब्सोल्यूट DownloadURL के माध्यम से डंप-रूट जॉइन एस्केप; लाइव माइग्रेट file:// LFI; X-Gitea-Internal-Auth (रिस्टोर Gitea uid के रूप में CLI है, /api/internal नहीं); रिस्टोर HTTP को रिमोट अनऑथ मानना (CVSS स्थानीय, उच्च विशेषाधिकार, उपयोगकर्ता इंटरैक्शन है); एक रिवर्स शेल। नाटक।
cd lab
./run.sh
केवल http://127.0.0.1:18137 को लक्षित करें। Compose lab/dump को केवल-पढ़ने के लिए माउंट करता है। run.sh कंटेनर के अंदर witness लगाता है, dump बनाता है, symlink रखता है, फिर gitea restore-repo चलाता है।
restore-rc=0 Restore repo labadmin/restored successfully
download status=200 snippet=GITEA-FILE-OPEN-WITNESS
SUCCESS GITEA-RESTORE-FILE-OPEN
OpenWithClient से file:// हटा दें, या डंप सिमलिंक्स का पालन करने से इनकार करें, और अविश्वसनीय डंप्स को पुनर्स्थापित न करें। पुनर्स्थापित अटैचमेंट में डंप-से-बाहर का साक्ष्य शामिल नहीं होना चाहिए।
uri.go · gitea_uploader.go · FilePathJoinAbsGNU Affero GPL v3.0. देखें LICENSE. केवल लूपबैक लैब। कोई वारंटी नहीं।