مختبر بحث واستنساخ الثغرات الأمنية المُتحكَّم به لـ CVE-2020-14343 في PyYAML
يوضح هذا المشروع الثغرة CVE-2020-14343 في بيئة Docker معزولة ومُتحكَّم بها.
يحتوي المختبر على بيئتين:
yaml.safe_load()يوضح المختبر دورة حياة الثغرة الكاملة:
حمولة إعادة الإنتاج المستخدمة في هذا المختبر غير ضارة عن قصد وتطبع فقط علامة اختبار.
| الخاصية | التفاصيل |
|---|
| CVE | CVE-2020-14343 |
| المنتج | PyYAML |
| الإصدارات المتأثرة | الإصدارات قبل 5.4 |
| الإصدار المُصحَّح | 5.4 |
| نوع الثغرة | التحقق غير الصحيح من المدخلات (CWE-20) |
| الخطورة | حرجة |
| سطح الهجوم | مدخلات YAML التي تتم معالجتها باستخدام وظيفة التحميل المصابة |
تحدث الثغرة عندما تتم معالجة مدخلات YAML غير الموثوقة باستخدام وظيفة تحميل PyYAML المصابة.
سمحت إصدارات PyYAML قبل 5.4 بوسوم YAML مُصمَّمة خصيصًا، بما في ذلك الوسوم الخاصة بـ Python مثل:
!!python/object/new
للوصول إلى وظيفة إنشاء الكائنات عند استخدام FullLoader.
لذلك يمكن لمستند YAML خبيث أن يتسبب في تنفيذ كود Python غير مقصود.
كانت المشكلة مرتبطة بإصلاح غير مكتمل لثغرة سابقة في PyYAML.
أصلحت PyYAML 5.4 الثغرة CVE-2020-14343 بنقل وسوم Python التعسفية إلى UnsafeLoader.
بالنسبة للتطبيقات التي تعالج YAML غير الموثوق، يستخدم هذا المختبر أيضًا yaml.safe_load() كنهج تحميل آمن.
يحتوي المختبر على خدمتي Docker معزولتين:
Host Machine
|
+------------+------------+
| |
v v
Vulnerable App Patched App
localhost:5000 localhost:5001
| |
PyYAML 5.3.1 PyYAML 5.4
FullLoader SafeLoader
| |
v v
Payload executes Payload rejected
| الخدمة | منفذ المضيف | منفذ الحاوية | PyYAML | الغرض |
|---|---|---|---|---|
| vulnerable | 5000 | 5000 | 5.3.1 | بيئة مصابة |
| patched | 5001 | 5000 | 5.4 | بيئة مُعالَجة |
cve-2020-14343-lab/
│
├── vulnerable/
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
│
├── patched/
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
│
├── exploit/
│ └── reproduce.py
│
├── detection/
│ └── detect.py
│
├── docker-compose.yml
└── README.md
| الملف/الدليل | الغرض |
|---|---|
vulnerable/app.py | تطبيق Flask يستخدم تحميل YAML المصاب |
vulnerable/Dockerfile | يبني صورة Docker المصابة |
vulnerable/requirements.txt | يثبّت PyYAML على 5.3.1 |
patched/app.py | تطبيق Flask يستخدم تحميل YAML الآمن |
patched/Dockerfile | يبني صورة Docker المُصحَّحة |
patched/requirements.txt | يثبّت PyYAML على 5.4 |
exploit/reproduce.py | يعيد إنتاج الثغرة باستخدام حمولة مُتحكَّم بها |
detection/detect.py | يتحقق من إصدار PyYAML داخل حاوية Docker |
docker-compose.yml | يبني ويشغّل كلتا البيئتين |
البرامج التالية مطلوبة:
يجب أن يكون Docker Desktop قيد التشغيل قبل بدء المختبر.
التطبيق المصاب مكشوف عن قصد فقط على الجهاز المحلي من خلال تعيينات منافذ Docker.
من الدليل الجذر للمشروع، شغّل:
docker compose up --build -d
شغّل:
docker compose ps
يجب أن تُظهر كلتا الخدمتين Up.
افتح:
http://127.0.0.1:5000
الاستجابة المتوقعة:
{
"message": "CVE-2020-14343 vulnerable YAML parser"
}
افتح:
http://127.0.0.1:5001
الاستجابة المتوقعة:
{
"message": "CVE-2020-14343 patched YAML parser"
}
docker compose up -d
docker compose down
docker compose up --build -d
docker compose ps
docker logs cve-vulnerable
docker logs cve-patched
يكشف التطبيق المصاب عن نقطة نهاية /parse تقبل مدخلات YAML.
تستخدم البيئة المصابة:
yaml.FullLoaderيقع نص إعادة الإنتاج في:
exploit/reproduce.py
التطبيق المصاب متاح على:
http://127.0.0.1:5000/parse
شغّل:
python exploit/reproduce.py
يرسل النص البرمجي حمولة YAML مُتحكَّم بها تحتوي على وسم YAML خاص بـ Python.
في البيئة المصابة، يتم قبول الحمولة ويُرجع التطبيق استجابة HTTP 200.
علامة الاختبار المُتحكَّم بها:
CVE-2020-14343-TEST
يتم تنفيذها داخل حاوية التطبيق المصاب.
يمكن التحقق من التنفيذ باستخدام:
docker logs cve-vulnerable
يتضمن مخرجات السجل المتوقعة:
CVE-2020-14343-TEST
يوضح هذا تنفيذ الكود من خلال سلوك تحميل YAML المصاب.
حمولة إعادة الإنتاج غير ضارة عن قصد. إنها تطبع فقط علامة اختبار ولا تعدّل نظام المضيف، ولا تصل إلى بيانات الاعتماد، ولا تصل إلى بيانات حساسة، ولا تتفاعل مع أنظمة خارجية، ولا تنفذ إجراءات مدمّرة.
يقع نص الاكتشاف في:
detection/detect.py
يتحقق النص البرمجي من إصدار PyYAML المثبَّت داخل حاوية Docker المحددة.
الإصدار المُصحَّح هو:
5.4
شغّل:
python detection/detect.py cve-vulnerable
النتيجة المتوقعة:
PyYAML installed version: 5.3.1
Fixed version: 5.4
STATUS: VULNERABLE
Reason: PyYAML version is older than 5.4.
شغّل:
python detection/detect.py cve-patched
النتيجة المتوقعة:
PyYAML installed version: 5.4
Fixed version: 5.4
STATUS: PATCHED
Reason: PyYAML version is 5.4 or newer.
Docker Container
|
v
docker exec
|
v
Import PyYAML
|
v
Read yaml.__version__
|
v
Compare with 5.4
|
+----------------------+
| |
< 5.4 >= 5.4
| |
v v
VULNERABLE PATCHED
يستعلم النص البرمجي عن إصدار PyYAML المثبَّت من الحاوية الهدف.
تستخدم البيئة المصابة:
PyYAML==5.3.1
تستخدم البيئة المُصحَّحة:
PyYAML==5.4
يستخدم التطبيق المُصحَّح أيضًا:
yaml.safe_load(yaml_input)
بدلاً من:
yaml.load(yaml_input, Loader=yaml.FullLoader)
yaml.safe_load() عندما يتطلب التطبيق فقط أنواع بيانات YAML القياسية.يتم اختبار نفس حمولة الاستغلال ضد التطبيق المُصحَّح.
يعمل التطبيق المُصحَّح على:
http://127.0.0.1:5001/parse
شغّل:
python exploit/reproduce.py http://127.0.0.1:5001/parse
النتيجة الملاحظة في هذا المختبر:
HTTP Status: 400
Server Response:
{"message":"could not determine a constructor for the tag 'tag:yaml.org,2002:python/object/new:tuple' ...","status":"error"}
يتم رفض وسم YAML الخاص بـ Python من قبل التطبيق المُصحَّح.
لا يتم تنفيذ علامة الاختبار المُتحكَّم بها في التطبيق المُصحَّح.
| الاختبار | البيئة المصابة | البيئة المُصحَّحة |
|---|---|---|
| إصدار PyYAML | 5.3.1 | 5.4 |
| الاكتشاف | VULNERABLE | PATCHED |
| طلب الاستغلال | HTTP 200 | HTTP 400 |
| وسم YAML الخاص بـ Python | مقبول | مرفوض |
| تنفيذ علامة الاختبار | ملاحظ في سجلات الحاوية | غير منفَّذ |
تأكد من تشغيل Docker Desktop وتحقق من:
docker version
تحقق من:
docker ps -a
أزل الحاويات القديمة إذا لزم الأمر:
docker rm cve-vulnerable cve-patched
ثم:
docker compose up --build -d
docker compose ps
docker logs cve-vulnerable
docker logs cve-patched
docker compose up --build -d
لإعادة بناء نظيفة:
docker compose build --no-cache
docker compose up -d
هذا المشروع مختبر إثبات مفهوم مُتحكَّم به ولا يمثل نشرًا إنتاجيًا.
تشمل القيود:
يجب التقاط الأدلة التالية لتقديم المشروع:
STATUS: VULNERABLE.CVE-2020-14343-TEST في سجلات Docker.STATUS: PATCHED.يمكن تخزين لقطات الشاشة في:
screenshots/
تم تطوير جميع أكواد إعادة الإنتاج والوثائق في هذا المستودع خصيصًا لهذا المختبر.
يوضح هذا المختبر الثغرة CVE-2020-14343 من التحديد حتى المعالجة.
تستخدم البيئة المصابة PyYAML 5.3.1 وتوضح تنفيذ الكود المُتحكَّم به من خلال حمولة YAML مُصمَّمة.
يحدد نص الاكتشاف إصدار التبعية المصاب.
ترقّي البيئة المُعالَجة PyYAML إلى 5.4 وتستخدم yaml.safe_load() لمعالجة YAML غير الموثوق.
ثم يتم رفض نفس حمولة إعادة الإنتاج من قبل التطبيق المُصحَّح، مما يوفر دليلًا قبل وبعد المعالجة.
يمكن إعادة إنتاج البيئة بأكملها باستخدام Docker Compose.