CVE-2026-1650

MDJM Event Management <= 1.7.8.1 - Missing Authorization to Unauthenticated Arbitrary Custom Event Field Deletion

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.7.8.2
Patched in
1d
Time to patch

Description

The MDJM Event Management plugin for WordPress is vulnerable to unauthorized data modification due to a missing capability check on the 'custom_fields_controller' function in all versions up to, and including, 1.7.8.1. This makes it possible for unauthenticated attackers to delete arbitrary custom event fields via the 'delete_custom_field' and 'id' parameters.

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.7.8.1
PublishedMarch 6, 2026
Last updatedMarch 7, 2026
Affected pluginmobile-dj-manager

What Changed in the Fix

Changes introduced in v1.7.8.2

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-1650 ## 1. Vulnerability Summary The **MDJM Event Management** plugin (versions up to 1.7.8.1) is vulnerable to unauthenticated arbitrary custom event field deletion. The vulnerability exists in the `MDJM_Event_Fields` class located in `includes/admin/pages/ev…

Show full research plan

Exploitation Research Plan: CVE-2026-1650

1. Vulnerability Summary

The MDJM Event Management plugin (versions up to 1.7.8.1) is vulnerable to unauthenticated arbitrary custom event field deletion. The vulnerability exists in the MDJM_Event_Fields class located in includes/admin/pages/event-fields.php. The class registers a controller function, custom_fields_controller(), to the admin_init hook. Because admin_init fires on admin-ajax.php even for unauthenticated users, and the controller lacks any capability checks (current_user_can) or nonce verification (check_admin_referer), an attacker can trigger the delete_field() method by providing specific GET parameters.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php (triggers admin_init unauthenticated)
  • Method: GET
  • Vulnerable Hook: admin_init
  • Vulnerable Function: MDJM_Event_Fields::custom_fields_controller
  • Required Parameters:
    • delete_custom_field: Must be present in $_GET.
    • id: The integer ID of the custom field (post ID) to be deleted.
  • Authentication: None (Unauthenticated).
  • Preconditions: An attacker must know or brute-force the ID of an existing custom event field (which uses the custom post type mdjm-custom-fields).

3. Code Flow

  1. Entry Point: A request is made to /wp-admin/admin-ajax.php.
  2. Hook Trigger: WordPress initializes the admin environment, firing the admin_init hook.
  3. Registration: In includes/admin/pages/event-fields.php, the constructor of MDJM_Event_Fields registers the handler:
    add_action('admin_init', array(&$this, 'custom_fields_controller'));
    
  4. Logic Branch: The custom_fields_controller() function executes:
    function custom_fields_controller() {
        // ... (POST logic for add/update)
        if (isset($_GET['delete_custom_field'], $_GET['id'])) {
            $this->delete_field();
        }
        return;
    }
    
  5. Sink: The delete_field() function is called. While the full source of delete_field is truncated in the provided snippet, the vulnerability description confirms it performs the deletion based on the id parameter without further authorization.

4. Nonce Acquisition Strategy

No nonce is required.
The code path in custom_fields_controller() for the GET parameters delete_custom_field and id does not invoke check_admin_referer() or wp_verify_nonce(). The missing authorization is the core of this vulnerability.

5. Exploitation Strategy

The exploit involves sending an unauthenticated GET request to the WordPress admin-ajax endpoint with the target parameters.

Step-by-Step Plan:

  1. Identify Target ID: Determine the ID of an existing custom event field (type mdjm-custom-fields).
  2. Execute Deletion: Use the http_request tool to send the malicious GET request.
  3. Verify: Use WP-CLI to confirm the post has been deleted.

Malicious Request:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php?delete_custom_field=1&id=[TARGET_ID]
  • Method: GET
  • Headers: None required.

6. Test Data Setup

To test the vulnerability, a custom field must first be created.

  1. Create a Custom Event Field via WP-CLI:
    wp post create --post_type=mdjm-custom-fields --post_title="Sensitive Field" --post_status=publish --post_content="Description"
    
  2. Record the ID: The command above will return the ID (e.g., 123). This is your [TARGET_ID].

