Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

الخلاصاتاتصالالخصوصية© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2021-35042 — تحليل أساسي حول CVE-2021-35942. حقن SQL في Django. | Kitploit
أدوات/GitHubGitHub/zer0qs/cve-2021-35042
تحليل الثغرات الأمنيةالاستغلالأمن الويبالأوراق والأبحاثالتعلم والتعليم
GitHubzer0qs/cve-2021-35042

CVE-2021-35042

تحليل أساسي حول CVE-2021-35942. حقن SQL في Django.

عرض المستودع
211منذ 4 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2021-35042: ثغرة حقن SQL في Django

أولا: نظرة عامة

Django هو إطار عمل لتطوير تطبيقات الويب مفتوح المصدر، مكتوب بلغة Python ومبني وفق نموذج MVC (Model - View - Controller). تم بناؤه في البداية لإدارة مواقع الويب ذات المحتوى الإخباري المملوكة لمجموعة النشر Lawrence، وهو برنامج CMS (نظام إدارة المحتوى).

توجد ثغرة حقن SQL في إصدارات Django 3.1.x -> 3.1.13 والإصدارات 3.2.x -> 3.2.5.

سبب هذه الثغرة هو أن وظيفة تصفية بيانات الإدخال التي يتحكم فيها المستخدم في QuerySet.order_by() غير كافية لمنع هجمات حقن SQL. يمكن استغلال هذه الثغرة للسماح للمهاجم بتنفيذ إجراءات غير مصرح بها تؤدي إلى تسريب بيانات حساسة.

CVE - IDCVE-2021-35042
الخطورة9.8 - حرجة
CWE - IDCWE-89: تحييد غير صحيح للعناصر الخاصة المستخدمة في أمر SQL ('حقن SQL')
تاريخ نشر الثغرة1/7/2021
البرامج المتأثرة3.1.x < 3.1.13, 3.2.x < 3.2.5
يتطلب مصادقةغير مطلوب

ثانيا: نظرة عامة x2

0x01. نموذج Django

في Django، يتم إنشاء الجداول وتحديد الحقول في قاعدة البيانات عن طريق تعريف فئة نموذج في ملف models.py. في هذا المثال، نعرّف جدولًا باسم Wolf وحقلًا باسم name.

0x02. QuerySet و Order_by() في Django

يُستخدم إطار عمل ORM المدمج في Django للتعامل مع قاعدة البيانات، ونتيجة الاستعلام هي مجموعة، وهذه المجموعة هي QuerySet.

order_by(fields) بشكل افتراضي، تُرجع order_by() QuerySet مرتبًا بترتيب محدد في خيار ordering في Meta الخاص بالنموذج. يمكننا تجاوز شرط order_by في كل استعلام باستخدام طريقة order_by().

مثال

wolves = Wolf.objects.order_by('-name', 'id')

ستكون نتيجة الاستعلام أعلاه مرتبة تنازليًا حسب حقل name، ثم تصاعديًا حسب id. تشير الإشارة السالبة قبل اسم الحقل name إلى أن النتيجة مرتبة تنازليًا.

المثال التالي سيرتب النتائج حسب الحقل المُدخل من المستخدم، وإذا لم يتم تمرير أي قيمة، فسيتم الترتيب حسب حقل id.

النتيجة

في الإصدارين 3.1 و 3.2، يسمح Django بدمج طريقة الاستعلام مع اسم الجدول في استعلام order_by. هذا هو السبب الرئيسي لهذه الثغرة.

تمرير اسم جدول يعطينا نفس نتيجة تمرير اسم حقل عادي

cve202135042_wolf هو اسم الجدول

أولاً، يستدعي التطبيق مباشرة دالة order_by()، ويتم تعريف الكود الذي يعالج دالة order_by() في: django/db/models/query.py

تقوم دالة order_by() بأمرين

  1. حذف جميع الطرق الحالية التي يتم استدعاؤها بواسطة order_by() وحذف المعامل الافتراضي الذي يتم تمريره عندما يستقبل order_by قيمة مختلفة.
  1. تمرير المعامل إلى order_by. تقوم دالة add_ordering() بهذا الأمر.
