אירוח מאובטח של נתוני משתמשים באפליקציות אינטרנט מודרניות

David Dworken
David Dworken

אפליקציות אינטרנט רבות צריכות להציג תוכן שנמצא בשליטת המשתמש. זה יכול להיות פשוט כמו הצגת תמונות שהועלו על ידי משתמשים (לדוגמה, תמונות פרופיל), או מורכב כמו עיבוד HTML בשליטת המשתמש (לדוגמה, מדריך לפיתוח אתרים). מאז ומתמיד היה קשה לבצע זאת בצורה מאובטחת, לכן עבדנו כדי למצוא פתרונות קלים אך מאובטחים שאפשר להחיל על רוב הסוגים של אפליקציות אינטרנט.

פתרונות קלאסיים לבידוד של תוכן לא מהימן

הפתרון הקלאסי להצגה מאובטחת של תוכן שנמצא בשליטת המשתמשים הוא להשתמש בדומיינים של ארגז חול. הרעיון הבסיסי הוא שאם הדומיין הראשי של האפליקציה הוא example.com, אפשר להציג את כל התוכן הלא מהימן ב-exampleusercontent.com. מכיוון ששני הדומיינים האלה הם אתרים שונים, תוכן זדוני ב-exampleusercontent.com לא יכול להשפיע על example.com.
אפשר להשתמש בגישה הזו כדי להציג באופן בטוח כל מיני סוגים של תוכן לא מהימן, כולל תמונות, הורדות ו-HTML. לא נראה שצריך להשתמש בתכונה הזו לצורך תמונות או הורדות, אבל הפעולה הזו מונעת סיכונים שנובעים מהחיפוש של תוכן, במיוחד בדפדפנים מדור קודם.
דומיינים של ארגז חול (Sandbox) נמצאים בשימוש נרחב בתחום, והם פועלים היטב במשך זמן רב. אבל יש להן שני חסרונות עיקריים:

  • לעתים קרובות יישומים צריכים להגביל את הגישה לתוכן למשתמש יחיד. לשם כך נדרשים הטמעת אימות והרשאה. מאחר שדומיינים של Sandbox לא משתפים בכוונה קובצי cookie עם הדומיין הראשי של היישום, קשה מאוד לעשות זאת באופן מאובטח. כדי לתמוך באימות, אתרים צריכים להסתמך על כתובות URL עם יכולות או להגדיר קובצי cookie נפרדים לאימות לדומיין ה-Sandbox. השיטה השנייה הזו בעייתית במיוחד באינטרנט המודרני, שבו דפדפנים רבים מגבילים קובצי cookie בין אתרים כברירת מחדל.
  • תוכן המשתמשים מבודד מהאתר הראשי, אבל הוא לא מבודד מתוכן של משתמשים אחרים. הפעולה הזו יוצרת את הסיכון לכך שתוכן זדוני של משתמשים יתקוף נתונים אחרים בדומיין של Sandbox (לדוגמה, על ידי קריאה של נתונים מאותו מקור).

חשוב גם לציין שדומיינים של Sandbox עוזרים לצמצם את סיכוני הפישינג, מאחר שהמשאבים פרוסים באופן ברור בדומיין מבודד.

פתרונות מודרניים להצגת תוכן של משתמשים

עם הזמן האינטרנט התפתח, ויש דרכים קלות ומאובטחות יותר להציג תוכן שאינו מהימן. יש כאן גישות רבות, ולכן מתוארות שני פתרונות שנמצאים כרגע בשימוש נרחב ב-Google.

גישה 1: הצגת תוכן לא פעיל של משתמשים

אם אתר צריך להציג רק תוכן לא פעיל של משתמשים (כלומר תוכן שאינו HTML או JavaScript, למשל תמונות והורדות), כעת ניתן לעשות זאת בבטחה ללא דומיין ארגז חול מבודד. יש שני שלבים עיקריים:

  • תמיד להגדיר את הכותרת 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'

ההגדרה משביתה את ההפעלה של JavaScript (וההכללה של משאבי משנה)

Cross-Origin-Resource-Policy: same-site

מניעת הכללה של הדף בין אתרים

