میزبانی ایمن داده های کاربر در برنامه های کاربردی وب مدرن

دیوید دورکن
David Dworken

بسیاری از برنامه‌های وب نیاز به نمایش محتوای تحت کنترل کاربر دارند. این می‌تواند به سادگی نمایش تصاویر آپلود شده توسط کاربر (مثلاً عکس‌های پروفایل) یا به پیچیدگی رندر کردن HTML تحت کنترل کاربر (مثلاً یک آموزش توسعه وب) باشد. انجام ایمن این کار همیشه دشوار بوده است، بنابراین ما تلاش کرده‌ایم تا راه‌حل‌های آسان اما ایمنی پیدا کنیم که بتوان آنها را در اکثر انواع برنامه‌های وب اعمال کرد.

راهکارهای کلاسیک برای جداسازی محتوای غیرقابل اعتماد

راه حل کلاسیک برای ارائه ایمن محتوای تحت کنترل کاربر، استفاده از دامنه‌های sandbox است. ایده اصلی این است که اگر دامنه اصلی برنامه شما example.com باشد، می‌توانید تمام محتوای غیرقابل اعتماد را در exampleusercontent.com ارائه دهید. از آنجایی که این دو دامنه بین سایتی هستند، هرگونه محتوای مخرب در exampleusercontent.com نمی‌تواند example.com تحت تأثیر قرار دهد. این رویکرد می‌تواند برای ارائه ایمن انواع محتوای غیرقابل اعتماد از جمله تصاویر، دانلودها و HTML استفاده شود. اگرچه ممکن است استفاده از این روش برای تصاویر یا دانلودها ضروری به نظر نرسد، اما انجام این کار به جلوگیری از خطرات ناشی از شنود محتوا ، به ویژه در مرورگرهای قدیمی، کمک می‌کند. دامنه‌های sandbox به طور گسترده در سراسر صنعت استفاده می‌شوند و مدت زیادی است که به خوبی کار می‌کنند. اما، آنها دو جنبه منفی عمده دارند:

  • برنامه‌ها اغلب نیاز دارند دسترسی به محتوا را به یک کاربر محدود کنند، که مستلزم پیاده‌سازی احراز هویت و مجوز است. از آنجایی که دامنه‌های sandbox عمداً کوکی‌ها را با دامنه اصلی برنامه به اشتراک نمی‌گذارند، انجام این کار به صورت ایمن بسیار دشوار است. برای پشتیبانی از احراز هویت، سایت‌ها یا باید به URLهای قابلیت تکیه کنند، یا باید کوکی‌های احراز هویت جداگانه‌ای را برای دامنه sandbox تنظیم کنند. این روش دوم به ویژه در وب مدرن که بسیاری از مرورگرها به طور پیش‌فرض کوکی‌های بین سایتی را محدود می‌کنند، مشکل‌ساز است.
  • اگرچه محتوای کاربر از سایت اصلی جدا شده است، اما از سایر محتوای کاربر جدا نشده است. این امر خطر حمله محتوای مخرب کاربر به سایر داده‌ها در دامنه سندباکس را ایجاد می‌کند (برای مثال، با خواندن داده‌های با مبدا یکسان).

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

راهکارهای مدرن برای ارائه محتوای کاربر

با گذشت زمان، وب تکامل یافته و اکنون روش‌های آسان‌تر و امن‌تری برای ارائه محتوای غیرقابل اعتماد وجود دارد. در اینجا رویکردهای مختلفی وجود دارد، بنابراین ما دو راه‌حل را که در گوگل استفاده می‌کنیم، شرح خواهیم داد.

رویکرد ۱: ارائه محتوای غیرفعال به کاربران

اگر سایتی فقط نیاز به ارائه محتوای غیرفعال کاربر (یعنی محتوایی که HTML یا جاوا اسکریپت نیست، مانند تصاویر و دانلودها) داشته باشد، اکنون می‌توان این کار را با خیال راحت و بدون یک دامنه ایزوله سندباکس انجام داد. دو مرحله کلیدی وجود دارد:

  • همیشه هدر Content-Type را روی یک نوع MIME شناخته شده که توسط همه مرورگرها پشتیبانی می‌شود و حاوی محتوای فعال نیست، تنظیم کنید. در صورت شک، application/octet-stream انتخاب مطمئنی است.
  • علاوه بر این، همیشه هدرهای پاسخ را تنظیم کنید تا مطمئن شوید که مرورگر پاسخ را به طور کامل ایزوله می‌کند.
هدر پاسخ هدف

X-Content-Type-Options: nosniff

از شنود محتوا جلوگیری می‌کند

Content-Disposition: attachment; filename="download"

به جای رندر کردن، دانلود را آغاز می‌کند

Content-Security-Policy: sandbox

محتوا را طوری در سندباکس قرار می‌دهد که انگار روی یک دامنه جداگانه ارائه شده است

Content-Security-Policy: default-src ‘none'

اجرای جاوا اسکریپت (و گنجاندن هرگونه زیرمنبع) را غیرفعال می‌کند

Cross-Origin-Resource-Policy: same-site

