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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-34207 — تحقق مرشح SSRF من نص اسم المضيف، لكن الوجهة الفعلية تم تحديدها لاحقًا بواسطة DNS. تلك الثغرة سمحت لعناوين URL الخاصة بـ Webhook التي يتحكم بها المهاجم بالوصول إلى أهداف loopback والبيانات الوصفية والشبكة الخاصة. | Kitploit
أدوات/GitHubGitHub/0xmrma/cve-2026-34207
تحليل الثغرات الأمنيةالاستغلالأمن الويباختبار الاختراقالأوراق والأبحاثالتعلم والتعليم
GitHub0xmrma/cve-2026-34207

CVE-2026-34207

تحقق مرشح SSRF من نص اسم المضيف، لكن الوجهة الفعلية تم تحديدها لاحقًا بواسطة DNS. تلك الثغرة سمحت لعناوين URL الخاصة بـ Webhook التي يتحكم بها المهاجم بالوصول إلى أهداف loopback والبيانات الوصفية والشبكة الخاصة.

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

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2026-34207

تحقق مرشح SSRF من نص اسم المضيف، ولكن الوجهة الفعلية تم تحديدها لاحقًا بواسطة DNS. سمحت هذه الفجوة لعناوين Webhook التي يتحكم فيها المهاجم بالوصول إلى loopback وبيانات التعريف وأهداف الشبكة الخاصة.

مقدمة

عثرت على هذه المشكلة أثناء مراجعة Typebot، منصة بناء روبوتات محادثة مفتوحة المصدر، مع سؤال أمني بسيط في ذهني:

ماذا يحدث إذا تحقق حماية SSRF من نص اسم المضيف، ولكن الوجهة الحقيقية تُقرر لاحقًا بواسطة DNS؟

في هذه الحالة، أدى هذا السؤال إلى خطأ حقيقي.

حماية SSRF الخاصة بـ Typebot لكتل Webhook / طلب HTTP تحققت فقط من:

  • سلسلة URL،
  • حظر نص اسم المضيف،
  • وتنسيقات IP الحرفية

لم تحل أسماء المضيف قبل السماح بالطلب.

هذا يعني أن اسم مضيف مثل ssrf-repro.example يمكن أن يبدو غير ضار أثناء التحقق، ثم يحل إلى:

  • 127.0.0.1
  • 169.254.169.254
  • أو المساحة الخاصة RFC1918/الشبكة الخاصة

وما زال يتم جلبها بواسطة عميل HTTP الخلفي.

أصبحت هذه المشكلة CVE-2026-34207.

Typebot: Typebot على GitHub
CVE: CVE-2026-34207
تم الإصلاح في: 3.16.0

أثر هذا على Typebot، منصة روبوتات محادثة مفتوحة المصدر واسعة الاستخدام. على موقعها الرسمي، يُقدم Typebot على أنه موثوق من أكثر من 650 شركة حول العالم. كما يعلن الموقع عن أكثر من 2 مليون محادثة شهريًا و أكثر من 1.5 مليون بوت منشور.

photo0

سلسلة الهجوم

عنوان URL لـ Webhook يتحكم به المهاجم -> اسم المضيف يمر عبر التحقق الحرفي فقط SSRF -> لا يوجد حل DNS قبل قرار السماح -> عميل HTTP الخلفي يحل اسم المضيف إلى هدف داخلي -> يصل الطلب من جانب الخادم إلى loopback / بيانات التعريف / الشبكة الخاصة -> تصبح بيانات الرد متاحة من خلال سجلات التنفيذ


ما يفعله Typebot

Typebot هو منصة بناء روبوتات محادثة.

يسمح للمستخدمين بإنشاء تدفقات يمكنها:

  • طرح الأسئلة
  • جمع المدخلات المنظمة
  • استدعاء الخدمات الخارجية
  • تسلسل منطق الأعمال
  • وتشغيل طلبات HTTP الصادرة من خلال كتل Webhook / طلب HTTP

هذا يعني أن تنفيذ الطلبات الصادرة هو حدود أمنية حقيقية.

السؤال المهم هنا لم يكن ما إذا كان Typebot يدعم كتل Webhook.

السؤال الحقيقي كان:

هل يتحقق حماية SSRF من الوجهة الفعلية التي سيتصل بها الخادم، أم فقط نص اسم المضيف الذي يظهر في URL؟

في هذه الحالة، تحقق فقط من الشكل النصي أولاً.

كان هذا هو الخطأ.


لماذا كان هذا السطح يستحق النظر

تفشل دفاعات SSRF بطرق متوقعة جدًا.

في معظم الأوقات، الأخطاء المثيرة للاهتمام ليست:

  • "لقد نسيت حظر 169.254.169.254"
  • أو "لقد نسيت حظر localhost"

