
Moodle 5.2.3 - Alto - Remoto - IDOR - core_grades_get_gradeitems lista itens de nota ocultos
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-grades-gradeitems
Moodle LMS 5.2.3 - Moodle
Classe: IDOR Alcance: Remoto
core_grades_get_gradeitems é ajax mais o serviço móvel oficial, sem chave capabilities em services.php. validate_context é a única barreira. Depois, grade_item::fetch_all despeja todos os itens do curso. O array_filter descarta GRADE_TYPE_NONE, itens de categoria e o item do curso. Oculto não está nesse filtro. O irmão core_grades_get_grade_tree já exige moodle/grade:viewall.
Um estudante matriculado faz POST de {courseid} e obtém nomes de itens de nota ocultos que a UI do boletim do estudante ainda esconde.
| ID | sem CVE ainda |
| CWE | CWE-862 / CWE-200 |
| CVSS | Médio: 4.3 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N |
| Produto | Moodle |
| Afetado | 5.2.3 tag v5.2.3 (344232c15336c71b80f9aca8359ce0e0a9f3d116) |
| Autenticação | estudante matriculado (moodle/grade:view; sem viewall / viewhidden) |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1 |
Autor: um estudante matriculado no curso. Ele faz POST do serviço AJAX com {courseid}. A resposta são nomes, IDs e categorias. O esquema de retorno não tem notas. Não é RCE. Não é LPE. Não é escrita de nota.
| Privilégio | Método / sink | Recon / integridade / disponibilidade | Comprovado em lab ou inferido |
|---|---|---|---|
| Ler nome, id e categoria de item de nota oculto | POST /lib/ajax/service.php?sesskey= core_grades_get_gradeitems {courseid} | Recon | Comprovado em lab. HTTP 200, nomes incluem MOODLE-GRADES-GRADEITEMS-WITNESS |
| Ler nome, id e categoria de item de nota visível | Mesma resposta | Recon (destinado a professores) | Comprovado em lab. nomes incluem Visible Lab Assignment |
| Mesmo catálogo pelo serviço móvel oficial | Mesma classe, services inclui MOODLE_OFFICIAL_MOBILE_SERVICE | Recon | Inferido de services.php. Lab usou AJAX. |
Percorrer valores sequenciais de courseid para cursos que o estudante pode acessar | Mesmo método, ids adivinhados | Recon | Inferido. Lab usou o id de curso semeado 2 |
| Ver o item oculto na UI do boletim do estudante | GET /grade/report/user/index.php?id= | n/a | Comprovado em lab fechado. hidden-in-ui=False, visible-in-ui=True |
| Chamar sem sessão | AJAX com sesskey fictícia | n/a | Comprovado em lab fechado. servicerequireslogin |
| Chamar como usuário logado que não está matriculado | AJAX de outsider, mesmo courseid | n/a | Comprovado em lab fechado. requireloginerror |
| Ler notas de outros estudantes ou escrever notas | n/a | n/a | Fechado. Chaves de retorno são id, itemname, category |
| PHP RCE / OS LPE | n/a | n/a | Fechado. Este resquício é uma leitura de catálogo |
Um professor ou gestor que já tem moodle/grade:viewall já vê o catálogo. Chamadores convidados / não autenticados ainda precisam de um contexto de curso.
Resquícios do mesmo pin: Blackboard img file read, enrol_database SQLi, grades feedback IDOR.
Fiz pin de moodle/moodle v5.2.3 após MSA-26-0042/0043. Os web services de notas estavam nessa janela de MSA. get_gradeitems.php ainda não tem require_capability. A UI do estudante já escondia o item. O catálogo AJAX não.
Caminhos errados já registrados: tratar AJAX não autenticado 200 como o vazamento (o corpo é servicerequireslogin); chamar isso de IDOR de nota porque o nome do método tem grade (o esquema é apenas nomes); esperar que get_grade_tree fosse o mesmo resquício (ele já exige viewall). Um reverse shell. Teatro.
Moodle v5.2.3 ao vivo em php:8.3-apache + MariaDB 11.4. O seed matricula labstudent, deixa laboutsider fora do curso e cria um item manual visível mais um item oculto cujo nome é a testemunha. run.sh copia um pin local ou git clone --depth 1 --branch v5.2.3. A árvore do Moodle não está neste pacote.
python3 moodle-grades-gradeitems-Abraxas-Labs.py
ou
cd lab
./run.sh
Alvo apenas http://127.0.0.1:19590. Projeto Compose moodle-grades-gradeitems. A stack é derrubada após a execução.
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
Após validate_context, exigir a mesma cap que get_grade_tree: require_capability('moodle/grade:viewall', $context). Também descartar itens ocultos a menos que o chamador tenha moodle/grade:viewhidden. Adicionar um caso Behat/PHPUnit: estudante matriculado, item manual oculto, core_grades_get_gradeitems deve omitir esse item (ou 403). A UI do boletim do estudante já o esconde.
get_gradeitems.phpget_grade_tree.phpservices.php (core_grades_get_gradeitems, sem capabilities)GNU Affero GPL v3.0. Veja LICENSE. Apenas lab em loopback. Sem garantia.