نگاره‌هایی پیرامون امنیت، شبکه و رمزنگاری

23 نوامبر 2021

استفاده از CDN یکی از رایج‌ترین فرآیندها برای بسیار از وب‌سایت‌های بزرگ و کوچک می‌باشد. علت استفاده از این سرویس نیز می‌تواند اهداف مختلفی داشته باشد، بهبود در SEO و ایجاد امنیت برخی از این دلایل می‌تواند باشد. البته برخی شرکت‌ها که رتبه آن‌ها در Search Engineها زیاد الویت ندارد (برای مثال سایت‌های دولتی) و هدف اصلی امنیت می‌باشد. در اینجا عماد به طور کاملا جامع یکی از رایج‌ترین حملات به وب‌سایت‌هایی که از CDN استفاده می‌کنند را توضیح داده است. اگر پس از مطالعه سوالی در ارتباط با این موضوع وجود داشت حتما مطرح کنید.

در این جا هم به صورت مختصر نحوه کار CDN‌ها به طور عمومی رو توضیح میدیم.

همان‌طور که در شکل میبینید، CDN در واقع اولین نقطه برای ورود کاربر به یک وب‌سایت است که وظایف متفاوتی مانند Cache کردن محتوا ثابت و ایجاد امنیت را بر عهده دارد. در این جا به بررسی بعُد امنیتی که CDN ایجاد می‌کند می‌پردازیم. CDNها در واقع آدرس‌های IP اصلی وب‌سایت‌ها رو مخفی می‌کنند و این باعث امن شدن بیشتر در مقابله برخی از حملات مثل DDoS و … شود، همچنین ابزارهای تیم امنیت وب‌سایت مورد نظر نیز برای مقابله در مقابل انواع حملات بیشتر می‌شود.

خب،فکر می‌کنم تا الان متوجه شده باشیم که چرا به طور کلی باید از CDN استفاده کنیم و این تفاوتی ندارد که CDN ایرانی باشد یا خارجی. چون علاوه بر مواردی که برای بهبود سرعت است مواردی امنیتی زیر را هم ایجاد می‌کند.
– مخفی کردن آدرس‌ IP یا آدرس‌های IP وب سایت (برای مقابله با حملات DoS و DDoS در لایه سه شبکه)

  • Rate Limit
  • WAF
  • DOS Protection (Layer 7)

وقتی که یک سایتی پشت سرور‌های CDN قرار می‌گیرد در صورتی که آدرس دامنه آن را PING کنیم آدرس سرور‌های CDN نمایش داده می‌شود. و این سایت می‌تواند در صورت نیاز از تمامی خدمات CDN استفاده کند. برای درک کامل شکل زیر بررسی شود، این شکل یک شماتیک عمومی استفاده از CDNها و ساختار شبکه وب‌سایت مورد نظر است.

خب حالا به این شرایط فکر کنیم که برای این وب‌سایتی که از CDN استفاده می‌کند، از موارد امنیتی CDN برای مثلا موارد زیر فعال کرده است که نقش اساسی بر روی امنیت وب‌سایت دارد.

  • Rate Limit
  • WAF
  • Firewall Protection
  • DDoS Protection

حالا اگر این CDN دور بخورد یا به طور صحیح‌تر Bypass شود همه این موارد غیر فعال می‌شود و وضعیت زیاد مناسب نیست!!

برای این که امکان Bypass کردن CDN به احتمال بسیار زیادی وجود دارد باید امن‌سازی‌هایی انجام شود تا در صورتی که این Bypass انجام گرفت کمترین نشر اطلاعات ایجاد شود.

در گام اول باید سرویس‌های Edge فقط به درخواست‌هایی که از طریق سرور‌های CDN ارسال می‌شود پاسخ دهند یا به عبارت دیگه اگر وب‌سرور یا Reverse Proxy شما روی Edge شبکه نیست به صورت لایه سه محدودیت آدرس IP فعال شود. اگر وب‌سرور یا Reverse Proxy روی Edge دارید محدودیت بر روی آن‌ها فعال شود و این مقاله برای وب‌سایت‌هایی است که وب‌سرور یا Reverse Proxy آن ها در لایه Edge قرار دارد.

خب با این کار تا حد بسیار زیادی مشکلات Bypass کردن برطرف می‌شود (یعنی در واقع مشکل Bypass کردن برطرف نمی‌شود، درخواست‌هایی که از آدرس‌های IP به جز رنج CDN باشد Drop می‌شود) ولی دلایل زیادی از نظر کسب‌وکار‌ها وجود دارد تا این محدودسازی انجام نمی‌شود برخی از این دلایل به شرح زیر است:

  1. در صورتی که مشکلی برای سرویس CDN ایجاد شود وب‌سایت مورد نظر از دسترس خارج می‌شود پس باید این قابلیت وجود داشته باشد تا در سریع‌ترین زمان از پشت CDN خارج شویم.
  2. محدودیت‌های فنی (استفاده از یک آدرس IP به صورت مشترک برای بیش از یک سرویس)
  3. محدودیت‌های مالی برای خرید تجهیزات شبکه‌-امنیتی و استفاده از تجهیزات مشترک

