למה צריך בידוד בין מקורות כדי להשתמש בתכונות מתקדמות כמו SharedArrayBuffer
, performance.measureUserAgentSpecificMemory()
וטיימר ברזולוציה גבוהה עם דיוק משופר?
מבוא
במאמר הפיכת האתר ל'מבודד בין מקורות' באמצעות COOP ו-COEP הסברנו איך עוברים למצב 'מבודד בין מקורות' באמצעות COOP ו-COEP. זהו מאמר נלווה שמסביר למה נדרש בידוד בין מקורות כדי להפעיל תכונות חזקות בדפדפן.
רקע
האינטרנט מבוסס על מדיניות המקור הזהה: תכונת אבטחה שמגבילה את האופן שבו מסמכים וסקריפטים יכולים לקיים אינטראקציה עם משאבים ממקור אחר. העיקרון הזה מגביל את הדרכים שבהן אתרים יכולים לגשת למשאבים ממקורות שונים. לדוגמה, למסמך מ-https://a.example
אין גישה לנתונים שמתארחים ב-https://b.example
.
עם זאת, למדיניות המקור הזהה היו כמה חריגים היסטוריים. כל אתר יכול:
- הטמעת iframes ממקורות שונים
- לכלול משאבים ממקורות שונים, כמו תמונות או סקריפטים
- פתיחת חלונות קופצים ממקורות שונים באמצעות הפניה ל-DOM
אם אפשר היה לתכנן את האינטרנט מחדש, החריגות האלה לא היו קיימות. לצערנו, עד שהקהילה האינטרנטית הבינה את היתרונות המרכזיים של מדיניות מחמירה של מקור יחיד, האינטרנט כבר הסתמך על ההחרגות האלה.
תופעות הלוואי של מדיניות המקור הזהה המחמירה הזו תוקנו בשתי דרכים. אחת מהדרכים הייתה באמצעות הצגת פרוטוקול חדש שנקרא שיתוף משאבים בין מקורות (CORS), שמטרתו לוודא שהשרת מאפשר שיתוף משאב עם מקור נתון. הדרך השנייה היא להסיר באופן משתמע את הגישה הישירה של הסקריפט למשאבים ממקורות שונים, תוך שמירה על תאימות לאחור. משאבים כאלה שמגיעים ממקורות שונים נקראים משאבים 'אטומים'. לדוגמה, זו הסיבה לכך שאי אפשר לשנות את הפיקסלים של תמונה ממקורות שונים באמצעות CanvasRenderingContext2D
, אלא אם מחילים את CORS על התמונה.
כל ההחלטות האלה לגבי מדיניות מתקבלות בתוך קבוצת הקשר גלישה.
במשך זמן רב, השילוב של CORS ומשאבים אטומים הספיק כדי להבטיח את הבטיחות בדפדפנים. לפעמים התגלו מקרים קיצוניים (כמו נקודות חולשה ב-JSON) שנדרשו תיקונים עבורם, אבל באופן כללי, העקרון של אי-מתן גישה ישירה לקריאה לבייטים הגולמיים של משאבים ממקורות שונים הוכיח את עצמו.
כל זה השתנה עם Spectre, שעלול לאפשר קריאה של כל נתון שנטען לאותה קבוצת הקשר של גלישה כמו הקוד שלכם. על ידי מדידת משך הזמן של פעולות מסוימות, תוקפים יכולים לנחש את התוכן של מטמון המעבד, וכך את התוכן של זיכרון התהליך. התקפות תזמון כאלה אפשריות באמצעות שעונים ברמת פירוט נמוכה שנמצאים בפלטפורמה, אבל אפשר להאיץ אותן באמצעות שעונים ברמת פירוט גבוהה, גם מפורשים (כמו performance.now()
) וגם משתמעים (כמו SharedArrayBuffer
). אם evil.com
מטמיע תמונה ממקורות שונים, הוא יכול להשתמש בהתקפת Spectre כדי לקרוא את נתוני הפיקסלים שלה, וכתוצאה מכך אמצעי ההגנה שמסתמכים על 'חוסר שקיפות' לא יעילים.
באופן אידיאלי, כל הבקשות ממקורות שונים צריכות לעבור בדיקה מפורשת על ידי השרת שבבעלותו המשאב. אם לא תתבצע בדיקה על ידי השרת שבבעלות המשאב, הנתונים לעולם לא ייכנסו לקבוצת ההקשר של הגלישה של גורם זדוני, ולכן הם לא יהיו חשופים להתקפות Spectre שדף אינטרנט יכול לבצע. אנחנו מכנים את המצב הזה 'מצב מבודד ממקורות שונים'. זה בדיוק מה ש-COOP+COEP עוסק בו.
במצב של בידוד בין מקורות, האתר המבקש נחשב פחות מסוכן, וכך אפשר להשתמש בתכונות חזקות כמו SharedArrayBuffer
, performance.measureUserAgentSpecificMemory()
ושעונים ברזולוציה גבוהה עם דיוק גבוה יותר, שיכולים לשמש להתקפות כמו Spectre. הוא גם מונע שינוי של document.domain
.
מדיניות הטמעה ממקורות שונים
מדיניות להטמעה במקורות שונים (COEP) מונעת מסמך לטעון משאבים ממקורות שונים שלא מעניקים לו הרשאה באופן מפורש (באמצעות CORP או CORS). בעזרת התכונה הזו אפשר להצהיר שמסמך לא יכול לטעון משאבים כאלה.
כדי להפעיל את המדיניות הזו, צריך לצרף למסמך את כותרת ה-HTTP הבאה:
Cross-Origin-Embedder-Policy: require-corp
הערך של COEP הוא require-corp
. כך אפשר לאכוף את המדיניות שלפיה המסמך יכול לטעון רק משאבים מאותו מקור, או משאבים שסומנו במפורש כאפשריים לטעינה ממקור אחר.
כדי שאפשר יהיה לטעון משאבים ממקור אחר, הם צריכים לתמוך ב-Cross Origin Resource Sharing (CORS) או ב-Cross Origin Resource Policy (CORP).
שיתוף משאבים בין מקורות (CORS)
אם משאב ממקור אחר תומך בשיתוף משאבים בין מקורות (CORS), אפשר להשתמש במאפיין crossorigin
כדי לטעון אותו לדף האינטרנט בלי שהוא ייחסם על ידי COEP.
<img src="https://third-party.example.com/image.jpg" crossorigin>
לדוגמה, אם משאב התמונה הזה מוצג עם כותרות CORS, צריך להשתמש במאפיין crossorigin
כדי שהבקשה לאחזור המשאב תשתמש במצב CORS. כך גם תמנעו את הטעינה של התמונה, אלא אם היא תגדיר כותרות CORS.
באופן דומה, אפשר לאחזר נתונים ממקורות שונים באמצעות השיטה fetch()
, שלא דורשת טיפול מיוחד כל עוד השרת מגיב עם כותרות ה-HTTP הנכונות.
מדיניות משאבים ממקורות שונים (CORS)
מדיניות משאבים ממקורות שונים (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
.
במאמר איך מבודדים את האתר מ-origin שונים באמצעות COOP ו-COEP מוסבר איך מטמיעים את התכונה הזו.