CVE-2025-13679

Tutor LMS <= 3.9.3 - Missing Authorization to Authenticated (Subscriber+) Sensitive Information Exposure via tutor_order_details

mediumMissing Authorization
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
3.9.4
Patched in
1d
Time to patch

Description

The Tutor LMS – eLearning and online course solution plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the get_order_by_id() function in all versions up to, and including, 3.9.3. This makes it possible for authenticated attackers, with Subscriber-level access and above, to enumerate order IDs and exfiltrate sensitive data (PII), such as student name, email address, phone number, and billing address.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=3.9.3
PublishedJanuary 7, 2026
Last updatedJanuary 8, 2026
Affected plugintutor

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-13679 (Tutor LMS Sensitive Information Exposure) ## 1. Vulnerability Summary The **Tutor LMS** plugin (versions <= 3.9.3) contains a missing authorization vulnerability within its AJAX handling logic. Specifically, the AJAX action `tutor_order_details` fails t…

Show full research plan

Exploitation Research Plan: CVE-2025-13679 (Tutor LMS Sensitive Information Exposure)

1. Vulnerability Summary

The Tutor LMS plugin (versions <= 3.9.3) contains a missing authorization vulnerability within its AJAX handling logic. Specifically, the AJAX action tutor_order_details fails to verify if the requesting user has the authority to view a specific order's details. While the endpoint requires the user to be authenticated (wp_ajax hook), it does not restrict access to administrators or the owner of the order. This allows any authenticated user (starting from the Subscriber role) to enumerate order IDs and retrieve PII, including student names, email addresses, phone numbers, and billing addresses.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Method: POST
  • Action: tutor_order_details
  • Vulnerable Parameter: order_id (integer)
  • Required Authentication: Subscriber-level (or any authenticated role)
  • Nonce Requirement: Yes, the plugin typically requires the _tutor_nonce or nonce parameter associated with Tutor LMS AJAX actions.

3. Code Flow

  1. Entry Point: The plugin registers the AJAX action:
    add_action( 'wp_ajax_tutor_order_details', array( $ajax_class, 'tutor_order_details' ) ); (inferred from Tutor LMS AJAX structure).
  2. Handler: The tutor_order_details() function is invoked.
  3. Data Fetching: The handler retrieves the order_id from $_POST['order_id'].
  4. Vulnerable Sink: It calls get_order_by_id( $order_id ) (or a similar internal method) to fetch order metadata.
  5. Authorization Failure: The code lacks a check like current_user_can('manage_tutor') or a verification that the get_current_user_id() matches the user ID associated with the order.
  6. Response: The full order object, including PII fields, is returned as a JSON response.

4. Nonce Acquisition Strategy

Tutor LMS localizes security nonces for its frontend and backend dashboards. To obtain a valid nonce for the tutor_order_details action as a Subscriber:

  1. Shortcode/Page Identification: The _tutor_nonce is typically enqueued on the Tutor LMS Dashboard page.
  2. Setup: Ensure a page exists with the [tutor_dashboard] shortcode.
  3. Extraction:
    • Log in as the Subscriber user.
    • Navigate to the dashboard page: /dashboard/ (or the page containing the shortcode).
    • Execute JavaScript via browser_eval to extract the nonce.
    • JS Variable: window.tutor_get_conf?.nonce or window._tutor_nonce. (Verbatim from Tutor LMS script localization: tutor_ajax.nonce).

5. Exploitation Strategy

Step 1: Authentication

Log in to the WordPress instance using Subscriber credentials.

Step 2: Nonce Extraction

Navigate to the Tutor Dashboard and extract the nonce:

// Browser Eval
window.tutor_ajax?.nonce

Step 3: PII Exfiltration Request

Send the malicious AJAX request to exfiltrate order details for a target order_id.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=tutor_order_details&order_id=123&_tutor_nonce=[EXTRACTED_NONCE]
    

(Note: Parameter names like order_id and _tutor_nonce are standard for Tutor LMS AJAX handlers).

6. Test Data Setup

  1. Admin User: Ensure an admin user exists (default ID 1).
  2. Target Content: Create a course and "purchase" it or manually generate a Tutor Order as the Admin.
    • Use WP-CLI to identify an existing order ID: wp post list --post_type=tutor_order --format=ids.
  3. Attacker User: Create a Subscriber user: wp user create attacker attacker@example.com --role=subscriber --user_pass=password123.
  4. Dashboard Page: Ensure a dashboard page exists for nonce generation:
    • wp post create --post_type=page --post_title="Dashboard" --post_content="[tutor_dashboard]" --post_status=publish

7. Expected Results

  • Success: The response will be a JSON object (HTTP 200) containing keys such as billing_first_name, billing_email, billing_phone, billing_address_1, etc., belonging to the user who placed order_id=123 (the Admin), even though the requester is a Subscriber.
  • Failure (Patched): The response will likely be a 403 Forbidden or a JSON error message indicating "Permission Denied".

8. Verification Steps

  1. Response Analysis: Use the http_request tool to inspect the JSON body. Check for the presence of the Admin's email or phone number.
  2. Cross-Check: Verify via WP-CLI that the exfiltrated data matches the database:
    • wp post get [ORDER_ID]
    • wp post meta list [ORDER_ID]

9. Alternative Approaches

If tutor_order_details is not the direct AJAX action, search for other order-related actions:

  • tutor_get_order_data
  • tutor_view_order
  • tutor_load_order_modal

If the _tutor_nonce is not found in tutor_ajax, check the global tutor_vars or search the page source for any string containing nonce. If the plugin fails to check the nonce entirely (common in "Missing Authorization" bugs), try the request without the _tutor_nonce parameter.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.