
GitLab CE 19.4.1 Gitaly fetch SSRF के लिए प्रूफ-ऑफ-कॉन्सेप्ट और लैब: GitHub/Bitbucket इम्पोर्टर resolved_address पिनिंग को छोड़ देते हैं, जिससे एक प्रमाणित उपयोगकर्ता DNS रीबाइंड करके आंतरिक होस्ट्स को फ़ेच कर सकता है।
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitlab-gitaly-fetch-ssrf
GitLab CE 19.4.1 - GitLab Inc.
GitHub Enterprise / Bitbucket Server आयात (और Direct Transfer, जब वह फ़्लैग चालू हो) Projects::ImportService#get_resolved_address को छोड़ देते हैं। Repository#fetch_as_mirror डिफ़ॉल्ट रूप से resolved_address: "" सेट करता है। Gitaly FetchRemote / CreateRepositoryFromURL क्लोन होस्टनाम को फिर से रिज़ॉल्व करता है। UrlBlocker ने पहले ही एक सार्वजनिक A-रिकॉर्ड की अनुमति दे दी थी। रीबाइंड करें, और git-HTTP ऑब्जेक्ट्स आयातित प्रोजेक्ट में पहुँच जाते हैं।
एक साइन-इन किया हुआ उपयोगकर्ता जो GitHub Enterprise आयात चला सकता है, Gitaly को ऐसे होस्ट से git-fetch करा सकता है जो अब वह IP नहीं है जिसे UrlBlocker ने पिन किया था।
| ID | अभी तक कोई CVE नहीं |
| CWE | CWE-918, CWE-367 |
| CVSS | High: 7.7 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N |
| Product | GitLab CE |
| Affected | 19.4.1-ce.0 (26212baacadb on the v19.4.1-ee tree) |
| Auth | प्रमाणित उपयोगकर्ता, GitHub Enterprise / Bitbucket Server आयातक |
| License | GNU Affero GPL v3.0 |
| Lab | केवल 127.0.0.1 |
GitHub Enterprise आयात को उस होस्टनाम की ओर इंगित करें जिसे वे नियंत्रित करते हैं। Rails UrlBlocker.validate! एक सार्वजनिक A-रिकॉर्ड की अनुमति देता है। ParallelImporter.imports_repository? true है, इसलिए ImportService कभी पिन नहीं करता। RepositoryImporter#fetch_as_mirror खाली resolved_address के साथ Gitaly को कॉल करता है। Gitaly git HTTP-फ़ेच करता है जो भी वह नाम अब है। आयातित रेपो में ऑब्जेक्ट्स मौजूद होते हैं।
ऑल-इन-वन omnibus पर वह वर्कर लूपबैक है। सीधे http://127.0.0.1 क्लोन होस्टनाम fail closed होते हैं। Repository-by-URL आयात पहले से ही पिन करता है। Direct Transfer के लिए bulk_import_enabled चाहिए (self-managed डिफ़ॉल्ट false)।
वही उत्पाद, सहोदर अवशेष: Gitea HTTPS import pin drop, webhook 0.0.0.0/8।
मैंने 19.4.1 पैच नोट्स पढ़े, फिर आयातक। Projects::ImportService#get_resolved_address होस्टनाम को मान्य IP में फिर से लिखता है और इसे Gitaly में पास करता है। GitHub और Bitbucket Server समानांतर आयातक imports_repository? सेट करते हैं और उस पथ को छोड़ देते हैं।
project.repository.fetch_as_mirror(project.unsafe_import_url, refmap: refmap, forced: true)
fetch_as_mirror डिफ़ॉल्ट रूप से resolved_address: "" सेट करता है। Direct Transfer का repository_pipeline.rb तो validate! को कॉल करता है और रिटर्न वैल्यू को त्याग देता है।
मैंने स्टॉक gitlab/gitlab-ce:19.4.1-ce.0 खड़ा किया। CE import_sources खाली शुरू होता है; लैब GitHub को सक्षम करती है। POST /api/v4/import/github github_hostname=http://ghe.lab:18080 के साथ। GitLab netns में कैचर नकली GHE JSON के साथ-साथ git http-backend बोलता है। सीड रेपो ब्लॉब WITNESS GITLAB-GITALY-FETCH-SSRF-WITNESS है।
GET /api/v4/projects/1/repository/files/WITNESS/raw?ref=master ने witness लौटाया। Gitaly लॉग: FetchRemote grpc.code=OK root/ghe-ssrf पर। कैचर: git/2.55 info/refs और git-upload-pack। नकारात्मक github_hostname=http://127.0.0.1:18080 400 Invalid URL है।
पहले से दर्ज गलत मोड़: सीड CveLabRoot9! एक WeakPasswords अस्वीकृति है (root सबस्ट्रिंग); 19.4 उस जाँच को 64 वर्णों पर पैड करता है; Faraday उस सार्वजनिक IP से कनेक्ट नहीं कर सकता जो कैचर नहीं है, इसलिए हार्नेस 1.1.1.1:18080 को REDIRECT करता है जबकि UrlBlocker अभी भी एक सार्वजनिक A देखता है; git-HTTP GET /repos/org/repo के DNS फ्लिप होने से पहले जीत सकता है; GitLab आयात के बीच में 502 देता है और फिर भी फ़ाइल वहाँ होती है। एक रिवर्स शेल। नाटक। ओरेकल आयातित ब्लॉब प्लस Gitaly FetchRemote है।
cd lab
./run.sh
लक्ष्य केवल http://127.0.0.1:18410। GitLab CE को कई GB RAM चाहिए। केवल अधिकृत लैब।
negative-loopback status=400 Invalid URL
witness-import status=201 import_status=scheduled
file-final http=200 body='GITLAB-GITALY-FETCH-SSRF-WITNESS'
SUCCESS GITLAB-GITALY-FETCH-SSRF imported-witness git-fetch-no-pin GITLAB-GITALY-FETCH-SSRF-WITNESS
def import_repository
project.ensure_repository
refmap = Gitlab::GithubImport.refmap
project.repository.fetch_as_mirror(project.unsafe_import_url, refmap: refmap, forced: true)
get_resolved_address को fetch_as_mirror में उसी तरह पास करें जैसे repository-by-URL आयात पहले से करता है। Direct Transfer में UrlBlocker.validate! को भी त्यागें नहीं।
repository_importer.rb · repository.rb · import_service.rbGNU Affero GPL v3.0। देखें LICENSE। केवल लूपबैक लैब। कोई वारंटी नहीं।