באפליקציות אינטרנט רבות צריך להציג תוכן שנשלט על ידי המשתמשים. הדבר יכול להיות פשוט כמו הצגת תמונות שהמשתמשים העלו (לדוגמה, תמונות פרופיל), או מורכב כמו עיבוד HTML בשליטת המשתמשים (לדוגמה, מדריך לפיתוח אתרים). תמיד היה קשה לעשות זאת בצורה מאובטחת, לכן עבדנו על מציאת פתרונות פשוטים אך מאובטחים שאפשר להחיל על רוב סוגי אפליקציות האינטרנט.
פתרונות קלאסיים לבידוד תוכן לא מהימן
הפתרון הקלאסי להצגה מאובטחת של תוכן בשליטת משתמשים הוא שימוש בדומיינים של ארגז חול. הרעיון הבסיסי הוא שאם הדומיין הראשי של האפליקציה הוא example.com
, אפשר להציג את כל התוכן הלא מהימן ב-exampleusercontent.com
. מכיוון ששני הדומיינים האלה מגיעים מאתרים שונים, תוכן זדוני ב-exampleusercontent.com
לא יכול להשפיע על example.com
.
אפשר להשתמש בגישה הזו כדי להציג בבטחה כל סוגי התוכן הלא מהימן, כולל תמונות, הורדות ו-HTML. יכול להיות שלא נראה לכם שצריך להשתמש בזה לתמונות או להורדות, אבל כך תוכלו למנוע סיכונים מניפוי תוכן, במיוחד בדפדפנים מדור קודם.
דומיינים של ארגז חול נמצאים בשימוש נרחב בתחום, והם פועלים היטב במשך זמן רב. אבל יש להם שני חסרונות עיקריים:
- לעיתים קרובות צריך להגביל את הגישה לתוכן למשתמש יחיד באפליקציות, ולשם כך צריך להטמיע אימות והרשאה. מכיוון שדומיינים של ארגז חול לא משתפים קובצי cookie עם דומיין האפליקציה הראשי בכוונה, קשה מאוד לעשות זאת בצורה מאובטחת. כדי לתמוך באימות, אתרים צריכים להסתמך על כתובות URL של יכולות או להגדיר קובצי cookie נפרדים לאימות לדומיין של ארגז החול. השיטה השנייה הזו בעייתית במיוחד באינטרנט המודרני, שבו דפדפנים רבים מגבילים קובצי cookie בכמה אתרים כברירת מחדל.
- תוכן המשתמש מבודד מהאתר הראשי, אבל לא מתוכן של משתמשים אחרים. כך נוצר סיכון להתקפה על נתונים אחרים בדומיין של ארגז החול על ידי תוכן זדוני של משתמשים (לדוגמה, באמצעות קריאת נתונים מאותו מקור).
חשוב גם לציין שדומיינים בסביבת חול עוזרים לצמצם את הסיכונים לדיגוג, כי המשאבים מחולקים בבירור לדומיין מבודד.
פתרונות מודרניים להצגת תוכן של משתמשים
עם הזמן, האינטרנט התפתח, ויש עכשיו דרכים קלות ובטוחות יותר להציג תוכן לא מהימן. יש הרבה גישות שונות לכך, לכן נפרט שני פתרונות שנעשה בהם שימוש נרחב ב-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 |
מניעת ההכללה של הדף באתרים שונים |
השילוב הזה של כותרות מבטיח שהאפליקציה תוכל לטעון את התגובה רק כמשאב משנה, או שהמשתמש יוכל להוריד אותה כקובץ. בנוסף, הכותרות מספקות כמה שכבות הגנה מפני באגים בדפדפן באמצעות כותרת ארגז החול של 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
כדי להפעיל בידוד בין מקורות.
- הצגת תוכן של משתמשים בתת-דומיין מבודד (למשל, Google משתמשת בדומיינים כמו
גישה 2: הצגת תוכן למשתמשים פעילים
אפשר גם להציג תוכן פעיל (למשל, תמונות HTML או SVG) בצורה בטוחה, בלי נקודות החולשה של הגישה הקלאסית לדומיין ב-sandbox.
האפשרות הפשוטה ביותר היא להשתמש בכותרת Content-Security-Policy: sandbox
כדי להורות לדפדפן לבודד את התגובה. נכון לעכשיו, לא כל הדפדפנים מטמיעים בידוד תהליכים למסמכים בארגז חול, אבל סביר להניח ששיפורים מתמשכים במודלים של תהליכי הדפדפן ישפרו את ההפרדה בין תוכן בארגז חול לבין אפליקציות מוטמעות. אם ההתקפות של SpectreJS והפרת אבטחה של ה-renderer לא נכללות במודל האיומים שלכם, סביר להניח ששימוש ב-sandbox של CSP יספק פתרון מספיק.
ב-Google פיתחנו פתרון שיכול לבודד באופן מלא תוכן פעיל לא מהימן על ידי עדכון הקונספט של דומיינים ב-sandbox. הרעיון המרכזי הוא:
- יוצרים דומיין חדש בארגז החול שנוסף לרשימת הסיומות הציבוריות. לדוגמה, הוספת
exampleusercontent.com
ל-PSL מאפשרת לוודא ש-foo.exampleusercontent.com
ו-bar.exampleusercontent.com
פועלים בין אתרים, ולכן הם מבודדים לחלוטין זה מזה. - כל כתובות ה-URL שתואמות ל-
*.exampleusercontent.com/shim
מנותבות לקובץ shim סטטי. קובץ ה-shim הזה מכיל קטע HTML קצר ו-JavaScript שמקשיב למטפל האירועיםmessage
ומעבד את כל התוכן שהוא מקבל. - כדי לעשות זאת, המוצר יוצר iframe או חלון קופץ ל-
$RANDOM_VALUE.exampleusercontent.com/shim
ומשתמש ב-postMessage
כדי לשלוח את התוכן הלא מהימן ל-shim לצורך עיבוד. - התוכן שעבר עיבוד הופך ל-Blob ומעובד בתוך iframe בארגז חול.
בהשוואה לגישה הקלאסית של דומיין ב-sandbox, כך אפשר להבטיח שכל התוכן מבודד לחלוטין באתר ייחודי. בנוסף, כשהאפליקציה הראשית מטפלת באחזור הנתונים לצורך עיבוד, אין יותר צורך להשתמש בכתובות URL של יכולות.
סיכום
שני הפתרונות האלה מאפשרים לעבור מדומיינים קלאסיים של ארגז חול, כמו googleusercontent.com
, לפתרונות מאובטחים יותר שתואמים לחסימת קובצי cookie של צד שלישי. ב-Google, כבר העברנו מוצרים רבים לשימוש בפתרונות האלה, ואנחנו מתכננים להעביר עוד מוצרים בשנה הבאה.