
Moodle 5.2.3 - 高 - リモート - IDOR - core_grades_get_gradeitems が非表示の成績項目を一覧表示する
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-grades-gradeitems
解説記事: https://abraxaslabs.tech/research/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、カテゴリ項目、コース項目を除外する。非表示はそのフィルタに含まれていない。兄弟メソッドである core_grades_get_grade_tree はすでに moodle/grade:viewall を要求している。
登録済みの学生が {courseid} を POST すると、学生の成績表 UI では依然として非表示になっている非表示成績項目の名前を取得できる。
| 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 ではない。スコアの書き込みでもない。
| 権限 | メソッド / シンク | 偵察 / 完全性 / 可用性 | ラボ実証または推測 |
|---|---|---|---|
| 非表示成績項目の名前、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 で非表示項目を確認する | GET /grade/report/user/index.php?id= | 該当なし | ラボ実証済み クローズ。hidden-in-ui=False、visible-in-ui=True |
| セッションなしで呼び出す | ダミーの sesskey を使った AJAX | 該当なし | ラボ実証済み クローズ。servicerequireslogin |
| 登録されていないログイン済みユーザーとして呼び出す | 外部者の AJAX、同一 courseid | 該当なし | ラボ実証済み クローズ。requireloginerror |
| 他の学生のスコアを読み取る、または成績を書き込む | 該当なし | 該当なし | クローズ。戻り値のキーは id、itemname、category |
| PHP RCE / OS LPE | 該当なし | 該当なし | クローズ。この残存問題はカタログの読み取りである |
すでに moodle/grade:viewall を持つ教師や管理者は、すでにカタログを閲覧できる。ゲスト / 未認証の呼び出し元は依然としてコースコンテキストを必要とする。
同じピンからの残り物: Blackboard img file read、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 をコース外に残し、可視の手動項目と、その名前が証人となる非表示項目を作成する。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 のみです。プロジェクト 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 を持っていない限り、非表示項目を除外する。Behat/PHPUnit のテストケースを追加する: 受講登録済みの学生、非表示の手動項目、core_grades_get_gradeitems はその項目を省略する(または 403)必要がある。学生の成績表 UI ではすでに非表示になっている。
get_gradeitems.phpget_grade_tree.phpservices.php(core_grades_get_gradeitems、capabilities なし)GNU Affero GPL v3.0。LICENSE を参照。ループバックラボ専用。保証なし。