الأخطاء الأقوى هي أخطاء الحدود:

  • التحقق يحدث قبل التوحيد
  • التحقق يحدث قبل إعادة التوجيه
  • التحقق يحدث قبل حل DNS
  • التحقق يحدث على تمثيل واحد، لكن مكدس الشبكة يستخدم تمثيلًا آخر

كان هذا هو المكان المناسب للبحث هنا.

كان لدى Typebot بالفعل منطق تقوية SSRF لعناوين IP البيانات الوصفية الحرفية، و loopback، والنطاقات الخاصة، وخدع IP المشفرة.

هذا جعل السؤال التالي واضحًا:

ماذا لو لم يكن اسم المضيف خطيرًا حرفيًا، ولكنه يحل إلى وجهة خطيرة لاحقًا؟

هذا بالضبط ما حدث.


السبب الجذري

كانت المشكلة الجذرية هي التحقق من الوجهة بناءً على نص اسم المضيف بدلاً من عنوان IP الذي تم حله.

في التنفيذ الضعيف، validateHttpReqUrl():

  • حلل URL
  • سمح فقط بـ http: و https:
  • حظر قائمة قصيرة من أسماء المضيف الحرفية مثل metadata.google.internal و metadata.goog و metadata و localhost
  • كشف خدع IP العشرية / السداسية / الثمانية الحرفية
  • حلل عناوين IPv4 / IPv6 الحرفية
  • تحقق من العنوان فقط إذا كان اسم المضيف نفسه هو بالفعل IP حرفي

هذا هو الجزء المهم.

إذا كان اسم المضيف قيمة عادية مثل:

ssrf-repro.example

فإن parseIPAddress(hostname) أعاد null، وتوقف المدقق عند هذا الحد.

لم يحدث حل DNS قبل الموافقة.

لذا المنطق الضعيف اختُزل عمليًا إلى:

root@kitploit:~
const ip = parseIPAddress(hostname);
if (ip) {
  validateIPAddress(ip);
}

هذا يعني:

  • تم حظر عناوين IP الخطيرة الحرفية
  • تم حظر عناوين IP المشفرة الخطيرة
  • لكن أسماء المضيف التي تحل إلى عناوين IP خطيرة لم تُحظر

النصف الثاني من الخطأ كان في مسار التنفيذ.

في executeHttpRequest()، قام Typebot أولاً بتشغيل التحقق ثم لاحقًا نفذ الطلب الفعلي باستخدام ky(request.url, ...).

لذا كان التسلسل:

  • تحقق من سلسلة URL
  • قبول اسم المضيف
  • لاحقًا حل اسم المضيف أثناء الطلب الصادر الفعلي
  • الاتصال بالهدف الداخلي الذي تم حله

هذا هو الثغرة بأكملها.


لماذا هذه مشكلة أمنية، وليست مجرد تصفية غير كاملة

الفرق المهم هو مكان اتخاذ قرار الثقة.

الكثير من الأخطاء تبدو صغيرة إذا وصفتها بشكل سيء.

إذا وصفت هذا الخطأ على أنه:

"مرشح اسم المضيف كان غير مكتمل"

يبدو وكأنه مشكلة جودة.

هذه ليست المشكلة الحقيقية.

المشكلة الحقيقية كانت:

  • اتخذ الخادم قرارًا أمنيًا قبل أن يعرف الوجهة الحقيقية
  • مكدس الشبكة اتصل لاحقًا بمكان آخر
  • والتعامل مع الطلب على أنه صالح من قبل التطبيق

هذا ليس ضعفًا تجميليًا في التصفية.

هذا فشل في حدود الثقة.

ولأن منفذ HTTP سجل بيانات الرد في سجلات التنفيذ، لم تكن المشكلة عمياء حتى في أقوى الحالات.

لذا لم يكن هذا مجرد:

  • "حدثت حركة مرور داخلية غير متوقعة"

كان:

  • حدثت حركة مرور داخلية
  • وغالبًا ما يمكن للمهاجم استرداد دليل ومحتوى الرد من خلال سلوك التطبيق العادي

هذا هو ثغرة SSRF حقيقية.


إثبات المفهوم

استخدمت طبقتين للإثبات لأنهما أظهرتا شيئين مختلفين.

إثبات المفهوم 1: عرض توضيحي محلي لحل الأسماء مستقل

عزل إثبات المفهوم الأول السبب الجذري بشكل نظيف.

استخدمت أداة مساعدة محلية صغيرة:

  • بدأت خادم HTTP loopback على 127.0.0.1
  • تحققت من URL مثل http://ssrf-repro.example:18080/...
  • استخدمت حلالًا مسيطرًا بحيث ssrf-repro.example حل إلى 127.0.0.1
  • ثم نفذت الطلب

