Moodle 5.2.3 - Alta - Remota - IDOR - core_grades_get_gradeitems enumera elementos de calificación ocultos
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-grades-gradeitems
Análisis: https://abraxaslabs.tech/research/moodle-grades-gradeitems
Moodle LMS 5.2.3 - Moodle
Clase: IDOR Alcance: Remoto
core_grades_get_gradeitems es ajax además del servicio móvil oficial, sin clave capabilities en services.php. validate_context es la única barrera. Después, grade_item::fetch_all vuelca todos los elementos del curso. El array_filter descarta GRADE_TYPE_NONE, los elementos de categoría y el elemento del curso. Oculto no está en ese filtro. El servicio hermano core_grades_get_grade_tree ya requiere moodle/grade:viewall.
Un estudiante matriculado envía por POST {courseid} y obtiene los nombres de los elementos de calificación ocultos que la interfaz del libro de calificaciones del estudiante aún oculta.
| ID | sin CVE todavía |
| CWE | CWE-862 / CWE-200 |
| CVSS | Medio: 4.3 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N |
| Producto | Moodle |
| Afectado | 5.2.3 etiqueta v5.2.3 (344232c15336c71b80f9aca8359ce0e0a9f3d116) |
| Autenticación | estudiante matriculado (moodle/grade:view; carece de viewall / viewhidden) |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1 |
Actor: un estudiante matriculado en el curso. Envía por POST el servicio AJAX con {courseid}. La respuesta son nombres, IDs y categorías. El esquema de retorno no tiene puntuaciones. No es RCE. No es LPE. No es una escritura de puntuaciones.
| Privilegio | Método / sink | Reconocimiento / integridad / disponibilidad | Probado en laboratorio o inferido |
|---|---|---|---|
| Leer el nombre, id y categoría de un elemento de calificación oculto | POST /lib/ajax/service.php?sesskey= core_grades_get_gradeitems {courseid} | Reconocimiento | Probado en laboratorio. HTTP 200, los nombres incluyen MOODLE-GRADES-GRADEITEMS-WITNESS |
| Leer el nombre, id y categoría de un elemento de calificación visible | Misma respuesta | Reconocimiento (previsto para profesores) | Probado en laboratorio. los nombres incluyen Visible Lab Assignment |
| El mismo catálogo a través del servicio móvil oficial | Misma clase, services incluye MOODLE_OFFICIAL_MOBILE_SERVICE | Reconocimiento | Inferido de services.php. El laboratorio usó AJAX. |
Recorrer valores secuenciales de courseid para cursos a los que el estudiante puede acceder | Mismo método, ids adivinados | Reconocimiento | Inferido. El laboratorio usó el id de curso sembrado 2 |
| Ver el elemento oculto en la interfaz del libro de calificaciones del estudiante | GET /grade/report/user/index.php?id= | n/a | Probado en laboratorio cerrado. hidden-in-ui=False, visible-in-ui=True |
| Llamar sin sesión | AJAX con un sesskey ficticio | n/a | Probado en laboratorio cerrado. servicerequireslogin |
| Llamar como un usuario autenticado que no está matriculado | AJAX de externo, mismo courseid | n/a | Probado en laboratorio cerrado. requireloginerror |
| Leer las puntuaciones de otros estudiantes o escribir calificaciones | n/a | n/a | Cerrado. Las claves de retorno son id, itemname, category |
| RCE en PHP / LPE en el SO | n/a | n/a | Cerrado. Este residuo es una lectura de catálogo |
Un profesor o gestor que ya tiene moodle/grade:viewall ya ve el catálogo. Los llamadores invitados / no autenticados siguen necesitando un contexto de curso.
Mismos restos de pin: Blackboard img file read, enrol_database SQLi, grades feedback IDOR.
Fijé moodle/moodle v5.2.3 después de MSA-26-0042/0043. Los servicios web de calificaciones estaban en esa ventana de MSA. get_gradeitems.php sigue sin require_capability. La interfaz del estudiante ya ocultaba el ítem. El catálogo AJAX no.
Pistas falsas ya registradas: tratar el AJAX no autenticado 200 como la fuga (el cuerpo es servicerequireslogin); llamar a esto un IDOR de puntuaciones porque el nombre del método contiene grade (el esquema es solo nombres); esperar que get_grade_tree fuera el mismo resto (ya requiere viewall). Una reverse shell. Teatro.
Moodle v5.2.3 en vivo sobre php:8.3-apache + MariaDB 11.4. La semilla matricula a labstudent, deja a laboutsider fuera del curso, y crea un ítem manual visible más un ítem oculto cuyo nombre es el testigo. run.sh copia un pin local o git clone --depth 1 --branch v5.2.3. El árbol de Moodle no está en este paquete.
python3 moodle-grades-gradeitems-Abraxas-Labs.py
o
cd lab
./run.sh
Dirígete solo a http://127.0.0.1:19590. Compón el proyecto moodle-grades-gradeitems. El stack se desmonta después de la ejecución.
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
Después de validate_context, exigir la misma capacidad que get_grade_tree: require_capability('moodle/grade:viewall', $context). Además, omitir los elementos ocultos a menos que quien llama tenga moodle/grade:viewhidden. Añadir un caso de Behat/PHPUnit: estudiante matriculado, elemento manual oculto, core_grades_get_gradeitems debe omitir ese elemento (o devolver 403). La interfaz del libro de calificaciones del estudiante ya lo oculta.
get_gradeitems.phpget_grade_tree.phpservices.php (core_grades_get_gradeitems, sin capabilities)