
Forgejo 16.0.5 - उच्च - रिमोट - SSRF - hostmatcher 0.0.0.1 को सार्वजनिक IP के रूप में अनुमति देता है
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-hostmatcher-0001-ssrf
Class: SSRF Reach: Remote
Forgejo 16.0.5 (8d24b7d) - Forgejo
डिफ़ॉल्ट [webhook] ALLOWED_HOST_LIST खाली है, इसलिए services/webhook/deliver.go क्लाइंट को बिल्ट-इन external के साथ बनाता है। वह प्रेडिकेट Go IsGlobalUnicast() && !isPrivate() है। isPrivate RFC1918/4193 के साथ-साथ v16.0.2 CGNAT ऐड है। RFC 6890 0.0.0.0/8 इनमें से कोई नहीं है। 127.0.0.1 लूपबैक है और अस्वीकृत है। 0.0.0.1 अनुमत है।
एक साइन-इन उपयोगकर्ता http://0.0.0.1 को वेबहुक कर सकता है और हुक इतिहास से HTTP बॉडी पढ़ सकता है। उसी पोर्ट पर 127.0.0.1 अस्वीकृत है।
| ID | अभी तक कोई CVE नहीं |
| Class | SSRF |
| Reach | Remote (प्रमाणित; कोई भी उपयोगकर्ता जो रेपो वेबहुक बना सकता है) |
| CWE | CWE-918 |
| CVSS | High: 7.7 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N |
| Product | Forgejo |
| Affected | v16.0.5 (8d24b7d) तक; v16.0.2 CGNAT ऐड का अवशेष |
| Auth | साइन-इन उपयोगकर्ता जो रेपो वेबहुक बना सकता है |
| License | GNU Affero GPL v3.0 |
| Lab | केवल 127.0.0.1 |
डिफ़ॉल्ट इंस्टॉल पर रजिस्टर करें, एक रेपो बनाएं, एक forgejo वेबहुक को http://0.0.0.1:<port>/... पर सेट करें, इसका परीक्षण करें, और रिस्पॉन्स बॉडी पढ़ें।
| Privilege | Method / sink | Recon / integrity / availability | Lab-proven or inferred |
|---|---|---|---|
डिफ़ॉल्ट वेबहुक allow-list को पार करते हुए इस-नेटवर्क 0.0.0.1 को डायल करें | POST /api/v1/repos/{owner}/{repo}/hooks फिर URL http://0.0.0.1:8080/ssrf के साथ POST .../hooks/{id}/tests | Recon (Forgejo होस्ट से आउटबाउंड HTTP) | Lab-proven। इतिहास में संग्रहीत HTTP 200 बॉडी FORGEJO-HOSTMATCHER-0001-WITNESS |
| जो भी उत्तर दे उसका पूरा HTTP रिस्पॉन्स पढ़ें | GET /{owner}/{repo}/settings/hooks/{id} ResponseInfo.Body प्रिंट करता है | Recon (पूर्ण-रिस्पॉन्स SSRF) | Lab-proven। इतिहास पृष्ठ में वही witness |
IPv4-mapped [::ffff:0.0.0.1] के माध्यम से समान क्लास | वही मैचर To4() फिर checkIP | Recon | hostmatcher से अनुमानित। Lab ने 0.0.0.1 का उपयोग किया |
| Forgejo netns में लूपबैक से अधिक व्यापक रूप से बाउंड किए गए लिसनर तक पहुंचें | Linux connect() से 0.0.0.0/8 इस-होस्ट है जब 0.0.0.1 lo पर हो | Recon | साइडकार oracle के विरुद्ध Lab-proven। किसी विशिष्ट क्लाउड IMDS के बारे में दावा नहीं |
समान डिफ़ॉल्ट मैचर पर बंद: 127.0.0.1 (इतिहास में lab-proven deny), 127.0.0.0/8, RFC1918, CGNAT 100.64.0.0/10, लिंक-लोकल 169.254.0.0/16 जिसमें IPv4 IMDS शामिल है, अनिर्दिष्ट 0.0.0.0। आउटबाउंड वेबहुक X-Forgejo-Internal-Auth / INTERNAL_TOKEN प्राप्त नहीं करता। यह अपने आप में RCE नहीं है। |
यह v16.0.2 CGNAT फिक्स नहीं है। Forgejo ने कभी Gitea-शैली की reserved-net सूची नहीं बनाई। gitea-hostmatcher-0000-ssrf के समान क्लास।
v16.0.2 ने CGNAT को private में डाला। deny-list जोड़ने वाले पैच एक उपहार हैं: आप सूची पढ़ते हैं, फिर पूछते हैं कि IANA के पास अभी भी क्या है जो सूची भूल गई। एक सहोदर खोज ने दावा किया कि Go 1.26 IsGlobalUnicast ने 0.0.0.1 को बंद कर दिया। मैंने प्रेडिकेट और इन-ट्री टेस्ट की जांच की। वे कभी 0.0.0.1 को कवर नहीं करते।
पहले से दर्ज गलत मोड़: वेबहुक क्रिएट HTTP 201 को oracle मानना (इतिहास oracle है); 127.0.0.1 डिलीवरी सफल होना (वह एक अलग बग होगा - lab को यह अस्वीकृत चाहिए); X-Forgejo-Internal-Auth के साथ /api/internal को हिट करना; एक रिवर्स शेल। नाटक।
python3 forgejo-hostmatcher-0001-ssrf-Abraxas-Labs.py
या:
cd lab
./run.sh
लक्ष्य केवल http://127.0.0.1:19320। इमेज codeberg.org/forgejo/forgejo:16.0.5। Oracle साइडकार पोर्ट 8080 पर Forgejo netns साझा करता है।
create-hook name=neg-loopback ...
negative-control 127.0.0.1 blocked
create-hook name=hit-0001 ...
poll id=2 witness=True
SUCCESS forgejo-hostmatcher-0001-ssrf how=live pin=v16.0.5 0.0.0.1:8080 HTTP 200 FORGEJO-HOSTMATCHER-0001-WITNESS
RFC 6890 0.0.0.0/8 को not-external मानें (एक reserved-net सूची, IsGlobalUnicast नहीं)। 0.0.0.1 को उसी तरह अस्वीकृत किया जाना चाहिए जैसे 127.0.0.1 है।
hostmatcher.goGNU Affero GPL v3.0। देखें LICENSE। केवल लूपबैक lab। कोई वारंटी नहीं।