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

מניעת CSRF,‏ XSSI וזליגת מידע בין מקורות.

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

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

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

תאימות דפדפן

יש תמיכה בכותרות של בקשות Fetch Metadata בכל מנועי הדפדפנים המודרניים.

תמיכה בדפדפנים

  • Chrome: ‏ 76.
  • Edge: ‏ 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.
  • Edge: ‏ 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.
  • Edge: ‏ 79.
  • Firefox: ‏ 90.
  • Safari: 16.4.

מקור

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

Sec-Fetch-Dest

תמיכה בדפדפנים

  • Chrome: ‏ 80.
  • Edge: ‏ 80.
  • Firefox: ‏ 90.
  • Safari: 16.4.

מקור

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

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

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

הטמעת מדיניות בידוד משאבים

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

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

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

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

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

כל בקשה שלא מגיעה מהקשר בין מקורות (כמו evil.example) תתקבל. במיוחד, אלו בקשות ש:

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

שלב 3: מאפשרים ניווט פשוט ברמה העליונה והטמעת iframe

כדי לוודא שעדיין אפשר יהיה לקשר לאתר שלכם מאתרים אחרים, עליכם לאפשר ניווט פשוט (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: ביטול ההסכמה לנקודות קצה שנועדו לשרת תנועה בין אתרים (אופציונלי)

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

  • נקודות קצה שנועדו לגישה ממקורות שונים: אם האפליקציה שלכם מציגה נקודות קצה שפועלות עם 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. לאכוף את המדיניות על ידי דחיית בקשות שלא עומדות בדרישות.

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

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

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

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

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

קריאה נוספת