CVE-2026-42743

Masteriyo LMS – LMS Course Builder, Quizzes & Certificates <= 2.1.8 - Missing Authorization

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

Description

The Masteriyo LMS – LMS Course Builder, Quizzes & Certificates plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.1.8. 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<=2.1.8
PublishedMay 28, 2026
Last updatedJune 2, 2026

What Changed in the Fix

Changes introduced in v2.1.9

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-42743 ## 1. Vulnerability Summary The **Masteriyo LMS** plugin (up to and including version 2.1.8) contains a **Missing Authorization** vulnerability. Specifically, several integration addons (Google Meet, Lemon Squeezy, Bricks, and Elementor) register action…

Show full research plan

Exploitation Research Plan - CVE-2026-42743

1. Vulnerability Summary

The Masteriyo LMS plugin (up to and including version 2.1.8) contains a Missing Authorization vulnerability. Specifically, several integration addons (Google Meet, Lemon Squeezy, Bricks, and Elementor) register actions or REST API endpoints that either lack capability checks or fail to properly verify the identity/permissions of the requester.

The most technical and impactful manifestation is likely in the Lemon Squeezy Integration Addon, where a webhook handler is registered via wp_ajax_nopriv_masteriyo_lemon_squeezy_webhook. If this handler processes order data (such as enrolling users in courses) without verifying the Lemon Squeezy signature, an unauthenticated attacker can forge payment notifications to gain unauthorized access to paid courses.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php?action=masteriyo_lemon_squeezy_webhook
  • Alternative Endpoint: REST API routes under wp-json/masteriyo/v1/ (e.g., google-meet, settings) if parent controllers lack default authorization.
  • HTTP Method: POST
  • Authentication: None (unauthenticated).
  • Payload Type: JSON (mimicking a Lemon Squeezy webhook event).
  • Preconditions: The Lemon Squeezy integration must be active (or the attacker must trigger
Research Findings
Static analysis — not yet PoC-verified

Summary

Masteriyo LMS is vulnerable to unauthorized access due to missing and improper capability checks across several integrations. Unauthenticated attackers can spoof Lemon Squeezy payment webhooks to gain access to paid courses, while logged-in users can bypass restrictions on Google Meet content if their account role is not specifically identified as 'student'.

Vulnerable Code

/* addons/lemon-squeezy-integration/LemonSqueezyIntegrationAddon.php */
public function handle_webhook() {
    try {
        $payload   = file_get_contents( 'php://input' );
        $signature = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
        $event     = json_decode( $payload, true );

        if ( is_null( $event ) ) {
            throw new Exception( 'Event is null.', 400 );
        }

        // Verify signature.
        $secret = Setting::get_webhook_secret();
        $hash   = hash_hmac( 'sha256', $payload, $secret );
        if ( ! hash_equals( $hash, $signature ) ) {
            masteriyo_get_logger()->error( 'Invalid signature', array( 'source' => 'payment-lemon-squeezy' ) );
            throw new Exception( 'Invalid signature.', 403 );
        }

---

/* addons/google-meet/RestApi/GoogleMeetController.php */
// (line 305 approx.)
if ( is_user_logged_in() && masteriyo_is_current_user_student() && ! masteriyo_can_start_course( $course ) ) {
    return new \WP_Error(
        'masteriyo_rest_cannot_start_course',
        __( 'Sorry, you have not bought the course.', 'learning-management-system' ),
        array(
            'status' => rest_authorization_required_code(),
        )
    );
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/learning-management-system/2.1.8/addons/google-meet/RestApi/GoogleMeetController.php /home/deploy/wp-safety.org/data/plugin-versions/learning-management-system/2.1.9/addons/google-meet/RestApi/GoogleMeetController.php
--- /home/deploy/wp-safety.org/data/plugin-versions/learning-management-system/2.1.8/addons/google-meet/RestApi/GoogleMeetController.php	2025-12-16 16:25:56.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/learning-management-system/2.1.9/addons/google-meet/RestApi/GoogleMeetController.php	2026-05-04 17:27:34.000000000 +0000
@@ -305,7 +305,7 @@
 				return true;
 			}
 
-			if ( is_user_logged_in() && masteriyo_is_current_user_student() && ! masteriyo_can_start_course( $course ) ) {
+			if ( is_user_logged_in() && ! masteriyo_is_current_user_admin() && ! masteriyo_is_current_user_instructor() && ! masteriyo_can_start_course( $course ) ) {
 				return new \WP_Error(
 					'masteriyo_rest_cannot_start_course',
 					__( 'Sorry, you have not bought the course.', 'learning-management-system' ),
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/learning-management-system/2.1.8/addons/lemon-squeezy-integration/LemonSqueezyIntegrationAddon.php /home/deploy/wp-safety.org/data/plugin-versions/learning-management-system/2.1.9/addons/lemon-squeezy-integration/LemonSqueezyIntegrationAddon.php
--- /home/deploy/wp-safety.org/data/plugin-versions/learning-management-system/2.1.8/addons/lemon-squeezy-integration/LemonSqueezyIntegrationAddon.php	2025-01-02 13:28:12.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/learning-management-system/2.1.9/addons/lemon-squeezy-integration/LemonSqueezyIntegrationAddon.php	2026-05-04 17:27:34.000000000 +0000
@@ -343,9 +373,21 @@
 				throw new Exception( 'Event is null.', 400 );
 			}
 
+			if ( empty( $signature ) ) {
+				masteriyo_get_logger()->error( 'Missing signature header', array( 'source' => 'payment-lemon-squeezy' ) );
+				throw new Exception( 'Missing signature.', 403 );
+			}
+
 			// Verify signature.
 			$secret = Setting::get_webhook_secret();
-			$hash   = hash_hmac( 'sha256', $payload, $secret );
+
+			// Reject when no secret is configured — an empty key lets anyone forge a valid HMAC.
+			if ( empty( $secret ) ) {
+				masteriyo_get_logger()->error( 'Webhook secret is not configured', array( 'source' => 'payment-lemon-squeezy' ) );
+				throw new Exception( 'Webhook secret is not configured.', 403 );
+			}
+
+			$hash = hash_hmac( 'sha256', $payload, $secret );
 			if ( ! hash_equals( $hash, $signature ) ) {
 				masteriyo_get_logger()->error( 'Invalid signature', array( 'source' => 'payment-lemon-squeezy' ) );
 				throw new Exception( 'Invalid signature.', 403 );

Exploit Outline

The exploit targets the Lemon Squeezy webhook handler. An unauthenticated attacker sends a POST request to `wp-admin/admin-ajax.php?action=masteriyo_lemon_squeezy_webhook` with a JSON payload mimicking a successful purchase event (e.g., `order_created`). Because the plugin fails to enforce a configured 'Webhook Secret' and accepts empty signatures, an attacker can sign the payload using an empty key (`hash_hmac('sha256', $payload, '')`) and provide this value in the `X-Signature` header. The plugin validates this signature against the default empty secret, matches it, and processes the fake payment to enroll the attacker in any course.

Check if your site is affected.

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