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

בגרסה 67 של Chrome למחשב יש תכונה חדשה שנקראת בידוד אתר שמופעלת כברירת מחדל. הזה במאמר הזה נסביר מהו 'בידוד של אתרים', למה כדאי להשתמש בו ולמה כדאי למפתחי אתרים להיות מודעים לכך.

מהו 'בידוד של אתר'?

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

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

הבידוד של אתרים מקשה על אתרים לא מהימנים לגשת למידע או לגנוב אותו מהחשבונות שלכם באתרים אחרים. היא מספקת הגנה נוספת מפני סוגים שונים של באגים באבטחה כמו המתקפות האחרונות מסוג Meltdown ו-Spectre בערוץ צדדי.

למידע נוסף על 'בידוד של אתר', אפשר לעיין במאמר שלנו בבלוג בנושא אבטחה של Google.

חסימת קריאה ממקורות שונים

גם אם כל הדפים באתרים שונים מועברים לתהליכים נפרדים, דפים עדיין יכולים לשלוח בקשות באופן לגיטימי במשאבי משנה מסוימים באתרים שונים, כמו תמונות ו-JavaScript. דף אינטרנט זדוני עלול להשתמש רכיב <img> לטעינת קובץ JSON עם מידע אישי רגיש, כמו היתרה בחשבון הבנק:

<img src="https://your-bank.example/balance.json" />
<!-- Note: the attacker refused to add an `alt` attribute, for extra evil points. -->

בלי 'בידוד של אתר', התוכן של קובץ ה-JSON יועבר לזיכרון של כלי הרינדור ובשלב הזה כלי הרינדור מבחין בכך שהתמונה לא בפורמט חוקי ושהוא לא מעבד תמונה. אבל, התוקף יכול לנצל פרצת אבטחה כמו Spectre כדי לנסות לקרוא אותה. מקטע זיכרון.

במקום להשתמש ב<img>, התוקף יכול להשתמש ב-<script> גם כדי לשמור את המידע האישי הרגיש לצורך זיכרון:

<script src="https://your-bank.example/balance.json"></script>

חסימת קריאה בין מקורות, או CORB, היא תכונת אבטחה חדשה שמונעת תוכן של balance.json מכניסה לזיכרון של תהליך הרינדור, על סמך סוג ה-MIME שלו.

עכשיו נסביר איך CORB עובד. אתר יכול לבקש משרת שני סוגים של משאבים:

  1. משאבי נתונים, כמו מסמכי HTML, XML או JSON
  2. משאבי מדיה כמו תמונות, JavaScript, CSS או גופנים

אתר יכול לקבל מקורות נתונים מהמקור שלו או ממקורות אחרים באמצעות כותרות CORS מתירניות, כמו Access-Control-Allow-Origin: * מצד שני, אפשר לכלול משאבי מדיה מכל מקור, גם בלי כותרות CORS מאפשרות.

CORB מונע מתהליך הרינדור לקבל משאב נתונים ממקורות שונים (כלומר HTML , XML או JSON) אם:

  • למשאב יש כותרת X-Content-Type-Options: nosniff
  • CORS לא מאפשר באופן מפורש גישה למשאב

אם למשאב הנתונים ממקורות שונים לא מוגדרת הכותרת X-Content-Type-Options: nosniff, CORB מנסה לסרוק את גוף התגובה כדי לבדוק אם הוא HTML, XML או JSON. הדבר יש צורך כי חלק משרתי האינטרנט מוגדרים באופן שגוי ומציגים תמונות בתור text/html, לדוגמה.

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

כדי ליהנות מאבטחה אופטימלית ולהפיק תועלת מ-CORB, מומלץ לבצע את הפעולות הבאות:

  • צריך לסמן תשובות עם הכותרת Content-Type הנכונה. (לדוגמה, משאבי HTML צריכים להיות מוצגת בתור text/html, משאבי JSON עם סוג MIME של JSON ומשאבי XML עם סוג XML MIME).
  • לבטל את ההסכמה להרחקה באמצעות הכותרת X-Content-Type-Options: nosniff. בלי הכותרת, Chrome מבצע ניתוח תוכן מהיר כדי לנסות לוודא שהסוג נכון, אבל מאחר מאמת את האפשרות לאפשר תגובות כדי להימנע מחסימת קובצי JavaScript, עדיף לעשות את הדבר הנכון בעצמכם.

פרטים נוספים זמינים מאמר על CORB למפתחי אתרים או כאן אפשר לקבל הסבר מפורט על CORB.

למה חשוב למפתחי אתרים להשתמש ב'בידוד של אתר'?

מרוב הבחינות, 'בידוד של אתר' היא תכונה של הדפדפן שמיועדת מאחורי הקלעים, בפני מפתחי אתרים. לדוגמה, אין ממשק API חדש שחשוף לאינטרנט. באופן כללי, דפי אינטרנט שדפים לא יוכלו להבחין בהבדל בעת הפעלה עם או בלי 'בידוד של אתר'.

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

