Overview

מבוא

הערה: המסמכים האלה עדיין בשלבי פיתוח. צפויים שיפורים בעתיד הקרוב.

הגלישה הבטוחה של Google היא גרסה 5 של הגלישה הבטוחה של Google. שני השינויים העיקריים שבוצעו בגרסה 5 הם עדכניות הנתונים ופרטיות ה-IP. בנוסף, שיפרנו את פלטפורמת ה-API כדי להגביר את הגמישות והיעילות ולצמצם את העומס. בנוסף, הגלישה הבטוחה של Google גרסה 5 מאפשרת לבצע את ההעברה מ-v4 בקלות.

בשלב זה, Google מציעה גם את v4 וגם את v5, ושתיהן נחשבות מוכנות לייצור. אפשר להשתמש ב-v4 או ב-v5. לא הכרזנו על תאריך ההוצאה משימוש של גרסה 4. אם לא תפורסם הודעה כזו, נודיע לך על כך לפחות שנה אחת. הדף הזה יתאר את v5 וכן מדריך העברה מגרסה 4 ל-v5. התיעוד המלא של גרסה 4 יישאר זמין.

עדכניות הנתונים

שיפור משמעותי אחד של הגלישה הבטוחה בגרסה 5 של Google (בפרט, ממשק ה-API של גרסה 4 לעדכון) הוא עדכניות הנתונים והכיסוי שלהם. מכיוון שההגנה תלויה מאוד במסד הנתונים המקומי שמנוהל על ידי הלקוח, העיכוב והגודל של עדכון מסד הנתונים המקומי הם הגורם העיקרי להגנה שפוספסה. בגרסה 4, ללקוח טיפוסי לוקח 20 עד 50 דקות להשיג את הגרסה העדכנית ביותר של רשימות האיומים. לצערנו, התקפות פישינג מתפשטות במהירות: נכון לשנת 2021, 60% מהאתרים שמספקים התקפות נמשכים פחות מ-10 דקות. לפי הניתוח שלנו, כ-25-30% מהחסרונות להגנה מפני פישינג נובעים מחוסר פעילות בנתונים. נוסף על כך, מכשירים מסוימים לא מותאמים לניהול כל רשימות האיומים של הגלישה הבטוחה של Google. רשימות האיומים האלה הולכות וגדלות עם הזמן.

בגרסה 5 אנחנו משיקים מצב פעולה שידוע בשם 'הגנה בזמן אמת'. הפעולה הזו עוקפת את בעיית החוסר פעילות של הנתונים שצוינה למעלה. בגרסה 4, הלקוחות מצפים להוריד ולתחזק מסד נתונים מקומי, לבצע בדיקות מול רשימות האיומים שהורדו באופן מקומי, וכשיש התאמת קידומת חלקית, שולחים בקשה להורדת הגיבוב המלא. בגרסה 5, הלקוחות אמורים להמשיך להוריד ולתחזק מסד נתונים מקומי של רשימות איומים, אבל הלקוחות צפויים גם להוריד רשימה של אתרים בעלי סבירות גבוהה (שנקראים 'מטמון גלובלי'), לבצע גם בדיקה מקומית של המטמון הגלובלי הזה וגם בדיקה של רשימת איומים מקומית, ולבסוף, כשיש התאמת קידומת חלקית לרשימות איומים או חוסר התאמה במטמון הגלובלי, מבצעים בקשה להורדת המטמון הגלובלי. (לפרטים על העיבוד המקומי הנדרש על ידי הלקוח, יש לעיין בהליך הבא). הנתונים האלה מייצגים מעבר מ'אישור כברירת מחדל' ל'בדיקה כברירת מחדל', שיכול לשפר את ההגנה לאור הפצה מהירה יותר של איומים באינטרנט. במילים אחרות, זהו פרוטוקול שנועד לספק הגנה כמעט בזמן אמת: המטרה שלנו היא לאפשר ללקוחות להפיק תועלת מהנתונים העדכניים של הגלישה הבטוחה של Google.

פרטיות IP

הגלישה הבטוחה של Google (בגרסה 4 או 5) לא מעבדת שום דבר שמשויך לזהות המשתמש במהלך מילוי הבקשות. המערכת מתעלמת מקובצי Cookie, אם הם נשלחים. כתובות ה-IP המקוריות של הבקשות ידועות ל-Google, אבל Google משתמשת בכתובות ה-IP רק למטרות חיוניות של הרשת (כלומר לשליחת תגובות) ולמטרות מניעת מניעת שירות (DoS).