def add_ordering(self, *ordering):
        """
        Add items from the 'ordering' sequence to the query's "order by"
        clause. These items are either field names (not column names) --
        possibly with a direction prefix ('-' or '?') -- or OrderBy
        expressions.

        If 'ordering' is empty, clear all ordering from the query.
        """
        errors = []
        for item in ordering:
            if isinstance(item, str):
                if '.' in item:
                    warnings.warn(
                        'Passing column raw column aliases to order_by() is '
                        'deprecated. Wrap %r in a RawSQL expression before '
                        'passing it to order_by().' % item,
                        category=RemovedInDjango40Warning,
                        stacklevel=3,
                    )
                    continue
                if item == '?':
                    continue
                if item.startswith('-'):
                    item = item[1:]
                if item in self.annotations:
                    continue
                if self.extra and item in self.extra:
                    continue
                # names_to_path() validates the lookup. A descriptive
                # FieldError will be raise if it's not.
                self.names_to_path(item.split(LOOKUP_SEP), self.model._meta)
            elif not hasattr(item, 'resolve_expression'):
                errors.append(item)
            if getattr(item, 'contains_aggregate', False):
                raise FieldError(
                    'Using an aggregate in order_by() without also including '
                    'it in annotate() is not allowed: %s' % item
                )
        if errors:
            raise FieldError('Invalid order_by arguments: %s' % errors)
        if ordering:
            self.order_by += ordering
        else:
            self.default_ordering = False
            

المعامل الذي يتم تمريره إلى add_ordering() هو مصفوفة.

مثال عند تمرير المعامل كما يلي: wolves = Wolf.objects.order_by( 'name' , 'id' ) عندها، سيقوم التطبيق بتحويله إلى استعلام في قاعدة البيانات كما يلي:

SELECT "cve202135042_wolf"."id", "cve202135042_wolf"."name" FROM "cve202135042_wolf" ORDER BY "cve202135042_wolf"."name" ASC, "cve202135042_wolf"."id" ASC

عند تمريره، ستقوم دالة add_ordering بفحص كل عنصر في المصفوفة، وإذا كان string، فسيتم فحصه في 5 حالات:

  1. if '.' in item: سيتحقق مما إذا كان استعلامًا باسم عمود وأن هذا العمود له اسم جدول محدد في عبارة SQL أم لا. إذا كان كذلك، فسيصدر تحذيرًا وينفذ continue.
  2. if item == '?': إذا كانت قيمة العنصر هي علامة '?'، فسيتم ترتيب النتائج عشوائيًا، ثم continue.
  3. if item.startswith('-'): إذا بدأ العنصر بالحرف '-'، فسيتم ترتيب نتائج الاستعلام تنازليًا (DESC).
  4. if item in self.annotations: يتحقق مما إذا كان يحتوي على تعليق توضيحي أم لا، وإذا كان كذلك، فسيتم continue.
  5. if self.extra and item in self.extra: يحدد ما إذا كانت هناك إضافات، وإذا كان كذلك، فسيتم continue.

بعد الفحوصات الخمسة، يتم تمرير المعامل إلى دالة self.names_to_path(item.split(LOOKUP_SEP), self.model._meta) لمواصلة التحقق مما إذا كان اسم عمود صالحًا أم لا، وبعد ذلك إذا كان صالحًا، فسيتم إضافته إلى self.ordering الخاص بفئة Query لمزيد من المعالجة.

ثالثا: تحليل ثغرة حقن SQL في Django

0x31. السبب

يقوم ORM الخاص بـ Django بتصفية البيانات المُدخلة في الاستعلام بشكل صارم للغاية، لكن التغيير في الكود المصدري هذه المرة الذي أدى إلى حقن SQL هو أن المؤلف افترض أنه إذا كان اسم العمود هو عمود UUID (المعرف الفريد العام)، فلن يمكن تنفيذ استعلام order_by.

أي إذا كانت البيانات المُدخلة هي xxx-xxx-xxx-xxx (تنسيق UUID)، فلن يمكن تنفيذ الاستعلام.

الكود قبل إجراء التغيير

# django/db/models/sql/constants.py 
ORDER_PATTERN  =  _lazy_re_compile ( r '\?|[-+]?[.\w]+$' )
تنزيل الأداة