
Moodle 5.2.3 - عالي - عن بُعد - IDOR - core_grades_get_gradeitems يسرد عناصر الدرجات المخفية
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-grades-gradeitems
التحليل المكتوب: https://abraxaslabs.tech/research/moodle-grades-gradeitems
Moodle LMS 5.2.3 - Moodle
الفئة: IDOR الوصول: عن بُعد
core_grades_get_gradeitems هو ajax بالإضافة إلى خدمة الهاتف المحمول الرسمية، دون وجود مفتاح capabilities في services.php. validate_context هو البوابة الوحيدة. بعد ذلك يقوم grade_item::fetch_all بإخراج كل عنصر في المقرر. يُسقط array_filter العناصر من نوع GRADE_TYPE_NONE وعناصر الفئات وعنصر المقرر. العناصر المخفية ليست ضمن هذا الفلتر. الشقيق core_grades_get_grade_tree يتطلب بالفعل moodle/grade:viewall.
طالب مسجّل يرسل POST بـ {courseid} فيحصل على أسماء عناصر التقييم المخفية التي لا يزال واجهة سجل درجات الطالب تخفيها.
| المعرّف | لا يوجد CVE بعد |
| CWE | CWE-862 / CWE-200 |
| CVSS | متوسط: 4.3 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N |
| المنتج | Moodle |
| المتأثر | 5.2.3 وسم v5.2.3 (344232c15336c71b80f9aca8359ce0e0a9f3d116) |
| المصادقة | طالب مسجّل (moodle/grade:view؛ يفتقر إلى viewall / viewhidden) |
| الترخيص | GNU Affero GPL v3.0 |
| المختبر | 127.0.0.1 فقط |
الكاتب: طالب مسجّل في المقرر. يرسل POST إلى خدمة AJAX بـ {courseid}. الاستجابة هي أسماء ومعرّفات وفئات. مخطط الإرجاع لا يحتوي على درجات. ليس RCE. ليس LPE. وليس كتابة درجة.
| الصلاحية | الطريقة / نقطة الوصول | الاستطلاع / السلامة / التوافر | مُثبت مختبريًا أو مُستنتج |
|---|---|---|---|
| قراءة اسم ومعرّف وفئة عنصر تقييم مخفي | POST /lib/ajax/service.php?sesskey= core_grades_get_gradeitems {courseid} | استطلاع | مُثبت مختبريًا. HTTP 200، الأسماء تتضمن MOODLE-GRADES-GRADEITEMS-WITNESS |
| قراءة اسم ومعرّف وفئة عنصر تقييم ظاهر | نفس الاستجابة | استطلاع (مقصود للمعلمين) | مُثبت مختبريًا. الأسماء تتضمن Visible Lab Assignment |
| نفس الكتالوج عبر خدمة الهاتف المحمول الرسمية | نفس الفئة، services تتضمن MOODLE_OFFICIAL_MOBILE_SERVICE | استطلاع | مُستنتج من services.php. استخدم المختبر AJAX. |
المرور على قيم courseid المتسلسلة للمقررات التي يمكن للطالب دخولها | نفس الطريقة، معرّفات مُخمّنة | استطلاع | مُستنتج. استخدم المختبر معرّف المقرر المزوّد 2 |
| رؤية العنصر المخفي في واجهة سجل درجات الطالب | GET /grade/report/user/index.php?id= | لا ينطبق | مُثبت مختبريًا مغلق. hidden-in-ui=False، visible-in-ui=True |
| الاستدعاء دون جلسة | AJAX بمفتاح sesskey وهمي | لا ينطبق | مُثبت مختبريًا مغلق. servicerequireslogin |
| الاستدعاء كمستخدم مسجّل الدخول غير مسجّل في المقرر | AJAX من خارج المقرر، نفس courseid | لا ينطبق | مُثبت مختبريًا مغلق. requireloginerror |
| قراءة درجات طلاب آخرين أو كتابة درجات | لا ينطبق | لا ينطبق | مغلق. مفاتيح الإرجاع هي id وitemname وcategory |
| PHP RCE / OS LPE | لا ينطبق | لا ينطبق | مغلق. هذه البقايا هي قراءة كتالوج |
المعلم أو المدير الذي يمتلك بالفعل moodle/grade:viewall يرى الكتالوج مسبقًا. لا يزال المستخدمون الضيوف / غير المصادَقين بحاجة إلى سياق مقرر.
بقايا التثبيت نفسها: قراءة ملف صورة Blackboard، حقن SQL في enrol_database، IDOR في ملاحظات الدرجات.
ثبّتُّ moodle/moodle على الإصدار v5.2.3 بعد MSA-26-0042/0043. كانت خدمات الويب الخاصة بالدرجات ضمن نطاق تلك الـ MSA. لا يزال get_gradeitems.php بلا require_capability. كانت واجهة الطالب تُخفي العنصر بالفعل. أما كتالوج AJAX فلم يفعل.
المسارات الخاطئة المسجّلة سلفًا: اعتبار استجابة AJAX غير الموثّقة بحالة 200 هي التسريب (الجسم هو servicerequireslogin)؛ تسمية هذا بـ IDOR للدرجات لأن اسم الدالة يحتوي على grade (المخطط أسماء فقط)؛ توقّع أن يكون get_grade_tree هو نفس البقايا (فهو يتطلب viewall بالفعل). صدفة عكسية. مسرح.
Moodle مباشر v5.2.3 على php:8.3-apache + MariaDB 11.4. يُسجّل البذور labstudent، ويُبقي laboutsider خارج المقرر، ويُنشئ عنصرًا يدويًا مرئيًا إضافةً إلى عنصر مخفي اسمه هو الشاهد. ينسخ run.sh تثبيتًا محليًا أو git clone --depth 1 --branch v5.2.3. شجرة Moodle ليست في هذه الحزمة.
python3 moodle-grades-gradeitems-Abraxas-Labs.py
أو
cd lab
./run.sh
استهدف فقط http://127.0.0.1:19590. مشروع Compose moodle-grades-gradeitems. تُفكَّك الحزمة بعد انتهاء التشغيل.
SUCCESS moodle-grades-gradeitems student-ajax=200 hidden-in-ajax=yes hidden-in-ui=no visible-in-ajax=yes visible-in-ui=yes outsider-error=yes unauth-error=yes MOODLE-GRADES-GRADEITEMS-WITNESS
بعد validate_context، اشترط نفس القيد الذي يفرضه get_grade_tree: require_capability('moodle/grade:viewall', $context). كذلك احذف العناصر المخفية ما لم يكن لدى المستدعي moodle/grade:viewhidden. أضف حالة اختبار Behat/PHPUnit: طالب مسجّل، وعنصر يدوي مخفي، ويجب أن يحذف core_grades_get_gradeitems ذلك العنصر (أو يُرجع 403). واجهة سجل درجات الطالب تخفيه بالفعل.
get_gradeitems.phpget_grade_tree.phpservices.php (core_grades_get_gradeitems، بدون capabilities)GNU Affero GPL v3.0. راجع LICENSE. للاستخدام في مختبر loopback فقط. دون أي ضمان.