
CVE-2025-8088
إخلاء مسؤولية: هذا المحتوى لأغراض تعليمية وبحثية فقط. لا تستخدم هذه المعلومات لأي أنشطة ضارة.
اليوم، سنقوم بغوص عميق في ثغرة اجتياز مسار رائعة، يتم تتبعها تحت CVE-2025-8088. تسمح هذه الثغرة للمهاجم بكتابة ملف عشوائي إلى أي موقع على نظام الضحية عند استخراج أرشيف RAR مصمم خصيصًا. ما يجعل هذا الاستغلال مثيرًا للاهتمام هو نهجه "الرشاشي" لضمان تسليم الحمولة بنجاح، بغض النظر عن المكان الذي يستخرج فيه المستخدم الأرشيف.
ستقوم هذه المقالة بتحليل التقنية المستخدمة في إثبات المفهوم (PoC) المكتوب بلغة بايثون لصياغة ملف .rar الخبيث.
الهدف النهائي لهذا إثبات المفهوم كلاسيكي وفعّال: الاستمرارية. من خلال استغلال ثغرة اجتياز المسار، يهدف الاستغلال إلى إسقاط حمولة (payload.bat) في مجلد بدء تشغيل Windows (AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup). أي ملف قابل للتنفيذ أو نص برمجي يتم وضعه هنا سيتم تشغيله تلقائيًا في المرة التالية التي يسجل فيها المستخدم الدخول، مما يمنح المهاجم وصولاً مستمرًا.
يقوم نص بايثون بأتمتة عملية متعددة الخطوات لبناء exploit.rar النهائي. دعنا نستعرض منطقه.
أول شيء يفعله النص هو تحضير المكونات:
payload.bat. هذا هو الملف الخبيث الذي نريد إسقاطه على جهاز الضحية.PAYLOAD = "@echo off\necho Payload executed!\npause\n"
file1.txt, file2.txt, إلخ). تخدم هذه الملفات غرضين: تجعل الأرشيف يبدو شرعيًا، والأهم من ذلك، أنها تعمل كحاملات لحمولتنا المخفية.def create_files() -> Tuple[List[Path], Path]:
# ...
for i in range(NUM_DEPTHS):
decoy = Path(f"{DECOY_FILE_PREFIX}{i+1}.txt")
" X " * 200). سيتم تضمين هذا الحامل في بيانات وصفية للأرشيف واستبداله لاحقًا بمسارنا الخبيث.هذا جزء رئيسي من التقنية. بدلاً من تسمية ملف بمسار اجتياز، يستخدم النص ميزة من نظام الملفات NTFS تسمى تيارات البيانات البديلة (ADS). تسمح ADS بإخفاء بيانات داخل ملف موجود.
يقوم النص بإرفاق payload.bat كـ ADS لكل ملف خادع. اسم هذا التيار هو المكان الذي يستخدم فيه الحامل. باختصار، يقوم بإنشاء مسارات ملفات تبدو هكذا لنظام الملفات:
file1.txt:XXXXXXXXXXXXXXXXXXXX...
محتوى payload.bat يتم تخزينه الآن سرًا داخل file1.txt.
def attach_ads(decoy: Path, placeholder: str):
"""Attach payload to decoy as Alternate Data Stream"""
ads_path = f"{decoy}:{placeholder}"
with open(ads_path, "wb") as f:
f.write(Path("payload.bat").read_bytes())
بعد ذلك، يبحث النص عن أداة سطر الأوامر Rar.exe على النظام ويستخدمها لإنشاء أرشيف أساسي شرعي (base.rar). يحتوي هذا الأرشيف على جميع الملفات الخادعة، والتي تحمل الآن الحمولة سرًا في تيارات البيانات البديلة الخاصة بها.
في هذه المرحلة، base.rar هو أرشيف صالح تمامًا وغير ضار. يمكن لـ WinRAR استخراجه دون أي مشكلة، وسيقوم بإنشاء الملفات الخادعة بأسماء ADS الطويلة والغريبة.
def create_base_rar(rar_exe: str, decoys: List[Path]) -> Path:
# ...
subprocess.run(
f'"{rar_exe}" a -ep -os "{base_rar}" {files}',
# ...
)
هنا يصبح الاستغلال ذكيًا ومرنًا. لا يعرف المهاجم أين سيستخرج الضحية الأرشيف. هل سيكون C:\Users\victim\Downloads؟ أم C:\؟ أم D:\Temp؟
للتغلب على هذا الغموض، يقوم النص بإنشاء قائمة من سلاسل اجتياز المسار المختلفة، كل منها بعمق مختلف:
..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.bat..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.bat..\..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.batالفكرة هي أنه من خلال توفير أعماق متعددة، سينجح واحد منها على الأقل في التنقل من دليل الاستخراج إلى جذر نظام الملفات (مثل C:\) ثم إلى مجلد بدء التشغيل المستهدف.
def build_relative_paths() -> List[str]:
"""Generate paths with different traversal depths"""
paths = []
for depth in range(1, NUM_DEPTHS + 1):
paths.append(("..\\" * depth) + RELATIVE_DROP_PATH)
return paths
هذا هو جوهر الاستغلال. يفتح النص base.rar في الوضع الثنائي ويقوم بإجراء عملية جراحية عليه.
يقوم بالتكرار خلال البنية الداخلية للأرشيف، باحثًا عن رأس كل ملف (file1.txt, file2.txt, إلخ). داخل كل رأس، يجد اسم الحامل ADS (:XXXXXXXXXXXXXXXXXXXX...) ويستبدله بأحد مسارات الاجتياز الخبيثة التي تم إنشاؤها في الخطوة السابقة.
file1.txt يحصل على المسار مع ..\.file2.txt يحصل على المسار مع ..\..\.def patch_rar(base_rar: Path, placeholder: str, relative_paths: List[str]) -> Path:
# ...
while pos + 4 <= len(data) and current_file_index < len(target_paths_utf8):
# ...
# Find the placeholder and replace it with the target path
c = patch_placeholder_in_header(hdr, placeholder_utf8, target_utf8)
# ...
مجرد تغيير بيانات الرأس قد يفسد الأرشيف. يستخدم WinRAR مجموع اختباري CRC32 للتحقق من سلامة كل كتلة رأس. إذا لم يتطابق المجموع الاختباري مع محتوى الرأس، فسيظهر خطأ.
يتوقع إثبات المفهوم هذا. بعد تعديل رأس بالمسار الخبيث، يقوم بإعادة حساب المجموع الاختباري CRC32 الصحيح لكتلة الرأس الكاملة المعدلة ويكتب المجموع الاختباري الجديد مرة أخرى في الملف. هذا يجعل الأرشيف المعدل يبدو صالحًا تمامًا لـ WinRAR.
def rebuild_all_header_crc(buf: bytearray) -> int:
"""Recalculate CRC checksums for all headers"""
# ...
while pos + 4 <= len(buf):
# ...
# Calculate CRC for the header region
region = buf[block_start + 4:header_end]
crc = zlib.crc32(region) & 0xFFFFFFFF
# Write the new CRC back into the buffer
struct.pack_into("<I", buf, block_start, crc)
# ...