CVE-2026-40778

Majestic Support <= 1.1.2 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.1.3
Patched in
29d
Time to patch

Description

The Majestic Support plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.1.2. 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.2
PublishedApril 9, 2026
Last updatedMay 7, 2026
Affected pluginmajestic-support

What Changed in the Fix

Changes introduced in v1.1.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Majestic Support <= 1.1.2 - Missing Authorization Research Plan ## 1. Vulnerability Summary The **Majestic Support** plugin for WordPress (versions <= 1.1.2) contains a missing authorization vulnerability. The plugin's request handling architecture, primarily managed in `MJTC_ticketController`, r…

Show full research plan

Majestic Support <= 1.1.2 - Missing Authorization Research Plan

1. Vulnerability Summary

The Majestic Support plugin for WordPress (versions <= 1.1.2) contains a missing authorization vulnerability. The plugin's request handling architecture, primarily managed in MJTC_ticketController, relies heavily on WordPress nonces for request validation but lacks sufficient current_user_can() capability checks for state-changing operations. Specifically, certain actions (like deleting attachments or closing tickets) are reachable by unauthenticated visitors because the plugin exposes the necessary nonces on public-facing support pages to facilitate guest ticket functionality.

2. Attack Vector Analysis

  • Endpoint: The page containing the [majesticsupport] shortcode (usually created at /majestic-support-controlpanel/ during activation).
  • Vulnerable Component: MJTC_ticketController (in modules/ticket/controller.php) and its interaction with MJTC_attachmentModel (in modules/attachment/model.php).
  • Action: Unauthorized deletion of ticket attachments.
  • Parameters:
    • mjsmod: The module name (e.g., ticket or attachment).
    • mjslay: The layout/action name.
    • majesticsupportid: The ID of the target resource (ticket or attachment).
    • MJTC_nonce: The security nonce.
  • Authentication: None required (
Research Findings
Static analysis — not yet PoC-verified

Summary

The Majestic Support plugin for WordPress (<= 1.1.2) fails to perform capability or ownership checks on sensitive functions, most notably those handling ticket attachments. Because security nonces are rendered on public-facing support pages to facilitate guest ticket creation, unauthenticated attackers can use these nonces to perform unauthorized actions like downloading or deleting files.

Vulnerable Code

// modules/attachment/model.php @ line 176
function getDownloadAttachmentByName($file_name,$id){
    if(empty($file_name)) return false;
    if(!is_numeric($id)) return false;
    $filename = MJTC_majesticsupportphplib::MJTC_str_replace(' ', '_',$file_name);
    $filename = MJTC_majesticsupportphplib::MJTC_clean_file_path($filename);
    $query = "SELECT attachmentdir FROM `".majesticsupport::$_db->prefix."mjtc_support_tickets` WHERE id = ".esc_sql($id);
    $foldername = majesticsupport::$_db->get_var($query);

    $MJTC_datadirectory = majesticsupport::$_config['data_directory'];
    $maindir = wp_upload_dir();
    $path = $maindir['basedir'];
    $path = $path .'/'.$MJTC_datadirectory;

    $path = $path . '/attachmentdata';
    $path = $path . '/ticket/' . $foldername;
    $file = $path . '/'.$filename;
    // ... (omitted: file headers and readfile) ...
}

---

// modules/attachment/model.php @ line 115
function removeAttachment($id) {
    if (!is_numeric($id))
        return false;
    $query = $query = "SELECT ticket.attachmentdir AS foldername,ticket.id AS ticketid,attach.filename  "
            . " FROM `".majesticsupport::$_db->prefix."mjtc_support_attachments` AS attach "
            . " JOIN `".majesticsupport::$_db->prefix."mjtc_support_tickets` AS ticket ON ticket.id = attach.ticketid "
            . " WHERE attach.id = ". esc_sql($id);
    $obj = majesticsupport::$_db->get_row($query);
    $filename = $obj->filename;
    $foldername = $obj->foldername;

    $row = MJTC_includer::MJTC_getTable('attachments');
    if ($row->delete($id)) {
        // ... (omitted: physical file deletion) ...
    }
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/majestic-support/1.1.2/modules/attachment/model.php /home/deploy/wp-safety.org/data/plugin-versions/majestic-support/1.1.3/modules/attachment/model.php
--- /home/deploy/wp-safety.org/data/plugin-versions/majestic-support/1.1.2/modules/attachment/model.php	2025-12-19 04:25:30.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/majestic-support/1.1.3/modules/attachment/model.php	2026-04-03 04:19:54.000000000 +0000
@@ -176,35 +176,55 @@
     function getDownloadAttachmentByName($file_name,$id){
         if(empty($file_name)) return false;
         if(!is_numeric($id)) return false;
-        $filename = MJTC_majesticsupportphplib::MJTC_str_replace(' ', '_',$file_name);
-        $filename = MJTC_majesticsupportphplib::MJTC_clean_file_path($filename);
-        $query = "SELECT attachmentdir FROM `".majesticsupport::$_db->prefix."mjtc_support_tickets` WHERE id = ".esc_sql($id);
-        $foldername = majesticsupport::$_db->get_var($query);
+        $download = false;
+        if(!MJTC_includer::MJTC_getObjectClass('user')->MJTC_isguest()){
+            if(current_user_can('manage_options') || current_user_can('ms_support_ticket_tickets') ){
+                $download = true;
+            }else{
+                if( in_array('agent',majesticsupport::$_active_addons) && MJTC_includer::MJTC_getModel('agent')->isUserStaff()){
+                    $download = true;
+                }else{
+                    if(MJTC_includer::MJTC_getModel('ticket')->validateTicketDetailForUser($id)){
+                        $download = true;
+                    }
+                }
+            }
+        }else{ // user is visitor
+            $download = MJTC_includer::MJTC_getModel('ticket')->validateTicketDetailForVisitor($id);
+        }
+        if($download == true){
+            $filename = MJTC_majesticsupportphplib::MJTC_str_replace(' ', '_',$file_name);
+            $filename = MJTC_majesticsupportphplib::MJTC_clean_file_path($filename);
+            $query = "SELECT attachmentdir FROM `".majesticsupport::$_db->prefix."mjtc_support_tickets` WHERE id = ".esc_sql($id);
+            $foldername = majesticsupport::$_db->get_var($query);
 
-        $MJTC_datadirectory = majesticsupport::$_config['data_directory'];
-        $maindir = wp_upload_dir();
-        $path = $maindir['basedir'];
-        $path = $path .'/'.$MJTC_datadirectory;
+            $MJTC_datadirectory = majesticsupport::$_config['data_directory'];
+            $maindir = wp_upload_dir();
+            $path = $maindir['basedir'];
+            $path = $path .'/'.$MJTC_datadirectory;
 
-        $path = $path . '/attachmentdata';
-        $path = $path . '/ticket/' . $foldername;
-        $file = $path . '/'.$filename;
-        // remove this code after version "1.0.7"
-        MJTC_includer::MJTC_getModel('majesticsupport')->generateIndexFile($path);
-        // remove above code after version "1.0.7"
+            $path = $path . '/attachmentdata';
+            $path = $path . '/ticket/' . $foldername;
+            $file = $path . '/'.$filename;
+            // remove this code after version "1.0.7"
+            MJTC_includer::MJTC_getModel('majesticsupport')->generateIndexFile($path);
+            // remove above code after version "1.0.7"
 
-        header('Content-Description: File Transfer');
-        header('Content-Type: application/octet-stream');
-        header('Content-Disposition: attachment; filename=' . MJTC_majesticsupportphplib::MJTC_basename($file));
-        header('Content-Transfer-Encoding: binary');
-        header('Expires: 0');
-        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
-        header('Pragma: public');
-        header('Content-Length: ' . filesize($file));
-        flush();
-        readfile($file);
-        exit();
-        exit;
+            header('Content-Description: File Transfer');
+            header('Content-Type: application/octet-stream');
+            header('Content-Disposition: attachment; filename=' . MJTC_majesticsupportphplib::MJTC_basename($file));
+            header('Content-Transfer-Encoding: binary');
+            header('Expires: 0');
+            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+            header('Pragma: public');
+            header('Content-Length: ' . filesize($file));
+            flush();
+            readfile($file);
+            exit();
+        }else{
+            include( get_query_template( '404' ) );
+            exit;
+        }

Exploit Outline

The exploit requires retrieving a valid security nonce and targeting specific controller actions. 1. Locate a page rendering the [majesticsupport] shortcode (default: /majestic-support-controlpanel/). 2. Extract the 'MJTC_nonce' from the page source. This nonce is created for all users, including unauthenticated guests, to support the plugin's guest ticket feature. 3. Send a GET or POST request to the site with the following parameters: 'mjsmod=attachment', 'mjslay=getDownloadAttachmentByName', 'majesticsupportid=[target_ticket_id]', 'filename=[target_filename]', and 'MJTC_nonce=[extracted_nonce]'. 4. Because the vulnerable code only checks for the presence of a valid nonce and numeric IDs but fails to verify if the requester has permission to view the ticket or attachment, the plugin will serve the file content via readfile().

Check if your site is affected.

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