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

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

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

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

دليل الأدوات

الفئات

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

CVE-2021-35042

ثغرة حقن SQL في Django

عرض المستودع
117منذ 3 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2021-35042: Django SQL injection vulnerability

I. نظرة عامة

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

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

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

CVE - IDCVE-2021-35042
Severity9.8 - CRITICAL
CWE - IDCWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
تاريخ نشر الثغرة1/7/2021
البرامج المتأثرة3.1.x < 3.1.13, 3.2.x < 3.2.5
مطلوب مصادقةغير مطلوب

II. نظرة عامة (2)

0x01. نموذج Django

في Django، يتم إنشاء الجداول وتعريف الحقول في قاعدة البيانات عن طريق تعريف فئة نموذج (model) في ملف 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: يتحقق مما إذا كان يحتوي على تعليق (comment)، إذا كان كذلك، continue.
  5. if self.extra and item in self.extra: يحدد ما إذا كان هناك إضافات (extra) وإذا كان كذلك، continue.

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

III. تحليل ثغرة SQL injection في Django

0x31. السبب

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

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

الكود قبل التغيير

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