
توثّق هذه الوثيقة البحث في الثغرة الأمنية CVE-2025-2825 التي تؤثر على مكوّن الخادم في CrushFTP — وهو حل تجاري لتنظيم نقل الملفات وتخزينها (FTP، SFTP، HTTP/S، وواجهات مشابهة لـ S3 وغيرها).
يُصنَّف هذا الخلل كـ تجاوز للمصادقة (authentication bypass)، مما يسمح لمهاجم عن بُعد غير موثّق بالحصول على صلاحيات المسؤول. يمنح الاستغلال الناجح وصولاً بصلاحيات crushadmin، وإمكانية عرض وتعديل الملفات، وإدارة حسابات المستخدمين، وتنفيذ عمليات إدارية عبر واجهة الويب وواجهة برمجة التطبيقات (API) الخاصة بـ CrushFTP.
الإصدارات المتأثرة المُبلَّغ عنها (وفقاً للنشرات الأمنية العامة وتقارير الباحثين):
⚠️ ملاحظة: توجد في بعض المنشورات تكرارات وتداخلات لمعرّفات CVE (مثل CVE-2025-31161).
تحليل الثغرة خطوة بخطوة وعرض دورة البحث الكاملة، والتي تشمل:
وفقاً للتقارير العامة، تحمل الثغرة مخاطر حرجة (critical):
المثيلات التي تحمل المؤشرات التالية تعتبر حرجة:
CrushFTP (أي إصدار يحتوي على واجهة ويب).توفّر CrushFTP دعماً لواجهة برمجة تطبيقات شبيهة بـ S3. وللمصادقة تُستخدم ترويسة Authorization بالشكل التالي:
Authorization: AWS4-HMAC-SHA256 Credential=<AccessKey>/<Date>/<Region>/s3/aws4_request, SignedHeaders=<Headers>, Signature=<Signature>
يستخرج الخادم AccessKey من حقل Credential ويجب عليه التحقق من التوقيع. إلا أنه حدث خطأ في الكود عند التعامل مع العلامة lookup_user_pass.
// ServerSessionHTTP.java, метод loginCheckHeaderAuth()
if (this.headerLookup.containsKey("AUTHORIZATION") &&
this.headerLookup.getProperty("AUTHORIZATION").trim().startsWith("AWS4-HMAC")) {
boolean lookup_user_pass = true; // ← критическая ошибка
if (s3_username3.indexOf("~") >= 0) {
user_pass = user_name.substring(user_name.indexOf("~") + 1);
user_name = user_name.substring(0, user_name.indexOf("~"));
lookup_user_pass = false;
}
if (this.thisSession.login_user_pass(
lookup_user_pass,
false,
user_name,
lookup_user_pass ? "" : user_pass)) {
// Успешная аутентификация
}
}
يتم تمرير العلامة lookup_user_pass مباشرةً كمعامل باسم anyPass:
if (anyPass && user.getProperty("username").equalsIgnoreCase(the_user)) {
return user; // аутентификация без проверки пароля
}
وبالتالي:
إذا تم تحديد اسم المستخدم دون الرمز ~، تظل العلامة بقيمة true.
لا يتم التحقق من كلمة المرور.
يمكن للمهاجم اجتياز المصادقة بمجرد تحديد اسم مستخدم موجود (مثل crushadmin).
إلى جانب ملف تعريف ارتباط (cookie) صالح شكلياً باسم CrushAuth ومعامل c2f، يتيح ذلك تجاوز المصادقة والحصول على وصول إداري.
في الإصدار 11.3.1 وما بعده، قام المطوّرون بما يلي:
أضافوا المعامل s3_auth_lookup_password_supported (بقيمة افتراضية false) الذي يحجب السيناريو القابل للاستغلال.
أدخلوا عمليات فحص مبكرة لاسم المستخدم الذي يحتوي على ~.
فصلوا منطق العلامات، مما أزال تحويل lookup_user_pass ← anyPass.
التوصية: تحديث CrushFTP فوراً إلى 11.3.1+ أو تطبيق الحل البديل (workaround) مع تعطيل s3_auth_lookup_password_supported.
استغلال CVE-2025-2825 بسيط نسبياً ولا يتطلب تحضيراً معقداً. يكفي أن يرسل المهاجم طلب HTTP مُصمَّم خصيصاً يحتوي على عنصرين رئيسيين:
Authorization بتنسيق AWS S3 تحتوي على اسم مستخدم موجود وصحيح (حقل Credential مع AccessKey/اسم المستخدم).CrushAuth بالتنسيق المتوقع ومعامل c2f في عنوان URL/جسم الطلب، وتكون قيمهما متطابقة منطقياً (يجب أن يتوافق تنسيق ملف تعريف الارتباط مع البنية المتوقعة من الخادم).إذا كان الخادم عرضة للثغرة (إصدار من النطاق 10.0.0—10.8.3 أو 11.0.0—11.3.0 ولم يتم تطبيق التصحيح)، فإن هذا المزيج يجبر معالج المصادقة على السير في المسار القابل للاستغلال، حيث يتم تفسير علامة البحث عن كلمة المرور (lookup_user_pass) على أنها «أي كلمة مرور مقبولة»، فيتم توثيق المستخدم بالاسم فقط دون التحقق من كلمة المرور.
ملاحظة مهمة:
استغلال هذه الثغرة يتطلب عادةً إرسال طلبين متتاليين. الأول، وهو ما يُسمى طلب «الإحماء» (warm-up)، يطلق عملية المصادقة القابلة للاستغلال على الخادم. ومن العلامات المميزة على دخول الخادم في الحالة المطلوبة، تلقي خطأ
502 Bad Gatewayأو مجرد انتهاء مهلَة الانتظار (timeout). مباشرة بعد ذلك، يُرسَل الطلب الثاني الرئيسي، الذي ينفّذ الإجراء المطلوب (مثل إنشاء مستخدم) بينما يكون الخادم في الحالة القابلة للهجوم.
GET /WebInterface/function/?command=getUserList&serverGroup=MainUsers&c2f=1111 HTTP/1.1
Host: target-server:8080
Cookie: CrushAuth=1743113839553_vD96EZ70ONL6xAd1DAJhXMZYMn1111
Authorization: AWS4-HMAC-SHA256 Credential=crushadmin/
للاختبار، استخدمت مختبر Soulmate الذي صدر مؤخراً على منصة HTB، حيث يتطلب الأمر استغلال CrushFTP تحديداً.

