سلام، SSRF یکی از باگهایی است که این روزها یقه خیلی از سایت های بزرگ را می گیره. هرچند جدید نیست ولی خب هست دیگه. مشکل از اونجا نشأت می گیره که کنترل منابع خارجی که سایت از اونها استفاده می کنه خوب انجام نمیشه. در ادامه یکم در مورد این باگ، نحوه پیدا کردنش و اینکه چطوری میشه از طریق اون به داخل شبکه Pivot شد، می نویسم.
این SSRF مخفف Server Side Request Forgery هست و به نفوذگر اجازه ارسال درخواست های با امضاهای جعلی به سمت یه سرور آسیب پذیر میده و خب چون اون سرور آسیب پذیره این درخواست ها معتبر شناخته میشن و به عنوان یه نود معتبر توی شبکه معرفی میشه. از این طریق کنترل های فایروال دور خورده و نفوذگر به سرویس های داخل شبکه دست پیدا می کنه.
تصور کنید یه وب سرور عمومی توی شبکه یه شرکت به آدرس زیر هست:
public.example.com
این آدرس یه سرویس پراکسی را توی public.example.com/proxy هاست می کنه که صفحات وبی که در پارامتر url مشخص شدند را پردازش و به کاربر نمایش میده. تصور کنید کاربر درخواست زیر را میده
https://public.example.com/proxy?url=google.com
اون وب اپلیکشن، صفحه گوگل را نمایش میده
حالا تصور کنید admin_panel.example.com یه سرور داخلیه که یه پنل مخفی ادمین را هاست می کنه. واسه اینکه مطمئن بشن فقط کارمندا می تونن به این صفحه دسترسی داشته باشند، Access control طوری تنظیم شده که از بیرون و عملاً اینترنت کسی به اون دسترسی نداشته باشه و فقط کسایی به اون دسترسی پیدا کنن که یه IP معتبر داخلی داشته باشن (مثلاً یکی از workstation های کارمندا). حالا اگه یه کاربر تقاضای زیر را بده چی میشه؟
https://public.example.com/proxy?url=admin_panel.example.com
اگر مکانسیم کنترل SSRF نداشته باشند، خب چون درخواست از Public.examaple.com میاد و یک ماشین معتبر داخل شبکه هست، صفحه کنترل پنل ادمین به کاربر نمایش داده میشه. درواقع درخواست های نامعتبر که در حالت عادی توسط فایروال بلاک می شدند، الان دارن اجرا می شن!
این به این دلیل که اون محافظتی که روی شبکه DMZ یا همون Perimeter برای کنترل بین سرورهایی مثل وب سرور و ماشین های داخلیمون ست شده، بین ماشین های روی شبکه Trusted مون (مثلاً بین public.example.com و admin_panel.example.com ) وجود نداره.
حالا با استفاده از این وضعیت، یه نفوذگر می تونه هر نوع درخواست که دلش بخواد را روی شبکه ارسال کنه و بسته به اینکه اون سروره چه دسترسیهایی داره، یه نفوذگر می تونه فایلهای حساس داخل شبکه را بخونه یا مثلاً API های داخلی را صدا بزنه و یا مثل این حالتی که توضیح دادم به کنترل پنل های مخفی مدیرا دست پیدا کنه.جالب شد، نه؟!
خب 2 نوع SSRF داریم: به اولی میگن Regular SSRF یا همون SSRF معمولی و دومی هم مثل خیلی از باگ های دیگه Blind SSRF. مکانیسمهای پشت هردوی این نوع آسیبپذیری یه چیزه و عملاً اعتماد بین ماشین های روی یک شبکه را مورد هدف قرار میدن و exploit می کنن. تنها تفاوتی که بین این دوتا هست اینه که توی Blind نفوذگر بازخوردی از سمت سرور به وسیله درخواست های HTTP یا error message ها دریافت نمی کنه (مثل اون بالا که نفوذگر صفحه وب درخواستیش را می دید). هرچند این موضوع کمی استخراج دادهها و exploit کردن شبکه را سخت تر می کنه اما با این حال خیلی برای یک نفوذگر با ارزشه.
بهترین راه پیدا کردن این نوع آسیب پذیریها اینه که به صورت دستی code review کنیم و ببینیم تمامی ورودی های URL درست و درمون اعتبارسنجی میشن یا نه؟ ولی خب مشخصه که همیشه نمیتونیم این کار را کنیم و دسترسی کامل به کد نداریم، بنابراین باید تمرکز را گذاشت روی ویژگی هایی که قیافهاشون به SSRF می خوره.
همونطور که گفتم، SSRF وقتی اتفاق می افته که یه سرور به منابع خارجی نیاز داشته باشه. به طور مثال، بعضی وقتا یک وب اپلیکشن نیاز داره تا از روی URL یه عکس، thumbnail (همون عکس کوچولوها) درست کنه یا مثلاً نیاز داره تا از روی یه ویدیوئه سایت دیگه یه Screen shot داشته باشه (مثلاً youtube.com یا aparat.com). اگر سرور دسترسی به منابع داخلیشو درست محدود نکرده باشه، SSRF اتفاق می افته.
فک کنیم صفحه زیر که روی public.example.com هست به کاربرا اجازه بده تا عکسشونو از طریق اینترنت آپلود کنند
https://public.example.com/upload_profile_from_url.php?url=www.google.com/test.jpeg
واسه اینکه بخواد test.jpeg را پردازش کنه اول باید بره سراغ محتویات google.com و اونها را بخونه. اگر سرور تفاوتی بین منابع داخلی و خارجیش قائل نشده باشه، یه نفوذگر به راحتی می تونه درخواست زیر را بده:
https://public.example.com/upload_profile_from_url.php?url=localhost/password_file.txt
و خب همونطور که از اسم فایله معلومه می تونه کاری کنه که وب سرور فایل محتویات پسوردها را بهش نشون بده.
ویژگی هایی که معمولاً نسبت به SSRF آسیبپذیر هستند عبارتند از: webhook ها، فایل آپلودها بوسیله URL، پردازشگرهای اسناد و تصاویر، link expansion ها و سرویس های پراکسی! در واقع همه این ویژگی ها نیاز دارن تا منابع خارجی را دیده و پردازش کنن.
تست کردن SSRF معمولاً با آماده کردن ورودی URL با یه آدرس داخلی شروع میشه. حالا بسته به config شبکه ممکنه نیاز باشه چندین سرور مختلف تست بشن. مثلاً آدرس های زیر همون اول تست میشن:
یا مثلا میشه از این لینک بقیه آدرسها استفاده کرد.
توی مواقع SSRF عادی بررسی کنید ببینید سرور اطلاعاتی را به شما برمی گردونه که اطلاعاتی از شبکه داخلی را نمایش بده؟ اون پاسخه که میگیرید حاوی بنر سرویسهای داخلی یا محتویات HTML یه صفحه داخلی هست یا نه؟
برای مثال وقتی درخواست زیر را میدیم
https://public.example.com/upload_profile_from_url.php?url=127.0.0.1:22
سرور این جواب را میده؟
Error: cannot upload image: SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.4
توی مواقعی که Blind SSRF تست می کنیم، بررسی کنید ببینید تفاوتی بین رفتار سرور به پورت های معمول باز و بسته هست یا نه؟ (مثلاً پورت 80 و 443 معمولاً بازن درحالی که 11 بسته است). خصوصاً به Response Time و HTTP Response Code ها دقت کنید.
به طور مثال، نتیجه درخواست زیر یه Status Code 200 هست که خب میدونم 200 یعنی اوکی:
https://public.example.com/webhook?url=127.0.0.1:80
درحالی که Status Codeی که از درخواست زیر می گیریم 500 هست و خب 500 هم یعنی Internal Server Error:
https://public.example.com/webhook?url=127.0.0.1:11
وقتی این رفتار را از سرور می بینیم می تونیم بگیم که SSRF وجود داره و عملاً پورت 80 بازه و 11 بسته روی اون سرور بسته است.
توی این لینک هم می تونید پورت ها و سرویس هایی که بهشون نسبت داده شدند را ببینید.
توی این لینک می تونید یه SSRF باحال که اردیبهشت 97 از Shopify گرفته شده و 25000 دلار بانتی گرفته را ببینید
https://hackerone.com/reports/341876
توی مقاله بعدی سعی می کنم در مورد انواع SSRF و کارهایی که میشه با اون روی یه شبکه انجام بدید، صحبت کنم.