למה צריך "מבודד ממקורות שונים" כדי להשתמש בתכונות מתקדמות

למה צריך בידוד בין מקורות כדי להשתמש בתכונות מתקדמות כמו SharedArrayBuffer, performance.measureUserAgentSpecificMemory() וטיימר ברזולוציה גבוהה בצורה מדויקת יותר.

מבוא

במאמר הפיכת האתר ל'מבודד ממקורות שונים' באמצעות COOP ו-COEP הסברנו איך לעבור למצב 'מבודד בין מקורות' באמצעות COOP ו-COEP. במאמר הזה מוסבר למה צריך בידוד בין מקורות כדי להפעיל תכונות מתקדמות בדפדפן.

רקע

האינטרנט מבוסס על מדיניות מקור זהה: תכונת אבטחה שמגבילה את האינטראקציה של מסמכים וסקריפטים עם משאבים ממקור אחר. העיקרון הזה מגביל את הדרכים שבהן אתרים יכולים לגשת למשאבים ממקורות שונים. לדוגמה, למסמך מ-https://a.example אין גישה לנתונים שמתארחים ב-https://b.example.

עם זאת, למדיניות המקור הזהה היו כמה חריגות היסטוריות. כל אתר יכול:

  • הטמעת iframes ממקורות שונים
  • הכללת משאבים ממקורות שונים כמו תמונות או סקריפטים
  • פתיחת חלונות קופצים ממקורות שונים עם הפניה ל-DOM

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

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

כל ההחלטות האלה של המדיניות מתרחשות בתוך קבוצת הקשר של גלישה.

קבוצת הקשר של גלישה

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

כל זה השתנה ב-Spectre, שבו כל הנתונים שנטענים לאותה קבוצת הקשר גלישה כמו הקוד שלכם יכולים להיות קריאים. על ידי מדידת הזמן שלוקח לפעולות מסוימות, תוקפים יכולים לנחש את התוכן של המטמון של המעבד (CPU), ואת התוכן של הזיכרון של התהליך. התקפות תזמון כאלה אפשריות באמצעות טיימרים ברמת פירוט נמוכה שקיימים בפלטפורמה, אבל אפשר לזרז אותם באמצעות טיימרים ברמת פירוט גבוהה, גם מפורשים (כמו performance.now()) וגם מרומזים (כמו SharedArrayBuffer). אם evil.com מטמיע תמונה ממקורות שונים, הוא יכול להשתמש בהתקפה של Spectre כדי לקרוא את נתוני הפיקסלים שלו, ולכן ההגנות מסתמכות על 'אטימות' כלא יעילות.

ספקטר

במצב אידיאלי, כל הבקשות ממקורות שונים צריכים לבדוק באופן מפורש על ידי השרת שהוא הבעלים של המשאב. אם השרת שבבעלותו לא יספק את הבדיקה, הנתונים אף פעם לא יגיעו לקבוצת הקשר הגלישה של גורם זדוני, ולכן הם לא יגיעו להישג יד מפני התקפות Spectre שדף אינטרנט יכול לבצע. אנחנו קוראים לו מצב מבודד ממקורות שונים. זה בדיוק הנושא של COOP+COEP.

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

מדיניות הטמעה ממקורות שונים

מדיניות ההטמעה ממקורות שונים (COEP) מונעת ממסמך לטעון משאבים ממקורות שונים שלא מעניקים הרשאות למסמך באופן מפורש (באמצעות CORP או CORS). באמצעות התכונה הזו תוכלו להצהיר שמסמך לא יכול לטעון משאבים כאלה.

איך פועל COEP

כדי להפעיל את המדיניות הזו, צריך לצרף למסמך את כותרת ה-HTTP הבאה:

Cross-Origin-Embedder-Policy: require-corp

מילת המפתח require-corp היא הערך המקובל היחיד עבור COEP. המדיניות הזו אוכפת את המדיניות שלפיה המסמך יכול לטעון רק משאבים מאותו מקור או משאבים שמסומנים במפורש כניתן לטעינה ממקור אחר.

כדי שאפשר יהיה לטעון משאבים ממקור אחר, הם צריכים לתמוך בשיתוף משאבים בין מקורות (CORS) או במדיניות משאבים ממקורות שונים (CORP).

שיתוף משאבים בין מקורות

אם משאב בין מקורות תומך בשיתוף משאבים בין מקורות (CORS), אפשר להשתמש במאפיין של crossorigin כדי לטעון אותו לדף האינטרנט מבלי להיחסם על ידי COEP.

<img src="https://third-party.example.com/image.jpg" crossorigin>

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

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

מדיניות בנושא משאבים בין מקורות

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

לכותרת Cross-Origin-Resource-Policy יכולים להיות שלושה ערכים אפשריים:

Cross-Origin-Resource-Policy: same-site

אפשר לטעון משאבים שמסומנים בתור same-site רק מאותו אתר.

Cross-Origin-Resource-Policy: same-origin

אפשר לטעון משאבים שמסומנים בתור same-origin רק מאותו מקור.

Cross-Origin-Resource-Policy: cross-origin

כל אתר יכול לטעון משאבים שמסומנים בתור cross-origin. (הערך הזה נוסף למפרט של CORP יחד עם COEP).

מדיניות פותחן ממקורות שונים

מדיניות פותחן מקורות צולבים (COOP) מאפשרת לך לוודא שחלון ברמה העליונה מבודד ממסמכים אחרים על ידי הצבתם בקבוצה שונה של הקשר גלישה, כדי שהם לא יוכלו לקיים אינטראקציה ישירות עם החלון שברמה העליונה. לדוגמה, אם מסמך עם COOP פותח חלון קופץ, המאפיין window.opener שלו יהיה null. בנוסף, המאפיין .closed של ההפניה של קובץ הפתיחה יחזיר true.

קופה

לכותרת Cross-Origin-Opener-Policy יכולים להיות שלושה ערכים אפשריים:

Cross-Origin-Opener-Policy: same-origin

מסמכים שמסומנים כ-same-origin יכולים לשתף את אותה קבוצת הקשר גלישה עם מסמכים מאותו מקור שמסומנים גם הם באופן מפורש ב-same-origin.

קופה

Cross-Origin-Opener-Policy: same-origin-allow-popups

במסמך ברמה העליונה עם same-origin-allow-popups עדיין נשמרים הפניות לכל החלונות הקופצים שלא מגדירים COOP או שלא מאפשרים בידוד על ידי הגדרת COOP של unsafe-none.

קופה

Cross-Origin-Opener-Policy: unsafe-none

unsafe-none היא ברירת המחדל, ומאפשרת להוסיף את המסמך לקבוצת הקשר הגלישה של פתיחת הקובץ, אלא אם לפתיחה עצמה יש COOP של same-origin.

סיכום

אם רוצים להבטיח גישה מדויקת יותר לתכונות מתקדמות כמו SharedArrayBuffer, performance.measureUserAgentSpecificMemory() או טיימרים ברזולוציה גבוהה, חשוב לזכור שהמסמך צריך להשתמש גם ב-COEP עם הערך require-corp וגם ב-COOP עם הערך same-origin. בהיעדרם, הדפדפן לא יבטיח בידוד מספיק כדי להפעיל את התכונות העוצמתיות האלה באופן בטוח. אפשר לקבוע את מצב הדף על ידי בדיקה אם הפרמטר self.crossOriginIsolated מחזיר true.

במאמר הגדרת האתר לבידוד בין מקורות באמצעות COOP ו-COEP מוסבר איך לעשות זאת.

משאבים