הגנה על המשאבים שלך מפני מתקפות באינטרנט באמצעות התכונה 'אחזור מטא-נתונים'

מניעת דליפות מידע של CSRF, XSSI ומקורות שונים.

למה צריך לבודד את משאבי האינטרנט?

אפליקציות אינטרנט רבות חשופות למתקפות ממקורות שונים, כמו Cross-site Request Forgery (CSRF), הכללת סקריפט חוצה-אתרים (XSSI), התקפות תזמון, דליפות מידע ממקורות שונים או התקפות ספקולטיביות בערוץ צדדי (Spectre).

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

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

תאימות דפדפן

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

תמיכה בדפדפן

  • Chrome: 76.
  • קצה: 79.
  • Firefox: 90.
  • Safari: 16.4.

מקור

רקע

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

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

היכרות עם אחזור מטא-נתונים

כותרות של בקשות אחזור מטא-נתונים הן תכונת אבטחה חדשה לפלטפורמת אינטרנט, שמיועדת לעזור לשרתים להתגונן מפני התקפות בין מקורות. מתן מידע על ההקשר של בקשת HTTP בקבוצה של כותרות Sec-Fetch-* מאפשר לשרת המשיב להחיל מדיניות אבטחה לפני עיבוד הבקשה. כך המפתחים יכולים להחליט אם לאשר או לדחות בקשה על סמך האופן שבו היא נשלחה וההקשר שבו ייעשה שימוש בה, וכך ניתן להשיב רק לבקשות לגיטימיות שנשלחו על ידי האפליקציה שלהם.

מאותו מקור
בקשות שמגיעות מאתרים שמקבלים שירות על ידי השרת שלכם (מקור זהה) ימשיכו לפעול. בקשת אחזור מ-https://site.example למשאב https://site.example/foo.json ב-JavaScript גורמת לדפדפן לשלוח את כותרת בקשת ה-HTTP 'Sec Fetch-Site: same-origin'.
בין אתרים
השרת יכול לדחות בקשות זדוניות בין אתרים שונים בגלל ההקשר הנוסף בבקשת ה-HTTP שמסופקת על ידי כותרות Sec-Fetch-*. תמונה בכתובת https://evil.example שמגדירה את מאפיין src של רכיב img ל-'https://site.example/foo.json' גורמת לדפדפן לשלוח את כותרת בקשת ה-HTTP 'Sec-Fetch-Site: Cross-site'.

Sec-Fetch-Site

תמיכה בדפדפן

  • Chrome: 76.
  • קצה: 79.
  • Firefox: 90.
  • Safari: 16.4.

מקור

Sec-Fetch-Site מציין לשרת מאיזה אתר נשלחה הבקשה. הדפדפן מגדיר את הערך הזה לאחד מהערכים הבאים:

  • same-origin, אם הבקשה נשלחה על ידי אפליקציה שלכם (למשל site.example)
  • same-site, אם הבקשה נשלחה על ידי תת-דומיין של האתר (למשל, bar.site.example)
  • none, אם הבקשה נגרמה באופן מפורש על ידי אינטראקציה של המשתמש עם סוכן המשתמש (למשל, לחיצה על סימנייה)
  • cross-site, אם הבקשה נשלחה על ידי אתר אחר (למשל evil.example)

Sec-Fetch-Mode

תמיכה בדפדפן

  • Chrome: 76.
  • קצה: 79.
  • Firefox: 90.
  • Safari: 16.4.

מקור

Sec-Fetch-Mode מציין את המצב של הבקשה. סוג זה תואם כמעט לסוג הבקשה ומאפשר לכם להבחין בין טעינות משאבים לבין בקשות ניווט. לדוגמה, היעד navigate מציין בקשת ניווט ברמה העליונה, ואילו no-cors מציין בקשות למשאבים כמו טעינת תמונה.

Sec-Fetch-Dest

תמיכה בדפדפן

  • Chrome: 80.
  • קצה: 80.
  • Firefox: 90.
  • Safari: 16.4.

מקור

Sec-Fetch-Dest חושף את היעד של בקשה (למשל, אם התג script או img גרמו לבקשה של משאב בדפדפן).

איך להשתמש באחזור מטא-נתונים כדי להגן מפני מתקפות ממקורות שונים

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

יישום מדיניות בנושא בידוד משאבים

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

שלב 1: אפשר בקשות מדפדפנים שלא שולחים מטא-נתונים לאחזור

מכיוון שלא כל הדפדפנים תומכים באחזור מטא-נתונים, עליך לאפשר בקשות שלא קובעות את הכותרות של Sec-Fetch-* על ידי בדיקת הנוכחות של sec-fetch-site.

if not req['sec-fetch-site']:
  return True  # Allow this request

שלב 2: אפשר לשלוח בקשות באותו אתר או ביוזמת הדפדפן

כל בקשה שלא הגיעה מהקשר של מקורות שונים (כמו evil.example) יאושרו. באופן ספציפי, הבקשות הן:

  • מגיעה מהאפליקציה שלכם (למשל, בקשה ממקור זהה שבו site.example מבקש site.example/foo.json תמיד יותר מותר).
  • מגיע מתת-הדומיינים שלכם.
  • נגרמות באופן מפורש מאינטראקציה של המשתמש עם סוכן המשתמש (למשל: ניווט ישיר או לחיצה על סימנייה וכו').
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
  return True  # Allow this request

שלב 3: מפעילים ניווט פשוט ברמה העליונה ו-iframes

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

if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
  # <object> and <embed> send navigation requests, which we disallow.
  and req['sec-fetch-dest'] not in ('object', 'embed'):
    return True  # Allow this request

שלב 4: מבטלים את ההסכמה לנקודות קצה (endpoints) שמיועדות להציג תנועה מאתרים שונים (אופציונלי)

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

  • נקודות קצה (endpoints) שמיועדות לגישה ממקורות שונים: אם האפליקציה שלכם מציגה נקודות קצה שמופעלות בהן CORS, צריך לבטל את ההסכמה לבידוד של משאבים באופן מפורש כדי לוודא שבקשות מאתרים שונים לנקודות הקצה האלה עדיין אפשריות.
  • משאבים ציבוריים (למשל תמונות, סגנונות וכו'): גם כל משאב ציבורי ולא מאומת שאמורים להיות נטענים ממקורות שונים מאתרים אחרים, יכול לקבל פטור.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
  return True

שלב 5: דחייה של כל הבקשות האחרות שרלוונטיות לאתרים שונים ולא לניווט

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

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

# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
  # Allow requests from browsers which don't send Fetch Metadata
  if not req['sec-fetch-site']:
    return True

  # Allow same-site and browser-initiated requests
  if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
    return True

  # Allow simple top-level navigations except <object> and <embed>
  if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
    and req['sec-fetch-dest'] not in ('object', 'embed'):
      return True

  # [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
  if req.path in ('/my_CORS_endpoint', '/favicon.png'):
    return True

  # Reject all other requests that are cross-site and not navigational
  return False

פריסה של מדיניות בידוד משאבים

  1. התקינו מודול כמו קטע הקוד שלמעלה כדי לתעד יומן ולעקוב אחר התנהגות האתר, ולוודא שההגבלות לא משפיעות על תנועה לגיטימית.
  2. כדי לתקן הפרות אפשריות, צריך לתת פטור לנקודות קצה לגיטימיות ממקורות שונים.
  3. כדי לאכוף את המדיניות, משחררים בקשות שלא עומדות בדרישות.

זיהוי ותיקון של הפרות מדיניות

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

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

אכיפה של מדיניות בידוד משאבים

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

קריאה נוספת