פורסם: 4 במאי 2020
במאמר איך להגדיר את האתר כ'חסום לגישה מדומיינים אחרים' באמצעות COOP ו-COEP הסברנו איך להגדיר את האתר כ'חסום לגישה מדומיינים אחרים' באמצעות COOP ו-COEP. זהו מאמר משלים שמסביר למה נדרשת חסימה לגישה מדומיינים אחרים כדי להפעיל תכונות מתקדמות בדפדפן.
מילון מונחים
במסמך הזה אנחנו משתמשים בהרבה מונחים עם שמות דומים וקיצורים. כדי להבהיר את המושגים, ריכזנו מילון מונחים קצר:
- COEP: מדיניות הטמעה ממקורות שונים
- COOP: מדיניות פותחן מרובת מקורות
- CORP: מדיניות שיתוף משאבים בין מקורות
- CORS: שיתוף משאבים בין מקורות
- CORB: Cross Origin Read Blocking
רקע
האינטרנט מבוסס על מדיניות המקור הזהה, תכונת אבטחה שמגבילה את האופן שבו מסמכים וסקריפטים יכולים ליצור אינטראקציה עם משאבים ממקור אחר. העיקרון הזה מגביל את הדרכים שבהן אתרים יכולים לגשת למשאבים ממקורות שונים. לדוגמה, למסמך מ-https://a.example
אין גישה לנתונים שמתארחים ב-https://b.example.
עם זאת, היו בעבר כמה חריגים למדיניות המקור הזהה. כל אתר יכול:
- הטמעת iframes ממקורות שונים
- כולל משאבים ממקורות שונים, כמו תמונות או סקריפטים
- פתיחת חלונות דו-שיח חוצי-מקורות עם הפניה ל-DOM
עד שהקהילה באינטרנט הבינה את היתרונות של מדיניות קפדנית בנושא מקורות זהים, האינטרנט כבר הסתמך על החריגים האלה.
השפעות הלוואי של מדיניות מקור זהה כזו על האבטחה תוקנו בשתי דרכים:
- פרוטוקול שיתוף משאבים בין מקורות (CORS) מוודא שהשרת מאפשר שיתוף משאב עם מקור נתון.
- המפתחים מסירים באופן מרומז את הגישה הישירה של סקריפטים למשאבי cross-origin, תוך שמירה על תאימות לאחור. משאבים כאלה ממקורות שונים נקראים משאבים אטומים. לכן, מניפולציה של פיקסלים ממקורות שונים באמצעות
CanvasRenderingContext2Dנכשלת אלא אם מוחל CORS על התמונה.
כל ההחלטות האלה לגבי מדיניות מתקבלות בתוך קבוצה של הקשרים של הגלישה.

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

באופן אידיאלי, השרת שבבעלותו המשאב בודק את כל בקשות ה-CORS. אם לא בוצעה בדיקה, הנתונים לא אמורים להגיע לקבוצת הקשרים של הגלישה של גורם זדוני. לכן, הנתונים לא נגישים להתקפות Spectre אפשריות. המצב הזה נקרא מצב חסום לגישה מדומיינים אחרים.
כשהקוד המוטמע נמצא במצב חסום לגישה מדומיינים אחרים, האתר ששולח את הבקשה נחשב לפחות מסוכן. כך האתר ששולח את הבקשה יכול להשתמש ב-SharedArrayBuffer, ב-performance.measureUserAgentSpecificMemory() ובטיימרים ברזולוציה גבוהה עם דיוק משופר, וגם למנוע התקפות Spectre אפשריות. במצב הזה אי אפשר לשנות את document.domain.
מדיניות הטמעה ממקורות שונים
מדיניות הטמעה ממקורות שונים (COEP) מונעת ממסמך לטעון משאבים ממקורות שונים שלא מעניקים למסמך הרשאה באופן מפורש באמצעות CORP או CORS. התכונה הזו מאפשרת להצהיר שמסמך לא יכול לטעון משאבים כאלה.
a.example, הוגדרה מדיניות COEP לערך require-corp. האתר a.example רוצה להטמיע 3 נכסים מהאתר b.example, אבל רק שניים מהם מוטמעים בהצלחה.
שני ההטמעות המוצלחות כוללות קובץ JavaScript עם מדיניות CORP חוצה-מקורות ותמונה עם CORS מותר. הנכס השלישי הוא סרטון עם מדיניות CORP שמחייבת הטמעה של הנכס רק באותו מקור, ולכן הסרטון לא ייטען ב-a.example.
כדי להפעיל את המדיניות הזו, מוסיפים את כותרת ה-HTTP הבאה למסמך:
Cross-Origin-Embedder-Policy: require-corp
הערך היחיד שמתקבל ב-COEP הוא require-corp. ההגדרה הזו אוכפת את המדיניות שלפיה המסמך יכול לטעון רק משאבים מאותו מקור, או משאבים שמסומנים במפורש כמשאבים שאפשר לטעון ממקור אחר.
כדי שיהיה אפשר לטעון משאבים ממקור אחר, הם צריכים לתמוך בשיתוף משאבים בין מקורות (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 מוסבר איך מטמיעים את התכונה הזו.