השילוב של הכותרות הזה מבטיח שהתגובה תיטען כמשאב משנה רק על ידי האפליקציה שלכם, או שתוריד את התגובה כקובץ על ידי המשתמש. בנוסף, הכותרות מספקות כמה שכבות הגנה מפני באגים בדפדפן דרך כותרת ה-Sandbox של CSP וההגבלה default-src. באופן כללי, ההגדרה שפורטה למעלה מספקת ביטחון גבוה שהתגובות שמוצגות כך לא יכולות להוביל לנקודות חולשה של הזרקה או בידוד.

מבט מעמיק על ההגנה

למרות שהפתרון שלמעלה מייצג הגנה מספקת מפני XSS, יש מספר אמצעי הקשחה נוספים שתוכלו ליישם כדי לספק שכבות אבטחה נוספות:

  • צריך להגדיר את הכותרת X-Content-Security-Policy: sandbox לתאימות עם IE11.
  • צריך להגדיר את הכותרת Content-Security-Policy: frame-ancestors 'none' כדי לחסום את ההטמעה של נקודת הקצה.
  • תוכן של משתמשי Sandbox בתת-דומיין מבודד על ידי:
    • הצגת תוכן של משתמשים בתת-דומיין מבודד (למשל, Google משתמשת בדומיינים כגון product.usercontent.google.com).
    • צריך להגדיר את Cross-Origin-Opener-Policy: same-origin ואת Cross-Origin-Embedder-Policy: require-corp כדי להפעיל בידוד בין מקורות.

גישה שנייה: הצגת תוכן פעיל של משתמשים

ניתן להציג באופן בטוח תוכן פעיל (לדוגמה, תמונות HTML או SVG) גם ללא נקודות החולשה של גישת הדומיין הקלאסית של Sandbox.
האפשרות הפשוטה ביותר היא לנצל את הכותרת Content-Security-Policy: sandbox כדי להורות לדפדפן לבודד את התגובה. לא כל דפדפני האינטרנט מטמיעים כרגע בידוד של תהליך עבור מסמכי ארגז חול, אבל חידודים מתמשכים במודלים של עיבוד דפדפן צפויים לשפר את ההפרדה בין תוכן שנמצא בארגז חול לבין הטמעת אפליקציות. אם התקפות SpectreJS ופריצה של renderer הן מחוץ למודל האיום, השימוש ב-Sandbox של CSP הוא כנראה פתרון מספק.
ב-Google פיתחנו פתרון שיכול לבודד באופן מלא תוכן פעיל לא מהימן על ידי מודרניזציה של המושג 'דומיינים של ארגז חול' (Sandbox). הרעיון המרכזי הוא:

  • יוצרים דומיין Sandbox חדש שיתווסף לרשימת הסיומות הציבוריות. לדוגמה, אם מוסיפים exampleusercontent.com ל-PSL, אפשר להבטיח ש-foo.exampleusercontent.com ו-bar.exampleusercontent.com נמצאים באתרים שונים ומבודדים באופן מלא זה מזה.
  • כתובות URL שתואמות ל-*.exampleusercontent.com/shim ינותבו לקובץ shim סטטי. קובץ shim מכיל קטע קוד קצר של HTML ו-JavaScript. הוא מאזין ל-handler של האירועים של message ומעבד כל תוכן שהוא מקבל.
  • כדי להשתמש בתכונה הזו, המוצר יוצר iframe או חלון קופץ אל $RANDOM_VALUE.exampleusercontent.com/shim, ומשתמש ב-postMessage כדי לשלוח את התוכן הלא מהימן ל-shim לצורך רינדור.
  • התוכן שעבר רינדור הופך ל-Blob ומעובד ב-iframe שבארגז חול (sandbox).

בהשוואה לגישה הקלאסית של דומיינים של Sandbox, השיטה הזו מבטיחה שכל התוכן מבודד לגמרי באתר ייחודי. בנוסף, מכיוון שהאפליקציה הראשית מטפלת באחזור הנתונים המיועדים לעיבוד, כבר אין צורך להשתמש בכתובות URL של יכולות.

סיכום

יחד, שני הפתרונות האלה מאפשרים לעבור מדומיינים קלאסיים של Sandbox, כמו googleusercontent.com, לפתרונות מאובטחים יותר שתואמים לחסימת קובצי cookie של צד שלישי. ב-Google כבר העברנו מוצרים רבים לשימוש בפתרונות האלה, ואנחנו מתכננים לבצע עוד העברות לשנה הבאה.