במקביל לגרסה 5, אנחנו משיקים ממשק API נלווה שנקרא Safe Overview Oblivious HTTP Gateway API. הפעולה הזו משתמשת ב-Oblivious HTTP כדי להסתיר את כתובות ה-IP של משתמשי הקצה מ-Google. לשם כך, צד שלישי שאינו מתקשר צריך לטפל בגרסה מוצפנת של בקשת המשתמש ולאחר מכן להעביר אותה ל-Google. כלומר, לצד השלישי יש גישה רק לכתובות ה-IP, ול-Google יש גישה רק לתוכן הבקשה. הצד השלישי מפעיל ממסר HTTP של Oblivious (למשל, השירות הזה של Fastly), ו-Google מפעילה את שער ה-Oblivious HTTP. זהו API אופציונלי. כשמשתמשים בנתונים האלה בשילוב עם הגלישה הבטוחה של Google, כתובות ה-IP של משתמשי הקצה לא נשלחות יותר ל-Google.

שימוש מתאים

שימוש מותר

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

תמחור

כל ממשקי ה-API של הגלישה הבטוחה של Google מוצעים בחינם.

מכסות

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

כתובות URL מתאימות

הגלישה הבטוחה של Google נועדה לפעול בכתובות URL שיוצגו בסרגל הכתובות של הדפדפן. הוא לא נועד לשמש לבדיקה מול משאבי משנה (כמו JavaScript או תמונה שאליה מפנה קובץ HTML, או כתובת URL של WebSocket שמופעלת על ידי JavaScript). אין לבדוק כתובות URL של משאבי משנה כאלה מול הגלישה הבטוחה של Google.

אם נכנסים לכתובת URL שמובילה להפניה אוטומטית (למשל HTTP 301), כדאי שכתובת ה-URL שאליה היא מועברת תיבדק מול הגלישה הבטוחה של Google. מניפולציה של כתובות URL בצד הלקוח, כמו History.pushState, לא מובילה לבדיקה של כתובות URL חדשות בהשוואה לגלישה הבטוחה של Google.

אזהרות משתמשים

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

ההנחיות האלה עוזרות להגן עליך ועל Google מפני אי-הבנות, בכך שהן מבהירות שהדף אינו ידוע בוודאות ב-100% בתור משאב אינטרנט לא בטוח, ושהאזהרות רק מזהות סיכון אפשרי.

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

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

אמצעי הפעולה

גרסה 5 של הגלישה הבטוחה של Google מאפשרת ללקוחות לבחור מבין שלושה מצבי פעולה.

מצב 'זמן אמת'

כשלקוחות בוחרים להשתמש בגרסה 5 של הגלישה הבטוחה של Google במצב 'זמן אמת', הלקוחות יחזיקו במסד הנתונים המקומי שלהם: (i) מטמון גלובלי של אתרים שעשויים להיות בעלי חשיבות רבה, בפורמט SHA256 - גיבובי SHA256 של ביטויי כתובות URL עם קידומת של מארח/נתיב, (ii) קבוצת רשימות של איומים, בפורמט של קידומות גיבוב (hash) מסוג SHA256 של ביטויים של כתובות URL עם סיומת מארח/נתיב. הרעיון הכללי הוא שבכל פעם שהלקוח רוצה לבדוק כתובת URL מסוימת, מתבצעת בדיקה מקומית באמצעות המטמון הגלובלי. אם הבדיקה מצליחה, מתבצעת בדיקה של רשימת איומים מקומית. אחרת, הלקוח ימשיך בבדיקת הגיבוב בזמן אמת כמפורט למטה.

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

תיאור מפורט של התהליך מופיע בהמשך.

מצב רשימה מקומית

כשלקוחות בוחרים להשתמש בגרסה 5 של הגלישה הבטוחה של Google במצב הזה, התנהגות הלקוח דומה ל-v4 Update API, למעט שימוש בפלטפורמת ה-API המשופרת של v5. הלקוחות ינהלו במסד הנתונים המקומי שלהם קבוצה של רשימות איומים בפורמט של קידומות גיבוב (hash) SHA256 של ביטויים של כתובות URL עם קידומת של מארח/נתיב. בכל פעם שהלקוח רוצה לבדוק כתובת URL מסוימת, מתבצעת בדיקה באמצעות רשימת האיומים המקומית. אם ורק אם יש התאמה, הלקוח מתחבר לשרת כדי להמשיך בבדיקה.

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

מצב 'אין אחסון בזמן אמת'

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

בכל פעם שהלקוח רוצה לבדוק כתובת URL מסוימת, הוא תמיד מתחבר לשרת כדי לבצע בדיקה. המצב הזה דומה למה שהלקוחות של v4 Lookup API עשויים להטמיע.

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

כתובות ה-URL בבדיקה

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

קנוניזציה של כתובות URL

