
GitLab CE webhook SSRF के लिए प्रूफ-ऑफ-कॉन्सेप्ट और लैब, जो 0.0.0.0/8 this-network रेंज के माध्यम से एक Maintainer को loopback तक पहुँचने और hook logs से प्रतिक्रियाएँ पढ़ने की सुविधा देता है।
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitlab-webhook-0net-ssrf
GitLab CE 19.4.1 - GitLab Inc.
Gitlab::HTTP_V2::UrlBlocker सटीक 0.0.0.0, ::, और 127.0.0.0/8 को ब्लॉक करता है। यह शेष 0.0.0.0/8 को ब्लॉक नहीं करता। Linux उस रेंज को "this network" मानता है और 0.0.0.1 को लोकल स्टैक तक पहुँचा देगा। एक प्रोजेक्ट Maintainer http://0.0.0.1:<port>/ पर वेबहुक बना सकता है, जबकि allow_local_requests_from_web_hooks_and_services बंद है। GitLab प्रतिक्रिया का 8 KB हुक लॉग में संग्रहीत करता है।
अपने ही प्रोजेक्ट का एक Maintainer GitLab से 0.0.0.1 के माध्यम से loopback पर POST करवा सकता है और हुक लॉग से body वापस पढ़ सकता है।
| ID | अभी तक कोई CVE नहीं |
| CWE | CWE-918 |
| CVSS | High: 8.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N |
| Product | GitLab CE |
| Affected | 19.4.1-ce.0 (v19.4.1-ee ट्री पर 26212baacadb) |
| Auth | प्रमाणित Maintainer (admin_web_hook) |
| License | GNU Affero GPL v3.0 |
| Lab | केवल 127.0.0.1 |
POST /api/v4/projects/:id/hooks के साथ url=http://0.0.0.1:<port>/। ट्रिगर करें या टेस्ट करें। हुक इवेंट्स API से response_body पढ़ें। all-in-one omnibus पर, Sidekiq Puma, Workhorse, और exporters के साथ कंटेनर netns साझा करता है। अपने प्रोजेक्ट के Maintainer को उन्हें पढ़ना नहीं चाहिए।
http://127.0.0.1/ और http://169.254.169.254/ ब्लॉक रहते हैं। यह link-local के माध्यम से IMDS नहीं है। यह this-network का छेद है।
वही उत्पाद, सहोदर अवशेष: Gitea HTTPS import pin drop, Gitaly fetch resolved_address छोड़ता है।
19.4.1 SSRF फिक्स के बाद मैंने url_blocker.rb पढ़ा। validate_localhost सटीक "::" और "0.0.0.0" के साथ Socket.ip_address_list है। validate_loopback ipv4_loopback? (127.0.0.0/8) और ipv6 loopback है। Specs 127.0.0.1 के octal/hex aliases को कवर करते हैं। वे कभी 0.0.0.1 का उल्लेख नहीं करते।
Webhook body sink है: WebHookService POST करता है और 8 KB संग्रहीत करता है। Maintainer के पास admin_web_hook है।
मैंने स्टॉक gitlab/gitlab-ce:19.4.1-ce.0 खड़ा किया। Local-requests बंद। GitLab netns के अंदर 0.0.0.1:18080 पर catcher। हुक बनाएँ http://127.0.0.1:18080/ और http://169.254.169.254/ : 422 Invalid url given। हुक बनाएँ http://0.0.0.1:18080/ : 201। टेस्ट पुश इवेंट्स : 201। हुक इवेंट्स response_body में GITLAB-WEBHOOK-0NET-SSRF-WITNESS शामिल है।
पहले से दर्ज गलत मोड़: /users/sign_in के साथ Accept: application/json 404 है; root युक्त seed password WeakPasswords है; lo में 0.0.0.1 जोड़ने से यह Socket.ip_address_list पर आ जाता है इसलिए validate_localhost "positive" को 422 करता है; IP_FREEBIND के साथ ip route add local 0.0.0.1/32 dev lo एड्रेस लिस्ट में शामिल हुए बिना बाइंड करता है; password में compose $ को $$ चाहिए। एक reverse shell। नाटक। Oracle 0.0.0.1 पर 201 है, 127.0.0.1 पर 422, लॉग में witness।
cd lab
./run.sh
लक्ष्य केवल http://127.0.0.1:18420। GitLab CE को कई GB RAM चाहिए। केवल अधिकृत lab।
negative-a 127.0.0.1 blocked
negative-b link-local blocked
positive-hook id=1
SUCCESS GITLAB-WEBHOOK-0NET-SSRF webhook response_body from 0.0.0.1:18080 hook_id=1 GITLAB-WEBHOOK-0NET-SSRF-WITNESS
def validate_localhost(addrs_info)
local_ips = ["::", "0.0.0.0"]
local_ips.concat(Socket.ip_address_list.map(&:ip_address))
return if (local_ips & addrs_info.map(&:ip_address)).empty?
raise BlockedUrlError, "Requests to localhost are not allowed"
end
def validate_loopback(addrs_info)
return unless addrs_info.any? { |addr| addr.ipv4_loopback? || addr.ipv6_loopback? }
raise BlockedUrlError, "Requests to loopback addresses are not allowed"
end
0.0.0.0/8 (और ::ffff:0.0.0.0/104) को उसी तरह अस्वीकार करें जैसे 127.0.0.0/8 अस्वीकार किया जाता है।
url_blocker.rb · web_hook_service.rb · project_hooks.rbGNU Affero GPL v3.0। देखें LICENSE। केवल loopback lab। कोई वारंटी नहीं।