بفضل هذه الثغرة، يمكن إضافة مستخدم جديد بصلاحيات مسؤول باستخدام الأمر setUserItem. وللقيام بذلك، شغّل new_user.py
python3 new_user.py --target_host http://ftp.soulmate.htb/ --port 80 --target_user crushadmin --new_user literide --password literide
تحليل ترويسة Authorization: عندما يرى الخادم ترويسة مصادقة بصيغة مشابهة لـ S3 (AWS4-HMAC...)، يستخرج من حقل Credential معرّف العميل (AccessKey / اسم المستخدم). في هذه المرحلة يحصل الخادم على سلسلة نصية يعتبرها اسم المستخدم — وهي القيمة المعرِّفة المستخدمة لاحقاً في منطق المصادقة.
العلامة lookup_user_pass ودورها:
يوجد في الكود علامة منطقية (boolean) باسم lookup_user_pass، من المفترض أن تحدد من أين يتم جلب كلمة المرور أثناء التحقق:
في السيناريو الطبيعي تساعد العلامة في تحديد: هل نستخدم كلمة المرور المرسلة في الطلب أم نجلبها من مخزن المستخدمين؛
ولكن بسبب خطأ في التنفيذ، يتم تمرير هذه العلامة نفسها إلى دالة التحقق وتُفسَّر هناك بشكل مختلف — كإشارة تسمح بتخطي التحقق من كلمة المرور (في جوهرها: «anyPass»).
تمرير العلامة عبر سلسلة الاستدعاءات:
المسار التقريبي: ServerSessionHTTP.loginCheckHeaderAuth() → Session.login_user_pass(...) → UserTools.ut.verify_user(...). عند الإدخال تحدد العلامة السلوك، وفي الدالة verify_user تؤدي إلى إرجاع كائن المستخدم الذي تم العثور عليه مبكراً بدون مقارنة كلمة المرور إذا تطابق الاسم. وهذا ما يتيح تجاوز التحقق من المصادقة — فالخادم «يتعرّف» على المستخدم بالاسم ويعتبره موثَّقاً.
العناصر المرافقة (cookie / c2f):
أشارت التحليلات العامة إلى أن المعالج يتوقع تنسيقاً صحيحاً لملف تعريف الارتباط/المعاملات بهدف ربط الطلب بالجلسة/السياق. غير أن الخلل الرئيسي يكمن تحديداً في الخطأ المنطقي في معالجة lookup_user_pass؛ أما العناصر الأخرى فتساعد فقط الطلب على المرور عبر المسارات القياسية للمعالجة.
السبب الجذري
Credential، كان يؤدي إلى أن مجرد وجود اسم مستخدم صحيح كان كافياً للحصول على بيانات المستخدم دون التحقق من كلمة المرور.القالب السلبي:
نظراً لاستحالة تحديد الإصدار الدقيق لـ CrushFTP في معظم خدمات الويب، فإن هذا القالب يتحقق فقط مما إذا كانت الخدمة تستخدم CrushFTP أم لا.
يُنصح باستخدامه مع القالب النشط
القالب النشط:
يتحقق القالب النشط من إمكانية تنفيذ الأمر getUserList.

نص برمجي متعدد الخيوط
يعمل النص البرمجي بشكل مشابه للقالب النشط، لكنه أسرع بكثير ويدعم إمكانية فحص عدة مضيفات في وقت واحد
python3 scan.py -t http://ftp.soulmate.htb/ -p 80 -u crushadmin

للتخفيف من المخاطر المرتبطة بـ CVE-2025-31161، يُنصح باتخاذ الخطوات التالية:
التحديث الفوري:
تطبيق حل بديل (Workaround) (إذا تعذّر التحديث):
s3_auth_lookup_password_supported على القيمة false. سيؤدي هذا إلى تعطيل منطق المصادقة القابل للاستغلال دون تحديث المنتج بالكامل.إجراءات تعويض المخاطر:
AWS4-HMAC-SHA256 في ترويسة Authorization، خاصة إذا لم تكن تستخدم تكامل S3.Authorization غير طبيعية موجهة إلى نقاط endpoints غير مخصصة لواجهة S3 API.