פריסת הדף המלא כבר לא מסונכרנת

בעזרת 'בידוד של אתר', פריסת הדף המלא אינה מובטחת עוד תהיה סינכרונית, מכיוון שמסגרות האתר כעת דף יכול להתפרס על פני מספר תהליכים. הדבר עשוי להשפיע על דפים אם הם מניחים שינוי הפריסה יופץ באופן מיידי לכל המסגרות בדף.

לדוגמה, נבחן אתר בשם fluffykittens.example שמתקשר עם הווידג'ט של רשתות חברתיות שמתארח ב-social-widget.example:

<!-- https://fluffykittens.example/ -->
<iframe src="https://social-widget.example/" width="123"></iframe>
<script>
  const iframe = document.querySelector('iframe');
  iframe.width = 456;
  iframe.contentWindow.postMessage(
    // The message to send:
    'Meow!',
    // The target origin:
    'https://social-widget.example'
  );
</script>

בהתחלה, הרוחב של <iframe> של הווידג'ט ברשתות החברתיות הוא 123 פיקסלים. אבל לאחר מכן, הדף FluffyKittens משנה את הרוחב ל-456 פיקסלים (הפעלת פריסה) ושולח הודעה לווידג'ט ברשת החברתית, שכולל את הקוד הבא:

<!-- https://social-widget.example/ -->
<script>
  self.onmessage = () => {
    console.log(document.documentElement.clientWidth);
  };
</script>

בכל פעם שהווידג'ט של הרשת החברתית מקבל הודעה דרך ה-API של postMessage, הוא מתעד את הרוחב של רכיב ה-<html> הבסיסי שלו.

איזה ערך רוחב נרשם? לפני שהתכונה 'בידוד אתרים' הופעלה ב-Chrome, התשובה הייתה 456. גישה document.documentElement.clientWidth אוכף את הפריסה, שבעבר הייתה סינכרונית לפני Chrome הפעלת 'בידוד של אתר'. עם זאת, כאשר 'בידוד אתר' מופעל, הווידג'ט החברתי ממקורות שונים עכשיו הפריסה מחדש מתבצעת באופן אסינכרוני בתהליך נפרד. לכן, התשובה יכולה להיות 123, כלומר הערך הישן של width.

אם גודל דף מסוים משנה את הגודל של <iframe> ממקורות שונים ולאחר מכן שולח אליו postMessage, עם מבודד של אתר, ייתכן שהמסגרת המקבלת עדיין לא יודעת מה הגודל החדש שלה בעת קבלת ההודעה. סמל האפשרויות הנוספות באופן כללי, הדבר עלול לגרום לתקלה בדפים אם הם מניחים ששינוי פריסה יופץ באופן מיידי המסגרות בדף.

בדוגמה הספציפית הזו, פתרון חזק יותר יגדיר את width במסגרת ההורה, וגם לזהות את השינוי ב-<iframe> על ידי האזנה לאירוע resize.

יכול להיות שהזמן הקצוב של handlers שנטענו יפוג בתדירות גבוהה יותר

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

addEventListener('unload', () => {
  doSomethingThatMightTakeALongTime();
});

במצב הזה, ה-handlers של unload בכל הפריימים מהימנים מאוד.

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

בעזרת 'בידוד של אתר', כל הניווטים בין אתרים הופכים לתהליכים שונים, כך שמסמכים מ- אתרים שונים לא משתפים תהליך זה עם זה. כתוצאה מכך, המצב שצוין למעלה חל יותר מקרים, ורכיבי handler של הסרת הנתונים שנטענו ב-<iframe> פועלים בדרך כלל בהתנהגויות שקשורות לרקע ולזמן קצוב לתפוגה שתוארו למעלה.

הבדל נוסף שנובע מבידוד אתר הוא הסדר המקביל החדש של מטפלים בהסרת הנתונים שנטענו: ללא בידוד אתר, רכיבי ה-handler של הסרת הנתונים שנטענו פועלים בסדר מחמיר מלמעלה-למטה, בכל המסגרות. אבל במקרה של אתר בידוד ורכיבי handler של הסרת נתונים שנטענו פועלים במקביל בתהליכים שונים.

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

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

addEventListener('pagehide', () => {
  const image = new Image();
  img.src = '/end-of-session';
});

לאור השינוי, גישה טובה יותר היא להשתמש ב-navigator.sendBeacon במקום זאת:

addEventListener('pagehide', () => {
  navigator.sendBeacon('/end-of-session');
});

אם דרושה לך יותר שליטה בבקשה, אפשר להשתמש באפשרות keepalive של Fetch API:

addEventListener('pagehide', () => {
  fetch('/end-of-session', {keepalive: true});
});

סיכום

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

תודות ל: אלכס מושצ'וק, צ'רלי רייס, ג'ייסון מילר, נאסקו אוסקוב, פיליפ וולטון, Shubhie Panicker, ו תומאס שטיינר על קריאת גרסת טיוטה של מאמר זה ושליחת משוב.