از درج صفحه به صورت بین سایتی جلوگیری می‌کند

این ترکیب هدرها تضمین می‌کند که پاسخ فقط می‌تواند به عنوان یک زیرمنبع توسط برنامه شما بارگیری شود، یا به عنوان یک فایل توسط کاربر دانلود شود. علاوه بر این، هدرها از طریق هدر CSP sandbox و محدودیت default-src ، چندین لایه محافظت در برابر اشکالات مرورگر ارائه می‌دهند. به طور کلی، تنظیمات ذکر شده، درجه بالایی از اطمینان را فراهم می‌کند که پاسخ‌های ارائه شده به این روش نمی‌توانند منجر به آسیب‌پذیری‌های تزریق یا جداسازی شوند.

دفاع در عمق

اگرچه راهکار پیشنهادی، دفاعی عموماً کافی در برابر XSS ارائه می‌دهد، اما تعدادی اقدامات امنیتی اضافی نیز وجود دارد که می‌توانید برای ایجاد لایه‌های امنیتی بیشتر اعمال کنید:

  • برای سازگاری با IE11، یک هدر X-Content-Security-Policy: sandbox تنظیم کنید.
  • برای جلوگیری از جاسازی نقطه پایانی، هدر Content-Security-Policy: frame-ancestors 'none' تنظیم کنید.
  • محتوای کاربر در محیط سندباکس روی یک زیردامنه ایزوله توسط:
    • ارائه محتوای کاربر در یک زیردامنه مجزا (مثلاً گوگل از دامنه‌هایی مانند product.usercontent.google.com استفاده می‌کند).
    • برای فعال کردن جداسازی بین مبدایی، Cross-Origin-Opener-Policy: same-origin و Cross-Origin-Embedder-Policy: require-corp تنظیم کنید.

رویکرد ۲: ارائه محتوای فعال به کاربران

ارائه ایمن محتوای فعال (به عنوان مثال، تصاویر HTML یا SVG) نیز می‌تواند بدون نقاط ضعف رویکرد دامنه سندباکس کلاسیک انجام شود.

ساده‌ترین گزینه، استفاده از هدر Content-Security-Policy: sandbox است تا به مرورگر بگوید پاسخ را ایزوله کند. اگرچه همه مرورگرهای وب، ایزوله‌سازی فرآیند را برای اسناد sandbox پیاده‌سازی نمی‌کنند، اما اصلاحات مداوم در مدل‌های فرآیند مرورگر احتمالاً جداسازی محتوای sandbox شده از برنامه‌های جاسازی را بهبود می‌بخشد. اگر SpectreJS و حملات رندرکننده خارج از مدل تهدید شما باشند، استفاده از CSP sandbox احتمالاً یک راه حل کافی است. در گوگل، ما راه حلی را توسعه داده‌ایم که می‌تواند با مدرن‌سازی مفهوم دامنه‌های sandbox، محتوای فعال غیرقابل اعتماد را به طور کامل ایزوله کند. ایده اصلی این است که:

  • یک دامنه sandbox جدید ایجاد کنید که به لیست پسوندهای عمومی اضافه شود. برای مثال، با اضافه کردن exampleusercontent.com به PSL، می‌توانید مطمئن شوید که foo.exampleusercontent.com و bar.exampleusercontent.com بین سایتی هستند و بنابراین کاملاً از یکدیگر جدا هستند.
  • URLهایی که با *.exampleusercontent.com/shim مطابقت دارند، همگی به یک فایل shim استاتیک هدایت می‌شوند. این فایل shim شامل یک قطعه کد کوتاه HTML و جاوا اسکریپت است که به رویداد مدیریت message گوش می‌دهد و هر محتوایی را که دریافت می‌کند، رندر می‌کند.
  • برای استفاده از این، محصول یک iframe یا یک کادر محاوره‌ای به آدرس $RANDOM_VALUE.exampleusercontent.com/shim ایجاد می‌کند و از postMessage برای ارسال محتوای غیرقابل اعتماد به shim جهت رندر شدن استفاده می‌کند.
  • محتوای رندر شده به یک Blob تبدیل شده و درون یک iframe که در حالت sandbox قرار دارد رندر می‌شود.

در مقایسه با رویکرد دامنه سندباکس کلاسیک، این تضمین می‌کند که تمام محتوا به طور کامل در یک سایت منحصر به فرد ایزوله شده است. و با داشتن برنامه اصلی که با بازیابی داده‌هایی که باید رندر شوند سروکار دارد، دیگر نیازی به استفاده از URLهای قابلیت نیست.

نتیجه‌گیری

این دو راهکار در کنار هم، مهاجرت از دامنه‌های سندباکس کلاسیک مانند googleusercontent.com به راه‌حل‌های امن‌تری که با مسدود کردن کوکی‌های شخص ثالث سازگار هستند را امکان‌پذیر می‌کنند. در گوگل، ما تاکنون بسیاری از محصولات را برای استفاده از این راه‌حل‌ها منتقل کرده‌ایم و مهاجرت‌های بیشتری را برای سال آینده برنامه‌ریزی کرده‌ایم.