
Moodle 5.2.3 - 高 - リモート - IDOR - core_grades_get_gradeitems が非表示の成績項目を一覧表示する
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-grades-gradeitems
Moodle LMS 5.2.3 - Moodle
クラス: IDOR 到達範囲: リモート
core_grades_get_gradeitems は ajax に加えて公式モバイルサービスであり、services.php に capabilities キーが存在しない。validate_context が唯一のゲートである。その後 grade_item::fetch_all がコース内のすべての項目をダンプする。array_filter は GRADE_TYPE_NONE、カテゴリ項目、コース項目を除外する。hidden はそのフィルタに含まれていない。兄弟メソッドの core_grades_get_grade_tree はすでに moodle/grade:viewall を要求している。
登録済みの学生が {courseid} を POST すると、学生の成績表 UI では依然として非表示にされている hidden 成績項目の名前を取得できる。
| ID | CVE 未採番 |
| CWE | CWE-862 / CWE-200 |
| CVSS | Medium: 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 のみ |
攻撃者: コースに登録済みの学生。{courseid} を付けて AJAX サービスに POST する。レスポンスは名前、ID、カテゴリである。戻り値のスキーマにスコアは含まれない。RCE ではない。LPE ではない。スコアの書き込みでもない。
| 権限 | メソッド / シンク | 偵察 / 完全性 / 可用性 | ラボで実証済みか推測か |
|---|---|---|---|
| hidden 成績項目の名前、id、カテゴリを読み取る | POST /lib/ajax/service.php?sesskey= core_grades_get_gradeitems {courseid} | 偵察 | ラボで実証済み。HTTP 200、名前に MOODLE-GRADES-GRADEITEMS-WITNESS が含まれる |
| 可視の成績項目の名前、id、カテゴリを読み取る | 同じレスポンス | 偵察 (本来は教師向け) | ラボで実証済み。名前に Visible Lab Assignment が含まれる |
| 公式モバイルサービス経由で同じカタログを取得 | 同じクラス、services に MOODLE_OFFICIAL_MOBILE_SERVICE が含まれる | 偵察 | services.php から推測。ラボでは AJAX を使用 |
学生が入れるコースの courseid を連番で走査 | 同じメソッド、id を推測 | 偵察 | 推測。ラボではシード済みのコース id 2 を使用 |
| 学生の成績表 UI で hidden 項目を表示 | GET /grade/report/user/index.php?id= | n/a | ラボで実証済み クローズ。hidden-in-ui=False、visible-in-ui=True |
| セッションなしで呼び出す | ダミーの sesskey を使った AJAX | n/a | ラボで実証済み クローズ。servicerequireslogin |
| 登録していないログイン済みユーザーとして呼び出す | 部外者による AJAX、同じ courseid | n/a | ラボで実証済み クローズ。requireloginerror |
| 他の学生のスコアを読み取る、または成績を書き込む | n/a | n/a | クローズ。戻り値のキーは id、itemname、category |
| PHP RCE / OS LPE | n/a | n/a | クローズ。この残存物はカタログの読み取りである |
すでに moodle/grade:viewall を持つ教師や管理者は、このカタログをすでに閲覧できる。ゲスト / 未認証の呼び出し元には依然としてコースコンテキストが必要である。
同じピンでの残存物: Blackboard img ファイル読み取り、enrol_database SQLi、grades feedback IDOR。
MSA-26-0042/0043 の後、moodle/moodle v5.2.3 をピン留めした。成績ウェブサービスはその MSA の対象期間に含まれていた。get_gradeitems.php には依然として require_capability が存在しない。学生 UI はすでにその項目を非表示にしていた。AJAX カタログはそうではなかった。
すでに記録済みの誤った道筋: 未認証 AJAX 200 をリークとみなすこと (ボディは servicerequireslogin); メソッド名に grade が含まれるためにこれをスコア IDOR と呼ぶこと (スキーマは名前のみ); get_grade_tree も同じ残存物だと期待すること (すでに viewall を要求している)。リバースシェル。茶番である。
php:8.3-apache + MariaDB 11.4 上のライブ Moodle v5.2.3。シードは labstudent を登録し、laboutsider をコース外に残し、可視の手動項目と、名前が witness である hidden 項目を作成する。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 を持たない限り hidden 項目を除外する。Behat/PHPUnit のケースを追加する: 登録済みの学生、hidden の手動項目、core_grades_get_gradeitems はその項目を省略する (または 403) こと。学生の成績表 UI はすでにそれを非表示にしている。
get_gradeitems.phpget_grade_tree.phpservices.php (core_grades_get_gradeitems、capabilities なし)GNU Affero GPL v3.0。LICENSE を参照。ループバックラボのみ。無保証。