أظهر هذا الخطأ بالضبط:

  • نجح التحقق لأن اسم المضيف لم يكن قيمة حرفية محظورة
  • الطلب اللاحق ما زال يصل إلى loopback

أظهر المخرجات الملتقطة:

  • نتيجة المدقق: نجاح
  • نتيجة تنفيذ الطلب: تم الوصول إلى loopback
  • نص الرد عاد من خدمة loopback

أثبت هذا فجوة التحقق مباشرة.


إثبات المفهوم 2: مسار التنفيذ الحقيقي لـ Typebot

أظهر إثبات المفهوم الثاني الخطأ من خلال مسار الميزة الفعلي الذي يهم.

أبسط إعادة إنتاج كانت:

  1. قم بربط اسم مضيف غير ضار بـ loopback على الجهاز حيث يحل Typebot الخلفي DNS
  2. ابدأ خدمة HTTP محلية
  3. أنشئ كتلة Webhook تشير إلى اسم المضيف غير الضار هذا
  4. شغل الكتلة من خلال مسار معاينة أو تنفيذ مباشر مصادق عليه

كتلة تمثيلية تبدو هكذا:

root@kitploit:~
{
  "id": "blk-webhook",
  "type": "Webhook",
  "options": {
    "webhook": {
      "method": "GET",
      "url": "http://ssrf-repro.example:8000/"
    }
  }
}

مع إدخال ملف المضيفين مثل:

root@kitploit:~
127.0.0.1 ssrf-repro.example

ما زال المدقق يقبل URL لأن:

  • ssrf-repro.example لم يكن في blockedHostnames
  • لم يكن localhost
  • parseIPAddress("ssrf-repro.example") أعاد null
  • لم يحدث تحقق من IP الوجهة

ثم قام عميل HTTP الخلفي بحل اسم المضيف إلى 127.0.0.1 واتصل على أي حال.

أثبت هذا الادعاء الكامل:

  • منطق التحقق الضعيف كان قابلاً للوصول في استخدام الميزة الحقيقية
  • الطلب أصاب فئة وجهة محظورة
  • وما زال التطبيق يعامله كطلب HTTP صادر ناجح

لماذا تم اختيار إثباتي المفهوم بهذه الطريقة

إثبات المفهوم الأول يثبت السبب الجذري.

إثبات المفهوم الثاني يثبت التأثير على المنتج.

هذا التقسيم مهم.

إذا أظهرت فقط:

"هذا المرشح يقبل اسم مضيف"

لم تظهر ما يكفي.

إذا أظهرت فقط:

"حدث طلب داخلي"

لم تعزل السبب.

التقرير الأقوى هو:

  • تحقق قائم على اسم المضيف قبل قيمة كان ينبغي ألا تُوثق
  • حل DNS لاحقًا غير المعنى الأمني الحقيقي لتلك القيمة
  • الخادم الخلفي اتصل بوجهة محظورة
  • ومسار الميزة ما زال مكتملاً

هذه هي القصة الكاملة.


الخطورة والتصنيف

تم تصنيف هذه المشكلة بشكل معقول كـ عالية.

تصنيف الاستشارة كان:

  • CWE-918: تزوير طلب من جانب الخادم (SSRF)
  • CWE-20: التحقق غير السليم من المدخلات
  • CVSS:
root@kitploit:~
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L

هذا منطقي.

لم يكن هذا SSRF غير مصادق عليه على مستوى الإنترنت بمفرده.

الامتيازات المطلوبة كانت منخفضة لأن الخطأ المستقل يتطلب فاعلًا يمكنه تكوين أو تشغيل كتلة Webhook / طلب HTTP.

لكن ضمن هذا الحد، كان التأثير خطيرًا:

  • الوصول إلى loopback
  • الوصول إلى الشبكة الخاصة
  • الوصول إلى بيانات التعريف
  • واستخراج الرد من خلال السجلات

هذه مشكلة SSRF قوية بذاتها.

وتصبح أكثر خطورة عند دمجها مع أخطاء أخرى توسع نطاق الوصول.


لماذا كان هذا لا يزال يستحق الإبلاغ

بعض الناس يرون SSRF مصادقًا عليه ويقللون من شأنه فورًا.

هذا خطأ.

السؤال الحقيقي ليس:

"هل كان المهاجم مسجل الدخول؟"

السؤال الحقيقي هو:

"هل يمكن لذلك المهاجم أن يجعل الخادم يتصل بمكان كان من المفترض أن يمنعه النموذج الأمني؟"

هنا، الإجابة كانت نعم.

المدقق ادعى حماية:

  • خدمات بيانات التعريف
  • loopback
  • النطاقات الخاصة RFC1918
  • النطاقات المحلية IPv6

