Tutor LMS – eLearning and online course solution <= 3.9.7 - Missing Authorization
Description
The Tutor LMS – eLearning and online course solution plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 3.9.7. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
Source Code
WordPress.org SVNThis research plan targets **CVE-2026-40743**, a Missing Authorization vulnerability in Tutor LMS (<= 3.9.7). The vulnerability allows unauthenticated attackers to perform unauthorized actions, typically via AJAX endpoints that fail to implement `current_user_can()` checks. --- ### 1. Vulnerabilit…
Show full research plan
This research plan targets CVE-2026-40743, a Missing Authorization vulnerability in Tutor LMS (<= 3.9.7). The vulnerability allows unauthenticated attackers to perform unauthorized actions, typically via AJAX endpoints that fail to implement current_user_can() checks.
1. Vulnerability Summary
- Vulnerability: Missing Authorization
- Affected Component: AJAX handlers registered via
wp_ajax_nopriv_(unauthenticated) orwp_ajax_(authenticated) that lack internal capability checks. - Root Cause: The plugin registers a sensitive action (likely related to course management, instructor settings, or system configuration) and fails to verify if the requesting user has the necessary permissions (e.g.,
manage_optionsortutor_instructor) before performing a state-changing operation.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action Name: To be determined via discovery (likely
tutor_ajax_...or a registration-related action). - Authentication: None (Unauthenticated).
- Parameter:
action,_tutor_nonce(or similar), and action-specific data parameters. - Preconditions: The plugin must be active. If the vulnerability involves course enrollment, at least one course must exist.
3. Code Flow (Inferred/Discovery Path)
- Entry Point: An AJAX request is sent to
admin-ajax.phpwithaction=[VULNERABLE_ACTION]. - Hook Registration: The plugin defines the hook in a class like
TUTOR\Ajaxor withinclasses/Ajax.phpusing:add_action( 'wp_ajax_nopriv_[VULNERABLE_ACTION]', array( $this, '[CALLBACK_FUNCTION]' ) ); - Nonce Validation: The callback likely calls
check_ajax_referer()orwp_verify_nonce(). If a nonce is required, it must be retrieved from the frontend (see Section 4). - Vulnerable Sink: The
[CALLBACK_FUNCTION]proceeds to update the database (e.g.,update_option,wp_update_user, or$wpdb->update) without callingcurrent_user_can().
4. Nonce Acquisition Strategy
Tutor LMS frequently localizes configuration data and nonces into a global JavaScript object named tutor_get_conf.
- Identify Trigger: Nonces are typically loaded on pages where Tutor LMS functionality is present (e.g., the Course Archive or a single Course page).
- Setup: Create a dummy course to ensure the scripts are enqueued.
wp post create --post_type=courses --post_title="Exploit Test" --post_status=publish
- Extraction:
- Navigate to the homepage or the newly created course page.
- Use
browser_evalto extract the nonce:browser_eval("window.tutor_get_conf?.nonce") - If that fails, check for other common Tutor LMS keys:
window.tutor_get_conf?.tutor_nonceorwindow.TutorLMSConfig?.nonce.
5. Exploitation Strategy
The specific vulnerable action needs to be identified. Based on common "Missing Authorization" flaws in Tutor LMS, we will test for unauthorized instructor registration or settings modification.
Phase A: Discovery
Search the plugin code for unauthenticated AJAX actions that perform updates:
grep -rn "wp_ajax_nopriv_" wp-content/plugins/tutor/ | grep -v "get_\|load_"
Note: Focus on actions that call functions involving update, delete, reset, or insert.
Phase B: Execution (Example: Unauthorized Setting Update)
Assuming the vulnerable action is tutor_place_order (unauthorized enrollment) or a settings reset.
Request Template:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=[IDENTIFIED_ACTION]& _tutor_nonce=[EXTRACTED_NONCE]& [PAYLOAD_PARAM]=[VALUE]
6. Test Data Setup
- Install Tutor LMS: Ensure version 3.9.7 is installed.
- Create Course:
wp post create --post_type=courses --post_title="Target Course" --post_status=publish - Identify Course ID: Use
wp post list --post_type=coursesto get the ID. - Check Registration Settings: Ensure "Anyone can register" is enabled in WP settings if testing user-related actions.
7. Expected Results
- Success: The server returns a successful response (often JSON
{"success": true}) and the state change is reflected in the database. - Failure: The server returns
403 Forbidden,-1, or a JSON error indicating "Permission Denied".
8. Verification Steps
After sending the exploit request, verify the impact using WP-CLI:
- If Enrollment Exploit: Check if the unauthenticated "session" (or a target user) is now enrolled.
wp db query "SELECT * FROM wp_posts WHERE post_type = 'tutor_enrolled'" - If Settings Exploit: Check the target option value.
wp option get [TARGET_OPTION_NAME] - If User Promotion Exploit: Check the user capabilities.
wp user list --role=tutor_instructor
9. Alternative Approaches
If the nopriv handlers are all properly authorized, investigate:
- Subscriber-level Authorization: Many Tutor LMS actions are registered for
wp_ajax_(authenticated) but only check for "logged in" status rather than specific capabilities.- Create a Subscriber user:
wp user create attacker attacker@example.com --role=subscriber. - Obtain a nonce while logged in as Subscriber.
- Attempt to access Instructor-level or Admin-level AJAX actions.
- Create a Subscriber user:
- REST API Endpoints: Check
register_rest_routecalls in Tutor LMS for missingpermission_callbackvalues.grep -rn "register_rest_route" wp-content/plugins/tutor/ -A 5
Summary
The Tutor LMS plugin for WordPress is vulnerable to unauthorized access in versions up to and including 3.9.7. This vulnerability arises because specific AJAX handlers lack internal capability checks, enabling unauthenticated attackers to execute unauthorized actions such as modifying course settings or instructor-level configurations.
Exploit Outline
1. Identify the targeted AJAX action registered via 'wp_ajax_nopriv_' or 'wp_ajax_' that lacks a 'current_user_can()' check within its callback function. 2. Navigate to the site's frontend (e.g., a course page) and extract a valid security nonce from the 'tutor_get_conf' or 'TutorLMSConfig' global JavaScript object. 3. Send a POST request to /wp-admin/admin-ajax.php with the 'action' parameter, the extracted nonce, and any required payload data for the unauthorized function. 4. Confirm execution by verifying changes to the plugin's configuration, user roles, or course data without the necessary administrative privileges.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.