לפני בדיקת כתובות URL, הלקוח צפוי לבצע כתובת קנונית מסוימת בכתובת ה-URL הזו.

קודם כל, אנחנו מניחים שהלקוח ניתח את כתובת ה-URL והפך אותה לתקינה בהתאם לתקן RFC 2396. אם בכתובת ה-URL נעשה שימוש בשם דומיין בינלאומי (IDN), הלקוח צריך להמיר את כתובת ה-URL לייצוג של קוד ASCII ב-Punycode. כתובת ה-URL חייבת לכלול רכיב נתיב. כלומר, חייב להיות בה לפחות קו נטוי אחד אחרי הדומיין (http://google.com/ במקום http://google.com).

תחילה מסירים מכתובת ה-URL את תווי Tab (0x09), CR (0x0d) ו-LF (0x0a). אין להסיר רצפי בריחה מהתווים האלה (למשל %0a).

שנית, אם כתובת ה-URL מסתיימת במקטע, צריך להסיר את המקטע. לדוגמה, אפשר לקצר את http://google.com/#frag ל-http://google.com/.

שלישית, ביטול בריחה של כתובת ה-URL באמצעות אחוזים חוזרים, עד שלא יהיו לה יותר תווי בריחה (escape). (כתוצאה מכך, כתובת ה-URL עלולה להיות לא תקינה).

כדי להגדיר את שם המארח כקנוני:

מחלצים את שם המארח מכתובת ה-URL ואז:

  1. מסירים את כל הנקודות המובילות והסופיות.
  2. מחליפים נקודות ברצף בנקודה אחת.
  3. אם אפשר לנתח את שם המארח ככתובת IPv4, צריך לנרמל אותו לערכים עשרוניים שמופרדים בנקודות. הלקוח צריך לטפל בכל קידוד חוקי של כתובות IP, כולל אוקטלי, הקסדצימלי ופחות מארבעה רכיבים.
  4. אם אפשר לנתח את שם המארח ככתובת IPv6 מוקפת, אפשר לנרמל אותו על ידי הסרת אפסים מיותרים בתחילת הרכיבים וכיווץ רכיבי אפס באמצעות תחביר של נקודה כפולה. לדוגמה, צריך להמיר את [2001:0db8:0000::1] ל-[2001:db8::1]. אם שם המארח הוא אחד משני הסוגים המיוחדים של כתובות IPv6, ממירים אותם ל-IPv4:
    • כתובת IPv6 במיפוי IPv4, כמו [::ffff:1.2.3.4], שצריך לשנות ל-1.2.3.4.
    • כתובת NAT64 שמשתמשת בקידומת הידועה 64:ff9b::/96, כמו [64:ff9b::1.2.3.4], שצריך להמיר ל-1.2.3.4.
  5. צריך להשתמש באותיות קטנות לכל המחרוזת.

כדי להגדיר את הנתיב כקנונית:

  1. כדי לפתור את הרצפים /../ ו-/./ בנתיב, צריך להחליף את /./ ב-/ ולהסיר את /../ ואת רכיב הנתיב הקודם.
  2. החלפת רצפים של לוכסנים עוקבים בתו קו נטוי יחיד.

אל תחילו את הקנוניזציה של הנתיבים האלה על הפרמטרים של השאילתה.

בכתובת ה-URL, מזינים באחוזים את כל התווים שהם <= ASCII 32 , >= 127 , # או %. תווי הבריחה (escape) צריכים לכלול תווי הקסדצימלי עם אותיות רישיות.

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

לאחר שכתובת ה-URL תהיה קנונית, השלב הבא הוא יצירת הביטויים של סיומת/קידומת. כל ביטוי סיומת/קידומת מורכב מסיומת מארח (או ממארח מלא) ומקידומת של נתיב (או נתיב מלא).

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

עבור המארח, הלקוח ינסה להשתמש בחמש מחרוזות שונות לכל היותר. אלו הם:

  • אם שם המארח אינו מילולי של IPv4 או IPv6, עד ארבעה שמות מארחים שנוצרו על ידי התחלה בדומיין eTLD+1 והוספת רכיבים מובילים עוקבים. קביעת ה-eTLD+1 צריכה להתבסס על רשימת הסיומות הציבוריות. לדוגמה, הפונקציה a.b.example.com תניב את הדומיין eTLD+1 של example.com וגם למארח עם רכיב מארח אחד נוסף b.example.com.
  • שם המארח המדויק בכתובת ה-URL. בהתאם לדוגמה הקודמת, התיבה a.b.example.com תסומן.

בנתיב, הלקוח ינסה שש מחרוזות שונות לכל היותר. אלו הם:

  • הנתיב המדויק של כתובת ה-URL, כולל הפרמטרים של השאילתה.
  • הנתיב המדויק של כתובת ה-URL, ללא פרמטרים של שאילתה.
  • ארבעת הנתיבים שנוצרו על ידי התחלה מהשורש (/) וצירוף רכיבי הנתיב ברצף, כולל קו נטוי בסוף.

הדוגמאות הבאות ממחישות את התנהגות הבדיקה:

עבור כתובת ה-URL http://a.b.com/1/2.html?param=1, הלקוח ינסה את המחרוזות הבאות הבאות:

a.b.com/1/2.html?param=1
a.b.com/1/2.html
a.b.com/
a.b.com/1/
b.com/1/2.html?param=1
b.com/1/2.html
b.com/
b.com/1/

עבור כתובת ה-URL http://a.b.c.d.e.f.com/1.html, הלקוח ינסה את המחרוזות הבאות הבאות:

a.b.c.d.e.f.com/1.html
a.b.c.d.e.f.com/
c.d.e.f.com/1.html
c.d.e.f.com/
d.e.f.com/1.html
d.e.f.com/
e.f.com/1.html
e.f.com/
f.com/1.html
f.com/

(הערה: דלגו על b.c.d.e.f.com, מכיוון שנתייחס רק לחמשת הרכיבים האחרונים של שם המארח ואת שם המארח המלא.)

עבור כתובת ה-URL http://1.2.3.4/1/, הלקוח ינסה את המחרוזות הבאות הבאות:

1.2.3.4/1/
1.2.3.4/

עבור כתובת ה-URL http://example.co.uk/1, הלקוח ינסה את המחרוזות הבאות הבאות:

example.co.uk/1
example.co.uk/

גיבוב (hashing)

בגלישה הבטוחה של Google נעשה שימוש אך ורק באלגוריתם SHA256 בתור פונקציית הגיבוב (hash). יש להחיל את פונקציית הגיבוב (hash) הזו על הביטויים שלמעלה.

בהתאם לנסיבות, הגיבוב המלא בגודל 32 בייטים ייחתך ל-4 בייטים, ל-8 בייטים או ל-16 בייטים:

  • כשמשתמשים בשיטה hashes.search, אנחנו דורשים כרגע לחתוך את הגיבובים בבקשה ל-4 בייטים בדיוק. שליחת בייטים נוספים בבקשה הזו תפגע בפרטיות המשתמשים.

  • כשמורידים את הרשימות למסד הנתונים המקומי באמצעות method hashList.get או hashLists.batchGet, אורך הגיבובים שנשלחים על ידי השרת מושפע גם מאופי הרשימה וגם מהעדפת הלקוח לגבי אורך הגיבוב, כפי שנקבע על ידי הפרמטר desired_hash_length.

ההליך לבדיקת כתובות URL בזמן אמת

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

ההליך הזה לוקח כתובת URL יחידה u ומחזיר את הערך SAFE, UNSAFE או UNSURE. אם מוחזר SAFE, כתובת ה-URL נחשבת בטוחה על ידי הגלישה הבטוחה של Google. אם היא מחזירה את הערך UNSAFE, כתובת ה-URL נחשבת שעלולה להיות לא בטוחה על ידי הגלישה הבטוחה של Google, וצריך לבצע את הפעולה המתאימה: כמו הצגת אזהרה למשתמש הקצה, העברת הודעה שהתקבלה לתיקיית הספאם או דרישה לאישור נוסף מהמשתמש לפני שממשיכים. אם היא מחזירה UNSURE, יש להשתמש בהליך הבדיקה המקומית הבא לאחר מכן.

  1. מגדירים את expressions כרשימה של ביטויי סיומת/קידומת שנוצרו על ידי כתובת ה-URL u.
  2. מגדירים את expressionHashes כרשימה, שבה הרכיבים הם גיבובי SHA256 של כל ביטוי ב-expressions.
  3. לכל hash מתוך expressionHashes:
    1. אם hash נמצא במטמון הגלובלי, מחזירים את הערך UNSURE.
  4. מגדירים את expressionHashPrefixes כרשימה, שבה הרכיבים הם 4 הבייטים הראשונים של כל גיבוב ב-expressionHashes.
  5. לכל expressionHashPrefix מתוך expressionHashPrefixes:
    1. מחפשים את expressionHashPrefix במטמון המקומי.
    2. אם נמצאה רשומה שנשמרה במטמון:
      1. קובעים אם הזמן הנוכחי ארוך יותר משעת התפוגה שלו.
      2. אם הוא גדול יותר:
        1. מסירים מהמטמון המקומי את הרשומה השמורה במטמון שנמצאה.
        2. ממשיכים עם הלולאה.
      3. אם הוא לא גדול יותר:
        1. צריך להסיר את הexpressionHashPrefix הספציפי הזה מ-expressionHashPrefixes.
        2. צריך לבדוק אם הגיבוב המלא התואם בתוך expressionHashes נמצא ברשומה שנשמרה במטמון.
        3. אם נמצאו, צריך להחזיר UNSAFE.
        4. אם הוא לא נמצא, ממשיכים עם הלולאה.
    3. אם הרשומה שנשמרה במטמון לא נמצאה, ממשיכים לבצע את הלולאה.
  6. שולחים את הקובץ expressionHashPrefixes לשרת גרסה 5 של הגלישה הבטוחה של Google באמצעות גיבובי חיפוש של RPC או באמצעות שיטת ה-REST hashes.search. אם התרחשה שגיאה (כולל שגיאות רשת, שגיאות HTTP וכו'), צריך להחזיר את הערך UNSURE. אחרת, יש לשלוח את התגובה response שהתקבלה משרת SB, זו רשימה של גיבובים מלאים עם פרטי עזר שמזהים את אופי האיום (הנדסה חברתית, תוכנות זדוניות וכו'), וכן את זמן התפוגה של המטמון expiration.
  7. לכל fullHash מתוך response:
    1. מוסיפים את fullHash למטמון המקומי, יחד עם expiration.
  8. לכל fullHash מתוך response:
    1. מגדירים את isFound כתוצאה של מציאת fullHash ב-expressionHashes.
    2. אם isFound מוגדר כ-False, ממשיכים עם הלולאה.
    3. אם הערך של isFound הוא True, הפונקציה מחזירה את הערך UNSAFE.
  9. החזרה במחיר SAFE.

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

הליך בדיקת כתובת ה-URL של רשימת האיומים המקומיים

משתמשים בתהליך הזה כשהלקוח בוחר לפעול במצב 'רשימה מקומית'. משתמשים בו גם כאשר הלקוח בהליך RealTimeCheck שלמעלה מחזיר את הערך של UNSURE.

ההליך הזה לוקח כתובת URL יחידה u ומחזיר את הערך SAFE או UNSAFE.

  1. מגדירים את expressions כרשימה של ביטויי סיומת/קידומת שנוצרו על ידי כתובת ה-URL u.
  2. מגדירים את expressionHashes כרשימה, שבה הרכיבים הם גיבובי SHA256 של כל ביטוי ב-expressions.
  3. מגדירים את expressionHashPrefixes כרשימה, שבה הרכיבים הם 4 הבייטים הראשונים של כל גיבוב ב-expressionHashes.
  4. לכל expressionHashPrefix מתוך expressionHashPrefixes:
    1. מחפשים את expressionHashPrefix במטמון המקומי.
    2. אם נמצאה רשומה שנשמרה במטמון:
      1. קובעים אם הזמן הנוכחי ארוך יותר משעת התפוגה שלו.
      2. אם הוא גדול יותר:
        1. מסירים מהמטמון המקומי את הרשומה השמורה במטמון שנמצאה.
        2. ממשיכים עם הלולאה.
      3. אם הוא לא גדול יותר:
        1. צריך להסיר את הexpressionHashPrefix הספציפי הזה מ-expressionHashPrefixes.
        2. צריך לבדוק אם הגיבוב המלא התואם בתוך expressionHashes נמצא ברשומה שנשמרה במטמון.
        3. אם נמצאו, צריך להחזיר UNSAFE.
        4. אם הוא לא נמצא, ממשיכים עם הלולאה.
    3. אם הרשומה שנשמרה במטמון לא נמצאה, ממשיכים לבצע את הלולאה.
  5. לכל expressionHashPrefix מתוך expressionHashPrefixes:
    1. צריך לחפש את expressionHashPrefix במסד הנתונים המקומי של רשימת האיומים.
    2. אם לא ניתן למצוא את expressionHashPrefix במסד הנתונים המקומי של רשימת האיומים, צריך להסיר אותו מ-expressionHashPrefixes.
  6. שולחים את הקובץ expressionHashPrefixes לשרת גרסה 5 של הגלישה הבטוחה של Google באמצעות גיבובי חיפוש של RPC או באמצעות שיטת ה-REST hashes.search. אם התרחשה שגיאה (כולל שגיאות רשת, שגיאות HTTP וכו'), צריך להחזיר את הערך SAFE. אחרת, יש לשלוח את התגובה response שהתקבלה משרת SB, זו רשימה של גיבובים מלאים עם פרטי עזר שמזהים את אופי האיום (הנדסה חברתית, תוכנות זדוניות וכו'), וכן את זמן התפוגה של המטמון expiration.
  7. לכל fullHash מתוך response:
    1. מוסיפים את fullHash למטמון המקומי, יחד עם expiration.
  8. לכל fullHash מתוך response:
    1. מגדירים את isFound כתוצאה של מציאת fullHash ב-expressionHashes.
    2. אם isFound מוגדר כ-False, ממשיכים עם הלולאה.
    3. אם הערך של isFound הוא True, הפונקציה מחזירה את הערך UNSAFE.
  9. החזרה במחיר SAFE.

הליך בדיקת כתובות ה-URL בזמן אמת ללא מסד נתונים מקומי

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

ההליך הזה לוקח כתובת URL יחידה u ומחזיר את הערך SAFE או UNSAFE.

  1. מגדירים את expressions כרשימה של ביטויי סיומת/קידומת שנוצרו על ידי כתובת ה-URL u.
  2. מגדירים את expressionHashes כרשימה, שבה הרכיבים הם גיבובי SHA256 של כל ביטוי ב-expressions.
  3. מגדירים את expressionHashPrefixes כרשימה, שבה הרכיבים הם 4 הבייטים הראשונים של כל גיבוב ב-expressionHashes.
  4. לכל expressionHashPrefix מתוך expressionHashPrefixes:
    1. מחפשים את expressionHashPrefix במטמון המקומי.
    2. אם נמצאה רשומה שנשמרה במטמון:
      1. קובעים אם הזמן הנוכחי ארוך יותר משעת התפוגה שלו.
      2. אם הוא גדול יותר:
        1. מסירים מהמטמון המקומי את הרשומה השמורה במטמון שנמצאה.
        2. ממשיכים עם הלולאה.
      3. אם הוא לא גדול יותר:
        1. צריך להסיר את הexpressionHashPrefix הספציפי הזה מ-expressionHashPrefixes.
        2. צריך לבדוק אם הגיבוב המלא התואם בתוך expressionHashes נמצא ברשומה שנשמרה במטמון.
        3. אם נמצאו, צריך להחזיר UNSAFE.
        4. אם הוא לא נמצא, ממשיכים עם הלולאה.
    3. אם הרשומה שנשמרה במטמון לא נמצאה, ממשיכים לבצע את הלולאה.
  5. שולחים את הקובץ expressionHashPrefixes לשרת גרסה 5 של הגלישה הבטוחה של Google באמצעות גיבובי חיפוש של RPC או באמצעות שיטת ה-REST hashes.search. אם התרחשה שגיאה (כולל שגיאות רשת, שגיאות HTTP וכו'), צריך להחזיר את הערך SAFE. אחרת, יש לשלוח את התגובה response שהתקבלה משרת SB, זו רשימה של גיבובים מלאים עם פרטי עזר שמזהים את אופי האיום (הנדסה חברתית, תוכנות זדוניות וכו'), וכן את זמן התפוגה של המטמון expiration.
  6. לכל fullHash מתוך response:
    1. מוסיפים את fullHash למטמון המקומי, יחד עם expiration.
  7. לכל fullHash מתוך response:
    1. מגדירים את isFound כתוצאה של מציאת fullHash ב-expressionHashes.
    2. אם isFound מוגדר כ-False, ממשיכים עם הלולאה.
    3. אם הערך של isFound הוא True, הפונקציה מחזירה את הערך UNSAFE.
  8. החזרה במחיר SAFE.

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

תחזוקה של מסדי נתונים מקומיים

הגלישה הבטוחה של Google בגרסה 5 מצפה מהלקוח לתחזק מסד נתונים מקומי, אלא אם הלקוח בוחר במצב 'זמן אמת ללא אחסון'. הפורמט והאחסון של מסד הנתונים המקומי הזה תלוי בלקוח. אפשר להתייחס לתוכן של מסד הנתונים המקומי הזה כתיקייה שמכילה רשימות שונות כקבצים, והתוכן של הקבצים האלה הוא גיבובים מסוג SHA256 או תחיליות גיבוב (hash).

עדכונים במסד הנתונים

הלקוח יקרא באופן קבוע ל-hashList.get method או ל-hashLists.batchGet כדי לעדכן את מסד הנתונים. מכיוון שהלקוח הטיפוסי ירצה לעדכן כמה רשימות בבת אחת, מומלץ להשתמש ב-hashLists.batchGet.

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

בניגוד לגרסה 4, ברשימות גרסה 5 אפשר לזהות רק לפי שם האיום, סוג הפלטפורמה וסוג האיומים. האפשרות הזו מספקת גמישות במקרים שבהם כמה רשימות של גרסה 5 יכולות להשתמש באותו סוג איום. סוגי הפלטפורמות וסוגי האיומים יוסרו בגרסה 5.

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

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

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

פענוח התוכן של הרשימה

פענוח גיבובים וקידומות של גיבוב

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

נניח ששלושה ביטויים עם קידומת נתיב בסיומת המארח, כלומר a.example.com/, b.example.com/ ו-y.example.com/, יועברו באמצעות קידומות גיבוב של 4 בייטים. בנוסף, נניח שהפרמטר Rice, שנקבע ב-k, נבחר להיות 30. השרת יתחיל לחשב את הגיבוב המלא של המחרוזות האלה, בהתאמה:

291bc5421f1cd54d99afcc55d166e2b9fe42447025895bf09dd41b2110a687dc  a.example.com/
1d32c5084a360e58f1b87109637a6810acad97a861a7769e8f1841410d2a960c  b.example.com/
f7a502e56e8b01c6dc242b35122683c9d25d07fb1f532d9853eb0ef3ff334f03  y.example.com/

לאחר מכן השרת יוצר קידומות גיבוב של 4 בייטים לכל אחת מהאפשרויות שלמעלה, שהן 4 הבייטים הראשונים של הגיבוב המלא בגודל 32 בייטים, מפורשים כמספרים שלמים מסוג Big Endian של 32 ביט. המשמעות של Big endianness היא שהבייט הראשון של הגיבוב השלם הופך לבייט המשמעותי ביותר מתוך המספר השלם בן 32 סיביות. בשלב הזה יתקבלו המספרים השלמים 0x291bc542, 0x1d32c508 ו-0xf7a502e5.

השרת צריך למיין את שלוש הקידומות הגיבוב באופן לקסיקוגרפי (מקביל למיון מספרי באנדיאן גדול), ותוצאת המיון היא 0x1d32c508, 0x291bc542, 0xf7a502e5. קידומת הגיבוב הראשונה נשמרת ללא שינוי בשדה first_value.

לאחר מכן השרת מחשב את שני ההבדלים הסמוכים, שהם 0xbe9003a ו-0xce893da3 בהתאמה. בהינתן ש-k נבחר להיות 30, השרת מפצל את שני המספרים האלה לחלקי המנה ואת שאר החלקים באורך של 2 ו-30 ביטים בהתאמה. במספר הראשון, החלק של המנה הוא אפס והשארית היא 0xbe9003a; במספר השני, חלק המנה הוא 3, כי שני הביטים המשמעותיים ביותר הם 11 בבינארי והשארית 0xe893da3. במנה נתונה q, הוא מקודד ל-(1 << q) - 1 באמצעות 1 + q ביטים בדיוק. השארית מקודדת ישירות באמצעות k ביטים. החלק של המנה במספר הראשון מקודד כ-0 והחלק הנותר הוא בבינארי 001011111010010000000000111010. החלק של המנה של המספר השני מקודד כ-0111 והחלק הנותר הוא 001110100010010101.

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

001110100010010011110110100011 # Second number, remainder part
0111 # Second number, quotient part
001011111010010000000000111010 # First number, remainder part
0 # First number, quotient part

זה יהיה בשורה אחת,

00111010001001001111011010001101110010111110100100000000001110100

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

0 01110100 01001001 11101101 00011011 10010111 11010010 00000000 01110100

לאחר מכן, הקידוד האנדיאני הקטן לוקח כל בייט מימין ומכניס אותו ל-bytestring:

01110100
00000000
11010010
10010111
00011011
11101101
01001001
01110100
00000000

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

התוצאה הסופית

additions_four_bytes {
  first_value: 489866504
  rice_parameter: 30
  entries_count: 2
  encoded_data: "t\000\322\227\033\355It\000"
}

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

פענוח אינדקסים להסרת קידוד

אינדקסים להסרה מקודדים באותה שיטה שצוינה למעלה באמצעות מספרים שלמים של 32 ביט. הקידוד והפענוח של אינדקסים להסרה לא השתנו בין גרסה 4 לגרסה 5.

רשימות זמינות

מומלץ להשתמש ברשימות הבאות בגרסה v5alpha1:

שם הרשימה גרסה 4 של ThreatType Enum תואם תיאור
gc אין הרשימה הזו היא רשימת מטמון גלובליות. זוהי רשימה מיוחדת שמשמשת רק במצב הפעולה 'זמן אמת'.
se SOCIAL_ENGINEERING הרשימה הזו מכילה איומים מסוג SOCIAL_ENGINEERING.
mw MALWARE הרשימה הזו מכילה איומים מסוג איומים מסוג MALWARE בפלטפורמות של מחשבים.
uws UNWANTED_SOFTWARE הרשימה הזו מכילה איומים מסוג איומים מסוג UNWANTED_SOFTWARE בפלטפורמות למחשבים.
uwsa UNWANTED_SOFTWARE הרשימה הזו מכילה איומים מסוג איומים מסוג UNWANTED_SOFTWARE בפלטפורמות Android.
pha POTENTIALLY_HARMFUL_APPLICATION הרשימה הזו מכילה איומים מסוג איומים מסוג POTENTIALLY_HARMFUL_APPLICATION בפלטפורמות Android.

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

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

תדירות עדכון

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

דוגמאות לבקשות

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

הנה דוגמה לבקשת HTTP באמצעות hashes.search method:

GET https://safebrowsing.googleapis.com/v5/hashes:search?key=INSERT_YOUR_API_KEY_HERE&hashPrefixes=WwuJdQ

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

לפניכם דוגמה לבקשת HTTP באמצעות hashLists.batchGet:

GET https://safebrowsing.googleapis.com/v5alpha1/hashLists:batchGet?key=INSERT_YOUR_API_KEY_HERE&names=se&names=mw

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

מדריך להעברת נתונים (מיגרציה)

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

עדכונים של רשימת ההמרות

בגרסה 4, משתמשים בשיטת threatListUpdates.fetch כדי להוריד רשימות. בגרסה 5, אחד מהם יעבור ל-hashLists.batchGet.

בבקשה צריך לבצע את השינויים הבאים:

  1. מסירים לגמרי את האובייקט ClientInfo מגרסה 4. במקום לספק זיהוי של הלקוח באמצעות שדה ייעודי, פשוט משתמשים בכותרת הסוכן המשתמש המוכרת. אמנם אין פורמט קבוע לציון זיהוי הלקוח בכותרת הזו, אבל אנחנו מציעים פשוט לכלול את מזהה הלקוח המקורי ואת גרסת הלקוח ולהפריד ביניהם בתו רווח או בתו לוכסן.
  2. לכל אובייקט ListUpdateRequest v4:
    • מחפשים את שם הרשימה המתאימה של גרסה 5 בטבלה שלמעלה ומציינים את השם הזה בבקשת גרסה 5.
    • צריך להסיר שדות לא נחוצים כמו threat_entry_type או platform_type.
    • השדה state בגרסה 4 תואם ישירות לשדה versions בגרסה 5. את אותה מחרוזת בייט שנשלחת לשרת באמצעות השדה state ב-v4 אפשר פשוט לשלוח ב-v5 באמצעות השדה versions.
    • במגבלות של גרסה 4, גרסה 5 משתמשת בגרסה פשוטה יותר שנקראת SizeConstraints. צריך להסיר שדות נוספים כמו region.

יש לבצע את השינויים הבאים בתגובה:

  1. הערך של v4 enum ResponseType פשוט מוחלף בשדה בוליאני בשם partial_update.
  2. השדה minimum_wait_duration יכול להיות אפס או יושמט. במקרה כזה, הלקוח יתבקש להגיש בקשה נוספת באופן מיידי. זה קורה רק כשהלקוח מציין ב-SizeConstraints אילוץ קטן יותר על גודל עדכון מקסימלי מהגודל המקסימלי של מסד הנתונים.
  3. צריך לשנות את האלגוריתם לפענוח 'אורז' של מספרים שלמים של 32 ביט. ההבדל הוא שהנתונים המקודדים מקודדים בהתאמה שונה. גם ב-v4 וגם ב-v5, קידומות גיבוב של 32 ביט ממוינות באופן לקסיקוגרפי. אבל ב-v4 הקידומות האלה נחשבות 'אנדיאניות קטנות' כשהן ממוינות, ואילו ב-v5 הקידומות האלה נחשבות 'אנדיאניות גדולות' כשהן ממוינות. המשמעות היא שהלקוח לא צריך לבצע מיון כלשהו, כי מיון לפי סדר מילוני זהה למיון מספרי עם קצה גדול. דוגמה לסוג כזה בהטמעה של גרסה 4 ב-Chromium זמינה כאן. אפשר להסיר מיון כזה.
  4. יש להטמיע את אלגוריתם פענוח ה-Rice עבור אורכי גיבוב (hash) אחרים.

המרת חיפושי Hash

בגרסה 4, צריך להשתמש בmethod של fullHashes.find כדי לקבל גיבובים מלאים. השיטה המקבילה ב-v5 היא שיטת hashes.search.

בבקשה צריך לבצע את השינויים הבאים:

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

יש לבצע את השינויים הבאים בתגובה:

  1. השדה minimum_wait_duration הוסר. הלקוח תמיד יכול לשלוח בקשה חדשה לפי הצורך.
  2. האובייקט v4 ThreatMatch הופשט והופך לאובייקט FullHash.
  3. השמירה במטמון הפכה לפשוטה יותר למשך זמן של מטמון אחד. יש לעיין בתהליכים שלמעלה לאינטראקציה עם המטמון.