لكن فجوة حل أسماء المضيف أعادت تلك الوجهات نفسها من خلال تمثيل مختلف.

هذا بالضبط نوع الخطأ الذي يستحق CVE.


تحليل الإصلاح

كان الإصلاح قويًا لأنه صحح الحد الحقيقي، وليس مجرد عرض.

في التنفيذ المصحح، تم تغيير validateHttpReqUrl() لحل أسماء المضيف قبل الموافقة على الطلب.

المدقق الآن:

  • يستورد lookup من node:dns/promises
  • يعامل التحقق كغير متزامن
  • يحل أسماء المضيف غير الحرفية قبل السماح بها
  • يحلل كل عنوان تم حله
  • يتحقق من كل عنوان تم حله مقابل نفس النطاقات المحظورة

هذا هو الإصلاح الصحيح لأنه يغير قرار الثقة من:

  • "هل يبدو نص اسم المضيف جيدًا؟"

إلى:

  • "هل الوجهة الفعلية تحل إلى عنوان مسموح به؟"

هذه هي الخاصية الأمنية التي كان ينبغي أن توجد من البداية.

أضاف المعالجة أيضًا تغطية تراجعية لـ:

  • أسماء مضيف تحل إلى loopback
  • أسماء مضيف تحل إلى مساحة RFC1918
  • مضيفين داخليين مدرجين في القائمة البيضاء للمستضيفين الذاتيين
  • الحفاظ على الحماية غير القابلة للالتفاف لأهداف بيانات التعريف و loopback

هذا هو نوع التقوية الذي تريده في إصلاح SSRF حقيقي:

  • تم تصحيح الحد
  • السلوك المقصود موثق في الكود
  • والاختبارات تثبت الفئة

تم حل المشكلة في Typebot 3.16.0.


الإفصاح

تم الإبلاغ عن هذه المشكلة بشكل خاص من خلال تدفق الإبلاغ الأمني في GitHub.

تضمن التقرير:

  • السبب الجذري في validateHttpReqUrl()
  • مسار التنفيذ النهائي في executeHttpRequest()
  • استراتيجية إعادة إنتاج واقعية باستخدام حل اسم المضيف إلى loopback / أهداف خاصة
  • وعرضًا توضيحيًا مستقلاً لعزل فجوة التحقق

قبل المالكون المشكلة، وأصلحوا منطق التحقق، وتم نشر الثغرة لاحقًا كـ:

CVE-2026-34207

مع إصدار الإصلاح في Typebot 3.16.0.


ما يعلمه هذا الخطأ بالفعل

الدرس الرئيسي هنا بسيط:

القرارات الأمنية يجب أن تُتخذ على نفس التمثيل الذي سيستخدمه مكدس الشبكة فعليًا.

هذا يبدو واضحًا.

لكن الكثير من حمايات SSRF تفشل بالضبط لأنها لا تتبع هذه القاعدة.

  • سلسلة اسم المضيف تبدو آمنة.
  • DNS يغير معناها.
  • الطلب ما زال يُنفذ.

هذا كافٍ.

هذا الخطأ يعزز أيضًا شيئًا مهمًا حول مراجعة SSRF بشكل عام:

  • تصفية IP الحرفي ليست كافية
  • القوائم السوداء لأسماء المضيف ليست كافية
  • فحوصات IP المشفرة ليست كافية

إذا لم تحل وتتحقق من الوجهة الحقيقية، فإن مرشح SSRF الخاص بك ما زال غير مكتمل.

هذا هو الاستنتاج الحقيقي.


النقاط الرئيسية

  • دفاعات SSRF تفشل عندما يحدث التحقق قبل حل الوجهة
  • التحقق من نص اسم المضيف ليس نفس الشيء مثل التحقق من IP الوجهة
  • ميزات Webhook / طلب HTTP هي حدود أمنية حقيقية
  • SSRF المصادق عليه يمكن أن يكون عالي الخطورة عندما يصل إلى بيانات التعريف والخدمات الداخلية
  • تقرير قوي يربط السبب الجذري بالتأثير، وليس مجرد أحدهما
  • كان الإصلاح صحيحًا لأنه نقل القرار إلى الوجهة الفعلية التي تم حلها

الكلمات الختامية

لم تكن هذه الثغرة حول تحميل خيالي.

كانت حول طرح سؤال الحد الصحيح.

في Typebot، قام مدقق SSRF بفحص نص اسم المضيف أولاً. الوجهة الفعلية تم تحديدها لاحقًا بواسطة DNS. عميل الشبكة تبع العنوان الذي تم حله.

تلك الفجوة كانت الخطأ.

لهذا أصبحت CVE-2026-34207.

تم الإصلاح في Typebot 3.16.0.

تنزيل الأداة