پس می‌توانیم این نتیجه‌گیری رو داشته باشیم که اگر تجهیزات امنیتی به صورت اختصاصی داریم با ایجاد محدودیت در لایه سه و استفاده از یک آدرس IP برای وب‌سایت این مشکل به طور کلی به وجود نمی‌آید.

حالا فرض کنیم که به این شکل نیست که این مورد بسیار زیاد است. روی Edge امکان محدودسازی لایه سه وجود ندارد. سناریو به این شکل است که ما یک آدرس IP داریم و سرویس‌های متفاوتی مثل وب‌سایت و L2TP روی آن داریم. امن‌سازی یکم پیچیده‌تر میشود پس با هم گام به گام پیش میریم:

محدودسازی وب‌سایت

برای محدودسازی در این مرحله باید وب‌سرور ما فقط به درخواست‌هایی که از طریق CDN ارسال می‌شود پاسخ دهد. این محدودسازی می‌تواند در لایه Firewall سیستم‌عامل یا خود وب‌سرور انجام شود . در این جا ما فرض رو بر این میگیریم که محدودسازی بر روی وب‌سرور انجام شود در این جا وب‌سرور مورد نظر NGINX است. علت این که محدودسازی در لایه OS را انجام نمی‌دهیم به این دلیل است که در واقع همان محدودسازی در لایه سه اتفاق می‌افتد.

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    allow 2001:0db8::/32;
    deny  all;
}

با این کار محدودسازی برای ارسال درخواست خارج از طریق CDN امکان‌پذیر نیست ولی این نوع کانفیگ هم نقاط مثبت و هم نقاط منفی دارد:

نکات +

  • این امکان رو داریم که بر روی هر وب‌سایت روی یک وب‌سرور مشترک یک Trust list مجزا داشته باشیم.
  • در صورت اشتباه در یک Trust list تمام سرویس‌ها تحت تاثیر قرار نمی‌گیرند

نکات منفی –

  • درصورتی که رنج CDN تغییر کند باید تمامی لیست‌هایی که از این رنج استفاده کردند بروز شوند
  • در صورتی که از Certificate استفاده شود امکان شناسایی آدرس IP وجود دارد.(باید محدودسازی برای این قسمت نیز انجام شود)
  • مدیریت سخت

در بین تمام نقاط مثبت و منفی یکی از موارد جزو مواردی است که می‌تواند از نظر امنیتی برای کسب‌وکار مشکل‌ساز شود و این مورد شناسایی از طریق Certificate است. اگر بخوام به ساده‌ترین حالت ممکن توضیح بدم به این صورت است که اگر هکر یک درخواست HTTPS به آدرس IP وب سایت ارسال کند Certificate نمایش داده می‌شود حتی در صورتی که 403 دریافت کند.

برای رفع این مشکل دو راه وجود دارد که به شخصه راه دوم رو بیشتر دوست دارم.

  1. فقط درخواست‌هایی که دارای هاست هدر مشخصی است پاسخ داده شود.
  2. نمایش Certificate اشتباه

علت پیشنهاد به نمایش نام یک Certificate اشتباه و غیر Valid این است که بسیاری از هکرها وقتی با ابزار یا به صورت دستی شروع به اسکن می‌کنند فقط به نام Certificate که بر می‌گردد دقت می‌کنند و بر روی نام Certificate جستجو را انجام می‌دهند. اگر آدرس شما هیچ موردی رو برنگرداند ممکن است اسکن برروی آن ادامه داشته باشد. ابزار‌های پیچیده و مخصوصی نیز برای این کار وجود ندارد با nmap نیز امکان شناسایی نام Certificate که بر روی آدرسIP است وجود دارد.

برای این که بتونیم Certificate اشتباده نمایش بدیم نیاز داریم که یک Certificate داشته باشیم، این کار شاید در لحظه اول نشدنی یا دور از منطق باشد، چون باید یک Certificate خریداری شود (تا ROOT Certificate آن در تمامی OSها وجود داشته باشد)و … ولی سوالی که اینجا وجود دارد این است که حتما باید Certificate ما Valid باشد؟! و جواب این سوال خیر است، پس یا CA سرور راهندازی می‌کنیم (که من این کار رو نمی‌کنم) و Certificate رو با اسم دلخواه صادر می‌کنیم یا سری به سایت selfsignedcertificate میزنیم و Certificate دلخواهمون رو صادر می‌کنیم (Certificate‌های صادر شده در این سایت Valid نمی‌باشد). بعد از این کار باید Certificate رو بر روی وب‌سرور خودمون کانفیگ کنیم. وب‌سرور ما NGINX است.

server {
 listen 80;
 server_name {{YOUR SERVER IP}};
 allow {{LIST OF CDN IP ADDRESSES}}; 
 deny all; #DenyEveryThing
 return 301 https://$host$request_uri;
}

server {
 listen 443 ssl ;
 server_name {{YOUR SERVER IP}};
 ssl_certificate /etc/ssl/certs/{{CERTIFICATE NAME}}.crt;
 ssl_certificate_key /etc/ssl/certs/{{CERTIFICATE NAME}}.key;
 allow {{LIST OF CDN IP ADDRESSES}}; 
 deny all; #DenyEveryThing

    location / {
        proxy_pass https://facebook.com;
}
}

