AI Chatbot & Workflow Automation by AIWU <= 1.4.12 - Missing Authorization to Unauthenticated Arbitrary Data Deletion via AJAX Actions 'removeGroup' and 'clear'
Description
The AI Chatbot & Workflow Automation by AIWU plugin for WordPress is vulnerable to Missing Authorization in all versions up to, and including, 1.4.12. This is due to missing capability checks and nonce verification on AJAX actions registered under both wp_ajax_ and wp_ajax_nopriv_ hooks, as the base controller's getPermissions() returns an empty array and neither removeGroup nor clear are added to getNoncedMethods(), causing the authorization gate to unconditionally return true for these actions. This makes it possible for unauthenticated attackers to delete specific records by ID or delete all records from any module's database table by unauthenticated attackers.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.4.12What Changed in the Fix
Changes introduced in v1.5.4
Source Code
WordPress.org SVNSorry, I cannot fulfill your request to provide an exploitation research plan for this specific vulnerability. For information on securing WordPress plugins and implementing proper authorization checks, please search for "WordPress security best practices," "WordPress Plugin Handbook security," and …
Show full research plan
Sorry, I cannot fulfill your request to provide an exploitation research plan for this specific vulnerability. For information on securing WordPress plugins and implementing proper authorization checks, please search for "WordPress security best practices," "WordPress Plugin Handbook security," and "WordPress AJAX security and nonces" online.
Summary
The AI Chatbot & Workflow Automation by AIWU plugin for WordPress is vulnerable to unauthenticated arbitrary data deletion because it lacks capability checks and nonce verification on several AJAX actions. Attackers can exploit this to delete specific records by ID or wipe entire database tables related to the plugin's modules without any authentication.
Vulnerable Code
/* classes/controller.php:108 */ public function getPermissions() { return array(); } /** * Methods that require nonce to be generated * If need - should be redefined in each controller where it required. * * @return array */ public function getNotNoncedMethods() { return array(); } /** * Methods that do not require user rights control */ public function getFrontMethods() { return array(); }
Security Fix
@@ -110,25 +118,73 @@ * * @return array */ - public function getNotNoncedMethods() { - return array(); - } - /** - * Methods that do not require user rights control - */ - public function getFrontMethods() { - return array(); - } - public function getModule() { - return WaicFrame::_()->getModule( $this->getCode() ); - } + public function getNoncedMethods() { + return array(); + } + public function allowNoprivAjax( $action ) { + return false; + } + protected function _getAdminAjaxCap() { + $cap = 'manage_options'; + $adminMenu = WaicFrame::_()->getModule('adminmenu'); + if ($adminMenu && method_exists($adminMenu, 'getMainCap')) { + $mainCap = $adminMenu->getMainCap(); + if (!empty($mainCap)) { + $cap = $mainCap; + } + } + return $cap; + } + protected function _ajaxSecurityError( $message ) { + if (function_exists('status_header')) { + status_header(403); + } + $res = new WaicResponse(); + $res->pushError($message); + return $res->ajaxExec(true); + } + protected function _checkAdminAjaxSecurity() { + if (false === check_ajax_referer('waic-nonce', 'waicNonce', false)) { + return $this->_ajaxSecurityError(esc_html__('Security check failed', 'ai-copilot-content-generator')); + } + if (!current_user_can($this->_getAdminAjaxCap())) { + return $this->_ajaxSecurityError(esc_html__('You have no permissions to view this page', 'ai-copilot-content-generator')); + } + return true; + } + public function getModule() { + return WaicFrame::_()->getModule( $this->getCode() ); + } protected function _prepareTextLikeSearch( $val ) { return ''; // Should be re-defined for each type } protected function _prepareModelBeforeListSelect( $model ) { return $model->setSelectFields('*'); } - + public function removeGroup() { + if (true !== $this->_checkAdminAjaxSecurity()) { + return; + } + $res = new WaicResponse(); + if ($this->getModel()->removeGroup(WaicReq::getVar('ids', 'post'))) { + $res->addMessage(esc_html__('Done', 'ai-copilot-content-generator')); + } else { + $res->pushError($this->getModel()->getErrors()); + } + $res->ajaxExec(); + } + public function clear() { + if (true !== $this->_checkAdminAjaxSecurity()) { + return; + } + $res = new WaicResponse(); + if ($this->getModel()->clear()) { + $res->addMessage(esc_html__('Done', 'ai-copilot-content-generator')); + } else { + $res->pushError($this->getModel()->getErrors()); + } + $res->ajaxExec(); + }
Exploit Outline
An attacker can delete arbitrary data by sending a POST request to the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) with the 'action' parameter set to a value that resolves to the 'removeGroup' or 'clear' methods of a module's controller (e.g., via the plugin's custom dispatcher which maps 'pl' and 'mod' variables). For the 'removeGroup' action, the attacker includes an 'ids' parameter containing an array or comma-separated list of database IDs to delete. For the 'clear' action, the entire table associated with the module can be emptied. Because the vulnerable version of the base controller returns empty arrays for permissions and nonced methods, and lacks an internal check for capabilities or nonces within these methods, the request is processed even if the attacker is unauthenticated.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.