Jellyfin Server 12.2 - عالية الخطورة - عن بُعد - IDOR - GET /Items/Suggestions omit-userId يكشف مسار المكتبة المخفية ومعرّفاتها
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · jellyfin-suggestions-idor
Jellyfin Server 12.2 - Jellyfin
الفئة: IDOR. الوصول: عن بُعد (أي مستخدم مصادَق عليه غير مسؤول).
GET /Items/Suggestions محمي بـ [Authorize] فقط. عند حذف userId، يضبط SuggestionsController.GetSuggestions القيمة user = null ولا يستدعي RequestHelpers.GetUserId أبدًا. لا يستدعي InternalItemsQuery(null) الدالة SetUser. يتخطى LibraryManager.GetItemsResult الدالة AddUserToQuery. يتضمن new DtoOptions() الحقل ItemFields.Path. يتخطى GetBaseItemDtos(..., user: null) الدالة IsVisible.
علّمت GHSA-9x85 استخدام GetUserId (الحذف يعود إلى الـ claims؛ وأي GUID خارجي يُرجع 403). يستخدمها ItemsController.GetItems دائمًا. أما Suggestions فلم تفعل. المسار القديم GET /Users/{userId}/Suggestions يحتوي دائمًا على GUID في المسار، لذا يمر ذلك المسار الشقيق عبر GetUserId.
حساب مقيّد يستخرج العناوين والمعرّفات والنظرات العامة ومعرّفات المزوّدين ومسار نظام الملفات لمكتبات غير مخصصة له. وتُستخدم تلك الـ GUIDs في GET /Videos/{id}/stream غير المصادَق عليه.
| المعرّف | لا يوجد CVE بعد |
| CWE | CWE-639 / CWE-862 |
| CVSS | مرتفع: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| المنتج | Jellyfin Server |
| المتأثر | v12.2 (ca0f16eb7c195f720a1493ed469a27c4657db0c6)، الصورة jellyfin/jellyfin:12.2 |
| المصادقة | مصادَق عليه (أي مستخدم غير مسؤول، بما في ذلك حساب طفل / مكتبة مخفية) |
| الترخيص | GNU Affero GPL v3.0 |
| المختبر | 127.0.0.1:18790 فقط |
البقايا رقم 1 من بقايا Jellyfin 12.2. نفس التثبيت، حزم أخرى: jellyfin-svg-gzip (بقايا GHSA-cf3c الخاصة بـ gzip data:image/png)، jellyfin-playlist-itemids (بقايا GHSA-9x85 الخاصة بـ ItemIds + البث غير المصادَق عليه)، jellyfin-ffmpeg-colonslash (بقايا GHSA-wwwm الخاصة بعلامات الاقتباس في عنوان URL لـ .strm). هذه الحزمة هي التي تستخرج المكتبة المخفية.
أي مستخدم مصادَق عليه غير مسؤول، بما في ذلك حساب طفل / مكتبة مخفية / MaxParentalRating. يحتاج إلى رمز مستخدم عادي. لا صلاحيات مسؤول، ولا مفتاح API. لا يغيّر كلمات المرور. لا ينشئ حساب مسؤول. يقوم بجرد المكتبات غير المخصصة له، بما في ذلك مسار نظام الملفات، ثم يشغّل تلك الـ GUIDs.
جدول الصلاحيات (شامل). نفس المعيار المتبع في Signal-Server Dropwizard admin: الطريقة + المسار، وما يمنحه ذلك الاستدعاء، والاستطلاع مقابل السلامة مقابل التوافر، والمُثبت مختبريًا مقابل المُستنتج، والسطح المجاور الذي يبقى مغلقًا.
| المحور | الطريقة + المسار | ما يمنحه | المصدر |
|---|---|---|---|
| استطلاع | GET /Items/Suggestions بدون userId (اختياري limit / mediaType / type) | قائمة عناصر تعاودية غير محدودة النطاق: الاسم، المعرّف، النظرة العامة، معرّفات المزوّد، مسار نظام الملفات، بيانات وصفية لصور المكتبات غير المخصصة للمستدعي، بما في ذلك المجلدات الممنوحة لمستخدم مخفي فقط. لا تُطبَّق ACL المجلد ولا التصنيف العمري ولا الوسوم المسموح بها. | مُثبت مختبريًا. labuser المقيّد (EnableAllFolders=false، EnabledFolders=PublicB فقط): GET /Items witness=0؛ Suggestions witness=1 |
| استطلاع | نفسه مع حذف limit | يبقى InternalItemsQuery.Limit غير مضبوط؛ فتُعيد المستودع مجموعة المطابقات كاملة (جدول العناصر بأكمله، بترتيب عشوائي) | المصدر (SuggestionsController.cs:70-95) |
| استطلاع | GET /Videos/{itemId}/stream غير مُصادَق مع GUID من تلك القائمة | بايتات ذلك الملف بصفته UID الخاص بـ jellyfin | المصدر (لا يملك VideosController صنف [Authorize]؛ StreamingHelpers GetItemById بدون مستخدم). تم اختبار البث مختبريًا في المتبقي الشقيق jellyfin-playlist-itemids، وليس في هذه الحزمة |
| السلامة | لا شيء على Suggestions | لا كتابة كلمة مرور أو سياسة أو مفضلة أو جلسة | مغلق |
| الإتاحة | لا شيء على Suggestions | لا DoS يتجاوز كلفة الاستعلام العادية | مغلق |
يبقى مغلقًا على هذا الإصدار المثبّت
| المحور | الطريقة + المسار | سبب إغلاقه |
|---|---|---|
| استطلاع | GET /Items?userId= و GET /Items?parentId=<hiddenFolder> | دائمًا GetUserId + IsVisible (ItemsController.cs:265, 342-350) |
| استطلاع | GET /Playlists/{id}/Items?userId= | GetUserId (PlaylistsController.cs:524). من صنف GHSA-9x85، مُرقَّع |
| استطلاع | GET /Items/Suggestions?userId=<other> | GUID الغريب لا يزال يمرّ عبر GetUserId ويُعيد 403 لغير المسؤول. مُثبت مختبريًا (impersonate-403=yes) |
| استطلاع | المسار القديم GET /Users/{userId}/Suggestions | GUID المسار مطلوب، لذا فهو يستدعي GetUserId |
| السلامة | POST /Users/Password?userId= | AssertCanUpdateUser |
| السلامة | POST /Users/{id}/Policy | RequiresElevation |
| السلامة | الأجهزة، الجلسات، AddAdditionalUser | رفع الصلاحيات أو الجلسة الخاصة فقط |
| استطلاع | GET /Users / GET /Users/{id} | UserDto + السياسة (GUIDs المجلدات، بت المسؤول)، وليس محتويات المكتبة أو التجزئات. تعداد أفراد المنزل، وليس هذا المتبقي |
لا أدّعي RCE عبر DLL إضافة، ولا صدفة عكسية، ولا سرقة كلمات مرور. التفريغ هو فهرس (و Path) المكتبات غير المخصصة للمستدعي. أما البث عبر GUID فهو سلوك Jellyfin HTML5/DLNA قديم قائم؛ وهذا المتبقي هو ما يعدّد المعرّفات.
أغلق الإصدار v12.2 موجة GHSA الخاصة بـ 12.0. جلست على ذلك الوسم على أي حال وقرأت كل استعلام userId بجوار RequestHelpers.GetUserId. Items يستخدمه دائمًا. Suggestions يتفرّع: userId فارغ -> user = null، ولا يستدعي GetUserId أبدًا. هذا هو المتبقي.
run.sh يهيّئ مكتبتي أفلام (PrivateA مسمّاة بالشاهد، وPublicB)، ويكمل المعالج، وينشئ labuser مع EnableAllFolders=false وEnabledFolders=PublicB فقط، ثم يقارن GET /Items مع GET /Items/Suggestions.
منعطفات خاطئة مسجّلة سلفًا: اعتبار GET /Items هو التسريب (إنه محدود النطاق)؛ اعتبار Suggestions?userId=<admin> هو التسريب (403)؛ اعتبار المسار القديم /Users/{userId}/Suggestions هو الثغرة (لديه GUID لذا يستدعي GetUserId)؛ ادّعاء البث غير المُصادَق كخطأ هذه الحزمة (متبقٍ شقيق)؛ صدفة عكسية. مسرح.
أخطاء العميل تبدو كأخطاء المنتج. مساعد يحجب http.client لا يرسل أي حزمة أبدًا. .recv() على HTTPResponse ليست .read(). أذكر ذلك مرة واحدة لأنه كلّف وقتًا وبدا، لدقيقة، كأن 12.2 قد أنهى المهمة.
python3 jellyfin-suggestions-idor-Abraxas-Labs.py
أو
cd lab
./run.sh
استهدف فقط http://127.0.0.1:18790. الصورة jellyfin/jellyfin:12.2. يتطلب Docker. يقوم المشغّل chdir إلى lab/ ثم ينفّذ run.sh.
IOC user-items http=200 witness=0
IOC user-suggestions http=200 witness=1
IOC impersonate-suggestions http=403
SUCCESS jellyfin-suggestions-idor items-hidden=yes suggestions-has-witness=yes impersonate-403=yes JELLYFIN-SUGGESTIONS-IDOR-WITNESS