
Moodle 5.2.3 - Élevée - À distance - IDOR - core_grades_get_gradeitems liste les éléments de note masqués
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-grades-gradeitems
Moodle LMS 5.2.3 - Moodle
Classe : IDOR Portée : Distante
core_grades_get_gradeitems est un service ajax ainsi que le service mobile officiel, sans clé capabilities dans services.php. validate_context est la seule barrière. Ensuite grade_item::fetch_all extrait chaque élément du cours. Le array_filter écarte GRADE_TYPE_NONE, les éléments de catégorie et l'élément de cours. Le masquage (hidden) ne figure pas dans ce filtre. Le service frère core_grades_get_grade_tree exige déjà moodle/grade:viewall.
Un étudiant inscrit envoie en POST {courseid} et obtient les noms des éléments de note masqués que l'interface du carnet de notes de l'étudiant masque encore.
| ID | pas encore de CVE |
| CWE | CWE-862 / CWE-200 |
| CVSS | Moyen : 4.3 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N |
| Produit | Moodle |
| Affecté | 5.2.3 tag v5.2.3 (344232c15336c71b80f9aca8359ce0e0a9f3d116) |
| Auth | étudiant inscrit (moodle/grade:view ; sans viewall / viewhidden) |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Auteur : un étudiant inscrit au cours. Il envoie en POST le service AJAX avec {courseid}. La réponse contient des noms, des identifiants et des catégories. Le schéma de retour ne contient aucune note. Pas de RCE. Pas de LPE. Pas d'écriture de note.
| Privilège | Méthode / sink | Reconnaissance / intégrité / disponibilité | Prouvé en lab ou déduit |
|---|---|---|---|
| Lire le nom, l'id et la catégorie d'un élément de note masqué | POST /lib/ajax/service.php?sesskey= core_grades_get_gradeitems {courseid} | Reconnaissance | Prouvé en lab. HTTP 200, les noms incluent MOODLE-GRADES-GRADEITEMS-WITNESS |
| Lire le nom, l'id et la catégorie d'un élément de note visible | Même réponse | Reconnaissance (prévu pour les enseignants) | Prouvé en lab. les noms incluent Visible Lab Assignment |
| Même catalogue via le service mobile officiel | Même classe, services inclut MOODLE_OFFICIAL_MOBILE_SERVICE | Reconnaissance | Déduit de services.php. Le lab a utilisé AJAX. |
Parcourir des valeurs courseid séquentielles pour les cours auxquels l'étudiant peut accéder | Même méthode, ids devinés | Reconnaissance | Déduit. Le lab a utilisé l'id de cours préchargé 2 |
| Voir l'élément masqué dans l'interface du carnet de notes de l'étudiant | GET /grade/report/user/index.php?id= | n/a | Prouvé en lab fermé. hidden-in-ui=False, visible-in-ui=True |
| Appeler sans session | AJAX avec un sesskey factice | n/a | Prouvé en lab fermé. servicerequireslogin |
| Appeler en tant qu'utilisateur connecté non inscrit | AJAX d'un tiers, même courseid | n/a | Prouvé en lab fermé. requireloginerror |
| Lire les notes d'autres étudiants ou écrire des notes | n/a | n/a | Fermé. Les clés de retour sont id, itemname, category |
| RCE PHP / LPE OS | n/a | n/a | Fermé. Ce résidu est une lecture de catalogue |
Un enseignant ou un gestionnaire disposant déjà de moodle/grade:viewall voit déjà le catalogue. Les appelants invités / non authentifiés ont toujours besoin d'un contexte de cours.
Autres résidus du même pin : Blackboard img file read, enrol_database SQLi, grades feedback IDOR.
J'ai épinglé moodle/moodle v5.2.3 après MSA-26-0042/0043. Les services web de notes se trouvaient dans cette fenêtre MSA. get_gradeitems.php n'a toujours pas de require_capability. L'interface étudiant masquait déjà l'élément. Le catalogue AJAX ne le faisait pas.
Fausses pistes déjà consignées : considérer un AJAX non authentifié renvoyant 200 comme la fuite (le corps est servicerequireslogin) ; qualifier cela d'IDOR de notes parce que le nom de la méthode contient grade (le schéma ne contient que des noms) ; s'attendre à ce que get_grade_tree soit le même résidu (il exige déjà viewall). Un reverse shell. Du théâtre.
Moodle v5.2.3 en direct sur php:8.3-apache + MariaDB 11.4. Le seed inscrit labstudent, laisse laboutsider hors du cours, et crée un élément manuel visible ainsi qu'un élément masqué dont le nom est le témoin. run.sh copie un pin local ou git clone --depth 1 --branch v5.2.3. L'arborescence Moodle n'est pas incluse dans ce pack.
python3 moodle-grades-gradeitems-Abraxas-Labs.py
ou
cd lab
./run.sh
Cible uniquement http://127.0.0.1:19590. Projet Compose moodle-grades-gradeitems. La stack est démontée après l'exécution.
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
Après validate_context, exiger la même capacité que get_grade_tree : require_capability('moodle/grade:viewall', $context). Écarter également les éléments masqués sauf si l'appelant dispose de moodle/grade:viewhidden. Ajouter un cas Behat/PHPUnit : étudiant inscrit, élément manuel masqué, core_grades_get_gradeitems doit omettre cet élément (ou renvoyer 403). L'interface du carnet de notes de l'étudiant le masque déjà.
get_gradeitems.phpget_grade_tree.phpservices.php (core_grades_get_gradeitems, pas de capabilities)GNU Affero GPL v3.0. Voir LICENSE. Lab en boucle locale uniquement. Aucune garantie.