הגנה על החשבון

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

הגנה על חשבונות פיתוח

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

בוחרים קבוצות.

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

לא להשתמש ב-HTTP אף פעם

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

בקשת הרשאות מינימליות

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

הגבלת ההרשאות של תוסף מגבילה את מה שתוקף פוטנציאלי יכול לנצל.

אחזור חוצה-מקורות (() )

תוסף יכול להשתמש רק ב-fetch() וב-XMLHttpRequest() כדי לקבל משאבים מהתוסף ומדומיינים שצוינו בהרשאות. שימו לב שקריאות לשניהם מיוטות על ידי ה-handler של fetch ב-Service Worker.

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
  "host_permissions": [
    "https://developer.chrome.com/*",
    "https://*.google.com/*"
  ],
  "manifest_version": 3
}

התוסף הזה, בדוגמה שלמעלה, מבקש גישה לכל דבר ב-developer.chrome.com ובתת-דומיינים של Google על ידי רישום "https://developer.chrome.com/*" ו-"https://*.google.com/*" בהרשאות. אם התוסף נפרץ, עדיין תהיה לו הרשאה לקיים אינטראקציה עם אתרים שעומדים בדפוס ההתאמה. לתוקף תהיה רק יכולת גישה מוגבלת ל-"https://user_bank_info.com" או לאינטראקציה עם "https://malicious_website.com".

הגבלה של שדות מניפסט

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

ניתן לחיבור חיצוני

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

{
  "name": "Super Safe Extension",
  "externally_connectable": {
    "ids": [
      "iamafriendlyextensionhereisdatas"
    ],
    "matches": [
      "https://developer.chrome.com/*",
      "https://*.google.com/*"
    ],
    "accepts_tls_channel_id": false
  },
  ...
}

משאבים נגישים באינטרנט

אם יש משאבים נגישים באינטרנט, במסגרת "web_accessible_resources", האתרים והתוקפים יוכלו לזהות את התוסף.

{
  ...
  "web_accessible_resources": [
    {
      "resources": [ "test1.png", "test2.png" ],
      "matches": [ "https://web-accessible-resources-1.glitch.me/*" ]
    }
  ]
  ...
}

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

לכלול מדיניות בנושא אבטחת תוכן בוטה

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

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
   "content_security_policy": {
    "extension_pages": "default-src 'self'"
  },
  "manifest_version": 3
}

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

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
   "content_security_policy": {
    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';",
    "sandboxed_pages":"script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
  },

  "manifest_version": 3
}

הימנעות מ-Document.write() ומ-innerHTML

ייתכן שיהיה פשוט יותר ליצור באופן דינמי רכיבי HTML באמצעות document.write() ו-innerHTML, אבל הוא משאיר את התוסף ואת דפי האינטרנט שהתוסף תלוי בהם, והם פתוחים לתוקפים שמוסיפים סקריפטים זדוניים. במקום זאת, צריך ליצור צומתי DOM באופן ידני ולהשתמש ב-innerText כדי להוסיף תוכן דינמי.

function constructDOM() {
  let newTitle = document.createElement('h1');
  newTitle.innerText = host;
  document.appendChild(newTitle);
}

שימוש זהיר בסקריפטים של תוכן

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

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

פעולות שכוללות מידע אישי רגיש (כמו פרטים אישיים של המשתמש) או ממשקי API של Chrome עם גישה לפונקציות של הדפדפן צריכות להתבצע בקובץ השירות (service worker) של התוספים. נמנעים מחשיפת הרשאות תוסף בטעות לסקריפטים של תוכן:

  • יש להניח שהודעות מסקריפט של תוכן נוצרו על ידי תוקפים (למשל, אימות וניקוי של כל הקלט, והגנה על הסקריפטים מפני יצירת סקריפטים חוצי אתרים).
  • יש להניח שנתונים שנשלחים לסקריפט התוכן עלולים להיות דלפים לדף האינטרנט. אין לשלוח מידע אישי רגיש (למשל סודות מהתוסף, נתונים ממקורות אחרים באינטרנט, היסטוריית גלישה) לסקריפטים של תוכן.
  • הגבילו את היקף הפעולות המורשות שסקריפטים של תוכן יכולים להפעיל. אסור לאפשר לסקריפטים של תוכן להפעיל בקשות לכתובות URL שרירותיות או להעביר ארגומנטים שרירותיים לממשקי API של תוספים (למשל, אסור להעביר כתובות URL שרירותיות לשיטות fetch() או chrome.tabs.create()).

רישום וניקוי של מקורות קלט

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

תוסף צריך להירשם ל-runtime.onMessageExternal רק אם הוא מצפה לתקשורת מאתר חיצוני או מתוסף חיצוני. חשוב לוודא תמיד שהשולח תואם למקור מהימן.

// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.id === kFriendlyExtensionId)
      doSomething();
});

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

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.allowedAction)
    console.log("This is an allowed action.");
});