سمح DeepSeek Harness لمهاجم داخل بيئة معزولة (sandbox) بتنفيذ أوامر عشوائية ببساطة عن طريق تغيير ترويسة HTTP Host إلى 127.0.0.1، وهو ما يسجل 9.4 على مقياس CVSS. يوضح هذا الخلل كيف يمكن لقرار ثقة واحد في غير محله أن يحول حدوداً وقائية إلى باب خلفي مفتوح.
كيف تسلل هذا الخلل
يوجد الكود المعرض للخطر في دالة واحدة تقرأ ترويسة Host الخاصة بالطلب، وإذا كانت القيمة تساوي عنوان الحلقة المرتدة (loopback address)، فإنها تعامل الطلب كما لو كان قادماً من الجهاز المحلي.
لا يحتاج المهاجم الذي يمكنه تنفيذ كود داخل البيئة المعزولة إلى حمولة (payload) معقدة. فمن خلال إرسال طلب HTTP واحد يحتوي على Host: 127.0.0.1 ، يعتقد النظام الخلفي (backend) أن الاستدعاء صادر من المضيف نفسه، وبالتالي يتخطى جميع مطالبات الأمان، وفحوصات تحديد معدل الطلبات (rate-limit)، وخطوات التحقق من الأوامر. النتيجة: تنفيذ أوامر غير مقيد دون الحاجة إلى أي تفاعل إضافي.
لماذا يعد الوثوق بالترويسات أمراً خطيراً
الترويسات هي سلاسل نصية بسيطة يقدمها المستدعي. وسواء كان اسم الحقل Host أو X-Forwarded-For أو أي اسم مخصص آخر، يمكن للعميل ضبطه على أي قيمة يرغب بها. المصدر الوحيد الموثوق للحقيقة حول المكان الذي جاء منه الاتصال فعلياً هو طبقة النقل (transport layer) – أي عنوان IP المصدر للمقبس (socket) الذي يسجله نظام التشغيل عند اكتمال مصافحة TCP.
عندما يقرر تطبيق ما الوثوق بترويسة دون التأكد من أن بروكسي معروف ومعد بشكل صحيح هو من قام بحقنها، فإنه يمنح المهاجم مفاتيح المملكة. ويعد خلل DeepSeek Harness مثالاً نموذجياً على هذه العثرة.
التأثير في العالم الحقيقي: مثال shell.online
وثق مشروع shell.online مفتوح المصدر، الذي يوفر طرفية (terminal) قائمة على الويب، نفس هذا المأزق مؤخراً. وهو يستخدم علامة تكوين تسمى TRUST_PROXY:
- TRUST_PROXY = 0 – يتجاهل التطبيق ترويسة X-Forwarded-For ويعتمد على العنوان البعيد للمقبس (socket). وهذا يمنع العميل من تزوير عنوان IP للتهرب من حدود معدل الطلبات أو التظاهر بأنه مستخدم موثوق.
- TRUST_PROXY = 1 – يثق التطبيق في ترويسة X-Forwarded-For كتعريف لهوية العميل. إذا لم تكن الخدمة خلف بروكسي فعلي يقوم بتنقية هذه الترويسة، فيمكن للمهاجم تقديم عنوان IP جديد مع كل طلب، مما يؤدي فعلياً إلى إعادة ضبط أي تقنين (throttling) لكل عنوان IP.
يعكس خلل DeepSeek هذا السيناريو: فقد وثق الكود في Host كما لو كان البروكسي هو من وضعه، ومع ذلك كان من الممكن الوصول إلى الخدمة مباشرة.
ما يجب على المطورين فعله الآن
- راجع كل مكان تقرأ فيه الترويسات التي يقدمها العميل. حدد الترويسات التي تعاملها كمرجع موثوق (مثل Host و X-Forwarded-For و X-Real-IP) وتحقق من ضمان قيام بروكسي موثوق بإعادة كتابتها قبل وصولها إلى تطبيقك.
- اربط قرارات الأمان بعنوان المقبس (socket address) كلما أمكن ذلك. استخدم عنوان IP المصدر الذي يوفره نظام التشغيل لعمليات المصادقة، وتحديد معدل الطلبات، وفحوصات التحكم في الوصول.
- قم بتفعيل علامات الوثوق بالبروكسي فقط عندما يكون هناك بروكسي عكسي (reverse proxy) معد بشكل صحيح أمام الخدمة. إذا كنت تقوم بتشغيل التطبيق مباشرة، فابقِ هذه العلامات معطلة.
- وثق طوبولوجيا النشر (deployment topology) المطلوبة في ملف README الخاص بمشروعك أو دليل النشر، حتى يعرف المستخدمون الذين يستضيفون الخدمة بأنفسهم متطلبات الوثوق بالبروكسي.
- استخدم أدوات التحليل الساكن (static-analysis) أو أدوات مراجعة الكود التي تنبه إلى الاستخدام المباشر للترويسات في قرارات الأمان دون وجود منطق مصاحب للتحقق من البروكسي.
ما يجب مراقبته لاحقاً
من المرجح أن تعيد المجتمعات التي تقدم خدمات ويب ذاتية الاستضافة النظر في إعدادات الوثوق بالبروكسي الخاصة بها بعد هذا الحادث.
الدرس الأساسي صارخ: لا تسمح أبداً لنص يمكن لأي شخص على الإنترنت كتابته بأن يملي الوضع الأمني لنظامك. ثق بطبقة الشبكة، وليس بطبقة الطلب.
