ثغرة Server-Side Request Forgery (SSRF) تحدث عندما يقوم الـ API بجلب مورد بعيد (Remote Resource) بناءً على رابط (URL) يرسله المستخدم، دون التحقق من وجهة هذا الرابط بشكل صحيح.
في هذه الحالة، يثق السيرفر في المدخلات التي قدمها المستخدم ويقوم بإرسال طلب (Request) إلى العنوان المطلوب. المخترق يستغل هذا الأمر لإجبار السيرفر على إرسال طلبات "نيابة عنه" إلى أماكن لم يكن من المفترض الوصول إليها.
تخيل أن هناك شركة كبرى محصنة بأسوار عالية وحراس أمن على البوابة الرئيسية. هؤلاء الحراس يمنعون أي شخص غريب من الدخول إلى المكاتب الداخلية.
-
الوضع الطبيعي: داخل هذه الشركة يوجد "موظف توصيل بريد" مهمته الوحيدة هي تلقي طلبات من الموظفين أو الزوار لجلب طرود من "خارج" الشركة. يأتي الزائر ويقول له: "من فضلك، اذهب إلى المتجر الموجود في الشارع المقابل واجلب لي هذا الطرد"، فيذهب الموظف ويحضره.
-
المشكلة (ثغرة SSRF): يأتي شخص ذكي (المخترق) ويستغل أن حراس الأمن يثقون في "موظف البريد" ويسمحون له بالتجول داخل مكاتب الشركة بحرية دون تفتيش. بدلاً من أن يطلب منه جلب شيء من الخارج، يعطيه ورقة مكتوب فيها: "اذهب إلى مكتب المدير في الدور الثالث، واجلب لي الملف السري الموجود في الخزنة".
-
النتيجة:
- بما أن الطلب قادم من "موظف البريد" الموثوق، فإن حراس المكاتب الداخلية لن يمنعوه.
- يذهب الموظف (السيرفر)، يأخذ الملف (البيانات الحساسة)، ويعود به إلى الشخص الغريب الواقف خارج البوابة.
في هذا النوع، يقوم السيرفر بجلب البيانات من الرابط الذي وضعه المخترق ويعرضها له مباشرة في الاستجابة (Response).
- كيف يحدث: عندما تطلب من API جلب صورة من رابط، فيقوم السيرفر بجلب محتوى الرابط وإظهاره لك على الشاشة.
- خطورته: يمكن للمخترق وضع رابط لملف حساس داخل السيرفر (مثل
file:///etc/passwdفي أنظمة Linux)، وسيقوم السيرفر بقراءة الملف وعرض محتواه للمخترق كأنه "صورة".
هنا يقوم السيرفر بتنفيذ الطلب، لكنه لا يعيد البيانات للمخترق في الاستجابة. المخترق لا يرى ما جلبه السيرفر.
- كيف يحدث: عندما يرسل الـ API طلباً لـ Webhook لإشعار نظام آخر، ولا ينتظر عرض النتيجة للمستخدم.
- كيف يكتشفه المخترق: يضع المخترق رابطاً لسيرفر يمتلكه هو (عبر أدوات مثل Burp Collaborator أو Interactsh). إذا رأى أن سيرفره تلقى اتصالاً من IP السيرفر المستهدف، فهذا دليل على وجود الثغرة.
- استخدامه: يُستخدم غالباً لعمل "مسح للشبكة الداخلية" (Internal Port Scanning). يرسل المخترق طلبات لـ IPs داخلية مختلفة؛ فإذا كان الرد سريعاً يعني أن المنفذ مفتوح، وإذا تأخر يعني أنه مغلق، وهكذا يرسم خريطة للشبكة المخفية.
لا يقتصر الأمر على الروابط التقليدية، بل يمتد ليشمل:
- Cloud Metadata Services: وهي الخدمة الأكثر شهرة (مثل عنوان
169.254.169.254في AWS)، حيث يمكن للسيرفر جلب مفاتيح الوصول (Access Keys) والبيانات السرية للسحابة من خلالها. - Database Services: محاولة الاتصال بقواعد بيانات داخلية (مثل MongoDB أو Redis) التي غالباً ما تعمل بدون كلمة مرور لأنها "داخلية ومحمية".
- Internal Microservices: الاتصال بخدمات داخلية تقوم بعمليات حساسة (مثل خدمة إرسال الإيميلات أو خدمة الدفع).
إذا كان تطبيقك يعمل على منصات مثل AWS أو Google Cloud أو Azure، فإن الخطر الأكبر هو الوصول إلى Metadata Service.
- الأثر: يمكن للمخترق سحب "مفاتيح الوصول" (IAM Credentials) الخاصة بالسيرفر. إذا حصل عليها، يمكنه التحكم في كامل موارد السحابة، حذف قواعد البيانات، أو سرقة النسخ الاحتياطية.
- المسار الشهير: طلب العنوان
http://169.254.169.254/latest/meta-data/الذي يعيد معلومات حساسة جداً عن البيئة السحابية.
السيرفر المصاب يعمل كـ Proxy للمخترق.
- الأثر: يستطيع المخترق اكتشاف الأجهزة والخدمات الموجودة خلف جدار الحماية (مثل الطابعات، قواعد البيانات، أنظمة الموظفين الداخلية) التي لا تظهر أبداً للإنترنت. بعد اكتشافها، يمكنه محاولة اختراقها باستخدام ثغرات أخرى.
في بعض الأحيان، يدعم السيرفر بروتوكولات مثل file://.
- الأثر: بدلاً من وضع
http://في الرابط، يضع المخترقfile:///etc/passwdأو ملفات الإعدادات (Config files) التي تحتوي على كلمات مرور قاعدة البيانات. السيرفر سيقرأ الملف من القرص الصلب الخاص به ويعيده للمخترق.
الكثير من الخدمات الداخلية (مثل لوحات التحكم المصممة للموظفين فقط) لا تطلب كلمة مرور إذا كان الطلب قادماً من IP السيرفر نفسه (Trust-based auth).
- الأثر: المخترق يصل لهذه اللوحات وينفذ عمليات إدارية وكأنه "مدير النظام" الجالس خلف شاشة السيرفر.
- الأثر: إجبار السيرفر على إرسال آلاف الطلبات لخدمة داخلية ضعيفة حتى تتوقف عن العمل، مما يؤدي لتعطيل النظام بالكامل من الداخل.
ابحث في طلبات الـ API عن أي معامل (Parameter) يأخذ رابطاً (URL) أو اسماً لملف كقيمة. أمثلة شائعة:
?url=...?dest=...?path=...?uri=...?image_url=...?webhook_url=...
أبسط اختبار هو محاولة جعل السيرفر يتصل بمكان تملكه أنت.
- التجربة: استبدل الرابط الموجود في المعامل برابط لسيرفر تحت سيطرتك (أو استخدم أداة مثل
webhook.site). - النتيجة: إذا استقبل سيرفرك اتصالاً من IP السيرفر المستهدف، فهذا يعني أن السيرفر "ينفذ" الأوامر الخارجية، وهو مؤشر قوي جداً على وجود ثغرة SSRF.
حاول جعل السيرفر يتصل بنفسه (Localhost).
- التجربة: جرب إرسال هذه الروابط:
http://127.0.0.1:80http://localhost:22(لفحص منفذ الـ SSH)
- التحليل: قارن الاستجابة (Response). إذا كانت تختلف عن استجابة الروابط العادية (مثلاً تأخر في الرد أو رسالة خطأ مختلفة)، فقد يكون المنفذ مفتوحاً داخلياً.
إذا كان الموقع مستضافاً على خدمات سحابية، جرب العناوين الشهيرة الخاصة بها:
- AWS/Google Cloud:
http://169.254.169.254/latest/meta-data/ - DigitalOcean:
http://169.254.169.254/metadata/v1.json
إذا أعاد السيرفر أي معلومات عن البنية التحتية، فقد وجدت "كنزاً" في عالم الـ Bug Bounty.
المخترق الذكي لا يكتفي بـ http://. جرب:
file:///etc/passwd(لقراءة ملفات النظام).gopher://أوdict://(بروتوكولات قديمة قد تُستخدم للتفاعل مع قواعد بيانات داخلية مثل Redis).
إذا كان السيرفر يمنع كلمة "localhost" أو الـ IP "127.0.0.1"، جرب طرق الالتفاف:
- استخدام العشري:
http://2130706433/(وهو المعادل لـ 127.0.0.1). - استخدام روابط إعادة التوجيه (Redirects): ضع رابطاً لموقعك، واجعل موقعك يوجه السيرفر تلقائياً إلى الرابط الداخلي.
هذا هو الحل الأقوى والأكثر أماناً. بدلاً من محاولة منع الروابط السيئة، حدد فقط الروابط المسموح بها.
- كيف: إذا كان الـ API يحتاج جلب صور من سيرفر محدد (مثل
images.trusted.com)، فاجعل الكود يرفض أي رابط لا يبدأ بهذا العنوان. - لماذا: لأن المخترق مهما حاول استخدام IPs داخلية أو روابط Metadata، سيفشل لأنها ليست في "القائمة البيضاء".
إذا كان يجب عليك السماح بروابط من أي مكان في الإنترنت، فيجب عليك منع السيرفر من الاتصال بالشبكة الداخلية.
- ماذا تمنع:
127.0.0.1وlocalhost(النفس).- نطاقات الـ IP الخاصة مثل
10.0.0.0/8و172.16.0.0/12و192.168.0.0/16. - عناوين الـ Metadata الخاصة بالسحاب (مثل
169.254.169.254).
لا تسمح للسيرفر باستخدام بروتوكولات غير ضرورية.
- الحل: قيد الطلبات لتكون عبر
http://أوhttps://فقط. - الفائدة: هذا يغلق الباب أمام محاولات استخدام
file://لقراءة الملفات أوgopher://للتفاعل مع قواعد البيانات.
المخترقون يستخدمون إعادة التوجيه لتجاوز الفلاتر (يرسل رابطاً يبدو عادياً، ولكن عند طلبه يوجه السيرفر لعنوان داخلي).
- الحل: اجعل مكتبة الـ HTTP التي تستخدمها في السيرفر (مثل
axiosأوrequests) لا تتبع الروابط (Don't follow redirects) تلقائياً، أو قم بفحص الرابط الجديد بعد كل إعادة توجيه.
- الحل: ضع السيرفر الذي يقوم بجلب الموارد الخارجية في منطقة معزولة (DMZ) لا تملك صلاحية الوصول للشبكة الداخلية أو قواعد البيانات الحساسة.
- الفائدة: حتى لو وُجدت الثغرة، فلن يجد المخترق شيئاً ذا قيمة داخل تلك الشبكة المعزولة.
"الموقع يطلب مني رابطاً لمعاينة صورة ملفي الشخصي. ماذا لو أعطيته عنواناً داخلياً مثل http://192.168.1.1؟ إذا استغرق السيرفر وقتاً طويلاً للرد، فهذا يعني أن هناك جهازاً في هذا العنوان. سأقوم بعمل سكربت يمر على كل الـ IPs الداخلية (Internal Scanning) لأرسم خريطة كاملة للشبكة التي يظن المدير أنها آمنة."
"السيرفر مستضاف على AWS. سأحاول طلب الرابط السحري http://169.254.169.254/latest/meta-data/iam/security-credentialtials/. إذا نجح الأمر، سأحصل على Token يمنحني صلاحيات كاملة على السحابة، ويمكنني حينها إغلاق السيرفرات أو سرقة البيانات دون أن يكتشفني أحد."
"لوحة تحكم المدير (Admin Dashboard) ترفض دخولي من الخارج. لكن، ماذا لو طلبت من السيرفر جلب http://localhost/admin؟ غالباً المطور يثق في الطلبات القادمة من 'Localhost' ولا يطلب كلمة مرور. سأجعل السيرفر يفتح لي الأبواب التي أُغلقت في وجهي."
"المطور منع روابط http. حسناً، ماذا عن file:///etc/passwd؟ أو ftp://attacker.com؟ هل يمكنني استغلال بروتوكول gopher:// لإرسال أوامر مباشرة لقاعدة بيانات Redis الداخلية وحذف جميع الجلسات (Sessions)؟"
"السيرفر يمنع كلمة '127.0.0.1'. سأجرب تحويل العنوان إلى صيغة Hex أو Octal، أو سأستخدم خدمة مثل nip.io (مثلاً 127.0.0.1.nip.io). هل المطور قام بعمل الفلتر باستخدام Regex ضعيف يمكنني الالتفاف عليه؟"