7. Expected Results

  • Response: The server will likely return a 200 OK or a redirect (depending on whether the delete_field function calls wp_safe_redirect as seen in other functions in the class), but the key outcome is the background execution of the deletion.
  • Data State: The post with ID [TARGET_ID] and post_type mdjm-custom-fields should no longer exist or should be moved to the trash (depending on the wp_delete_post implementation in delete_field).

8. Verification Steps

After sending the HTTP request, verify the deletion using WP-CLI:

# Check if the post still exists
wp post list --post_type=mdjm-custom-fields --post_status=any --include=[TARGET_ID]

If the command returns an empty list or doesn't show the [TARGET_ID], the exploit was successful.

9. Alternative Approaches

If /wp-admin/admin-ajax.php is blocked or fails to trigger the hook as expected, any other admin file that triggers admin_init can be targeted, provided the user is not automatically redirected. Examples:

  • /wp-admin/admin-post.php?delete_custom_field=1&id=[TARGET_ID]
  • /wp-admin/index.php?delete_custom_field=1&id=[TARGET_ID] (Note: This may require a valid login session to bypass the is_user_logged_in() check in admin.php, whereas admin-ajax.php usually bypasses it for AJAX compatibility).

Since the vulnerability is unauthenticated, admin-ajax.php is the primary and most reliable vector.

Research Findings
Static analysis — not yet PoC-verified

Summary

The MDJM Event Management plugin for WordPress is vulnerable to unauthenticated arbitrary custom event field deletion due to a missing capability check and nonce verification on the custom_fields_controller function. This allows attackers to delete custom post types associated with event fields by sending a simple GET request to any administrative endpoint, including admin-ajax.php.

Vulnerable Code

// includes/admin/pages/event-fields.php line 17
function __construct()
{
    add_action('admin_init', array(&$this, 'custom_fields_controller'));

    add_action('mdjm_add_content_tags', array(&$this, 'add_tags'));
    // ...
}

---

// includes/admin/pages/event-fields.php line 104
function custom_fields_controller()
{
    if (isset($_POST['submit_custom_field'])) {
        if ($_POST['submit_custom_field'] == __('Add Field', 'mobile-dj-manager')) {
            $this->add_field();

        } elseif ($_POST['submit_custom_field'] == __('Save Changes', 'mobile-dj-manager')) {
            $this->update_field();
        }
    }

    if (isset($_GET['delete_custom_field'], $_GET['id'])) {
        $this->delete_field();
    }

    return;
} // custom_fields_controller

Security Fix

--- includes/admin/pages/event-fields.php
+++ includes/admin/pages/event-fields.php
@@ -104,6 +104,10 @@
 		function custom_fields_controller()
 		{
+			if ( ! current_user_can( 'manage_options' ) ) {
+				return;
+			}
+
 			if (isset($_POST['submit_custom_field'])) {
 				if ($_POST['submit_custom_field'] == __('Add Field', 'mobile-dj-manager')) {
 					$this->add_field();
@@ -115,6 +119,8 @@
 			}
 
 			if (isset($_GET['delete_custom_field'], $_GET['id'])) {
+				check_admin_referer( 'mdjm_delete_custom_field_' . $_GET['id'] );
+				$this->delete_field();
 			}
 
 			return;

Exploit Outline

1. Identify the post ID of a custom event field (typically using the 'mdjm-custom-fields' post type). 2. Construct a GET request to the WordPress admin environment (e.g., /wp-admin/admin-ajax.php) including the parameters 'delete_custom_field=1' and 'id' set to the target post ID. 3. Send the request without any authentication headers or session cookies. 4. The plugin's custom_fields_controller function, which is hooked to admin_init, will execute and call the delete_field method without verifying the user's identity or authorization level. 5. Observe that the custom event field is successfully deleted or moved to the trash.

Check if your site is affected.

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