أدت ثغرة حقن HTML مخزنة في لوحة وظائف RamenHire إلى تمكين أي شخص من ملء نموذج عام وتحويل رسائل البريد الإلكتروني الخاصة بإشعارات الفريق إلى منصة تصيد احتيالي.
كيف تسللت الثغرة
تعمل RamenHire باستخدام Next.js وSupabase وتسمح للشركات الناشئة بنشر الوظائف دون الحاجة لتسجيل الدخول. تؤدي كل عملية إرسال إلى إرسال بريد إلكتروني إلى فريق التوظيف الداخلي. يتم بناء نص البريد الإلكتروني عن طريق دمج حقول النموذج الخام — اسم الشركة، وصف الوظيفة، اسم جهة الاتصال — مباشرة في سلسلة HTML. لا تتم أي عملية هروب (escaping) أو تنقية (sanitisation) قبل وصول السلسلة إلى خدمة البريد.
نظرًا لأن القالب يعامل مدخلات المستخدم على أنها HTML آمن، يمكن لمتقدم بطلبات خبيثة حقن رابط مزيف "انقر هنا للتحقق". يتم تخزين الحمولة (payload) على الخادم كجزء من إدراج الوظيفة، لذا فإن كل رسالة بريد إلكتروني إشعار لاحقة تحمل الكود الخبيث. يمكن للمهاجم إخفاء ذلك الرابط بجانب زر "عرض لوحة التحكم" الحقيقي، مما يخدع أحد أعضاء الفريق للكشف عن بيانات الاعتماد أو زيارة موقع تصيد احتيالي.
لماذا كان الأمر مهماً
تصل رسائل البريد الإلكتروني إلى فريق التوظيف الأساسي، وهم أشخاص ينقرون على الروابط باستمرار لتحريك المرشحين عبر مراحل التوظيف.
الفجوة التقنية
عملية الهروب من HTML ليست خطوة واحدة. هناك سياقان يحتاجان إلى الحماية:
- عقد النصوص (Text nodes) – المحتوى الموجود بين الوسوم. تحويل
<إلى<و>إلى>يوقف الوسوم، لكنه لا يمنع المهاجم من الخروج من قيمة السمة (attribute value). - قيم السمات (Attribute values) – السلاسل النصية داخل الوسوم مثل
href="…". يؤدي حقن علامة اقتباس ("أو') إلى السماح للمهاجم بإغلاق السمة مبكرًا وإدراج علامات التنسيق الخاصة به.
كان الكود الأصلي يتعامل مع النص العادي فقط، مما ترك حقن السمات مفتوحًا على مصراعيه.
إصلاح المشكلة
أضاف المطور دالة مساعدة صغيرة escapeHtml وطبقها على كل قيمة يقدمها المستخدم قبل عملية الإدراج (interpolation)، سواء انتهى الأمر بالقيمة في عقدة نصية أو في سمة.
خطوات التحقق
- الاختبار المحلي – تم تزويد وظائف القالب بمجموعة من سلاسل الحقن. أظهر كل اختبار الأحرف المهربة فقط، دون وجود وسوم قابلة للتنفيذ.
- اختبار الإنتاج – بعد نشر الإصلاح، تم إرسال حمولة عبر الموقع المباشر، وتجاوز فحص البوت الخاص بـ Cloudflare Turnstile. وصلت الرسالة الناتجة إلى صندوق الوارد الخاص بالمطور؛ وظهر الرابط الخبيث وأي وسوم
scriptكنص غير مفهوم، وليس كعناصر قابلة للنقر.
ملاحظة بخصوص Gmail: قد تظل الخدمة تلون الرابط باللون الأزرق وتجعله قابلاً للنقر، ولكن هذا مجرد تسهيل من جانب العميل (client-side) ولا يعني نجاح حقن HTML. يمنع الإصلاح عملية الحقن من إنشاء أزرار حقيقية أو تشغيل برامج نصية (scripts).
ما يجب على المطورين مراقبته
- لا تثق أبدًا في البيانات الواردة من النماذج العامة – حتى النماذج التي تبدو غير ضارة يمكن أن تنتج مخرجات مخزنة تُستخدم في مكان آخر.
- قم بعملية الهروب عند نقطة الاستخدام – طبق عملية الهروب الواعية بالسياق (نص مقابل سمة) مباشرة قبل عملية العرض (rendering)، وليس في مرحلة مبكرة من خط المعالجة.
- اختبر كلاً من جانب العميل وجانب الخادم – تكتشف اختبارات الوحدة (Unit tests) الإخفاقات الواضحة؛ بينما يؤكد الاختبار اليدوي الشامل (end-to-end) عبر واجهة المستخدم المباشرة صمود الدفاعات تحت حركة المرور الحقيقية.
- كن على دراية بغرائب عملاء البريد الإلكتروني – تقوم بعض البرامج بربط الروابط تلقائيًا، مما يخلق شعورًا زائفًا بالأمان. تحقق من أن HTML الأساسي لا يحتوي على أي عناصر نشطة.
الخلاصة
أدت هفوة واحدة في التعامل مع مدخلات المستخدم إلى تحويل رسائل البريد الإلكتروني الروتينية للإشعارات إلى وسيلة تصيد احتيالي. أدى إدخال روتين شامل للهروب من HTML والتحقق من الإصلاح محليًا وفي بيئة الإنتاج إلى استعادة سلامة صندوق الوارد. تؤكد هذه الواقعة على درس خالد لأي تطبيق ويب يقوم بإنشاء HTML من بيانات غير موثوقة: التنقية الصحيحة أمر غير قابل للتفاوض، وتجاهلها قد يفتح خطًا مباشرًا إلى صناديق وارد مستخدميك.