با توجه به کانفیگ فایل بالا ما تمامی درخواست‌هایی که به پورت 80 ارسال می‌شود را 301 انجام می‌دهیم و به 443 تبدیل می‌کنیم. در قسمت 443، Certificate و Key که از سایت selfsignedcertificate دریافت کردیم وارد می‌کنیم. در پایان باید لیست آدرس‌های CDN به صورت Trust وارد شود و یک Reverse نیز فقط برای احتیاط زده می‌شود. حالا اگر اسکنی بر روی این آدرس انجام شود یا حتی بر روی مرورگر این آدرس باز شود و Certificate آن رو بررسی کنیم نام Certificate نامی است که شما آن را وارد کردید.

وقتی تمام این کار‌ها انجام شود امکان شناسایی آدرس IP شما وجود ندارد، فقط در صورتی که یک Config اشتباه انجام داده باشیم. اگر به صورت خلاصه این موضوع رو بررسی کنیم باید مراحل زیر طی شود:

  • محدود کردن وب‌سایت مورد نظر و دریافت ترافیک فقط از طریق سرورها CDN
  • دریافت یک Certificate و ست کردن آن بر روی وب‌سرور یا Reverse Proxy
  • بررسی منظم آدرس‌های IP برای عدم نمایش نام دامنه واقعی بر اساس آدرس IP (با یک Script قابل اجرا است)

تمامی این مواردی که در این مقاله به آن اشاره شد بر اساس تجربیات و تحقیقات من بوده و امکان آن وجود دارد راه‌حل‌هایی با کارایی بهتر نیز وجود داشته باشد. در صورتی که راه حل یا سوالی در این خصوص وجود داشت در توییتر میتونیم با هم صحبت کنیم.

ممنون که این مقاله رو مطالعه کردید.

3 پست نوشته شده
  • به اشتراک بگذارید:
برچسب‌ها: ،
  1. سجاد گفت:

    سلام و عرض ادب.
    برای تهیه این مطلب . انتشار این مطلب بسیار از شما سپاسگزارم.
    یک سوال در مورد نمایش Certificate غیر معتبر است.
    نکته اول چرا باید Certificate غیر معتبر معتبر استفاده کنیم؟ به صورت طبیعی میتونیم از یک Certificate معتبر استفاده کنیم. این کار رو میتونیم توسط Lets encrypt انجام بدیم.
    نکته بعدی: اگر هم نیازی به استفاده از Lets encrypt نباشد میتونیم از Self signed تولید شده توسط open SSLاستفاده کنیم.
    نکته اخر در Certificate تولید چه داده ای وجود داره که ممکنه خطر ساز باشه؟
    چون اگر Certificate‌های یک سایت رو دقت کنید اطلاعاتی مانند common name ،Signature Algorithm و …در دسترسه که چیز حساسی به نظر نمیاد.

    • vahaggn گفت:

      با سلام، ممنون که مطالعه کردید
      در این جا معتبر بودن یا نبوده Certificate برای مخفی کردن آدرس IP ما مهم نیست .در این سناریو ما دو تا Certificate داریم
      Certificate شماره یک: این Certificate برای استفاده عمومی سایت اصلی ما است که باید معتبر باشد (منظور از معتبر بودن یعنی Root Certificate صادر کننده در تمام مرورگر ها وجود داشته باشد)
      Certificate شماره دو(Certificate مورد بحث ما): از این Certificate برای مخفی کردن آدرس IP استفاده می کنیم که معتبر بودن یا نبوده ،صادر کننده ، نحوه صدور ، تاریخ انقضاء و … مهم نیست. فقط و فقط نام دامنه ای که این Certificate برای آن صادر شده است مهم است که باید دامنه‌ای به جز دامنه اصلی ما باشد. برای مثال برای دامنه memoryleaks.ir میتونیم از دامنه facebook.com یا هر دامنه دیگه که دوست داریم استفاده کنیم چون هدف مخفی کردن آدرس IP است
      صادر کننده Certificate مهم نیست چه به صورت Self signed یا خریداری شده یا رایگان
      در Certificate به طور کلی اطلاعات حساسی وجود ندارد فقط نام دامنه ای که برای آن صادر شده است مهم است که باید مخفی باشد.
      امیدوارم تونسته باشم جواب سوالات رو داده باشم اگر نکته‌ای هنوز گنگ هست حتما مطرح کنید

  2. این cert که بر میگرده در زمان درخواست به ای پی سرور پشت cdn معمولا در nginx همان default_server است که میتونیم یه دومین الکی تنظیم کنیم
    listen 443 ssl default_server;

    • vahaggn گفت:

      سلام ممنون که مطالعه کردید و ببخشید که دیر جواب میدم. بله فرمایش شما کاملا درست است ولی چند تا نکته وجود داره. بهتر به صورت کلی default_server غیرفعال بشه و نکته دوم شما با این روش همیشه میتونید مدیریت جداگانه برای درخواست های ارسال شده به آدرس IP داشته باشید