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

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

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

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

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

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

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

כשמבקשים או שולחים נתונים, צריך להימנע מחיבור HTTP. צריך להניח שחיבורי HTTP יהיו חשופים להאזנות או לשינויים. תמיד עדיף להשתמש ב-HTTPS, כי יש לו אבטחה מובנית שמונעת את רוב המתקפות מסוג Man-in-the-middle.

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

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

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

‫fetch()‎ חוצה-דומיינים

תוסף יכול להשתמש רק ב-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/*" ]
    }
  ]
  ...
}

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

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

כדי למנוע מתקפות שמקורן בפרצת אבטחה XSS ‏(cross-site scripting), צריך לכלול מדיניות אבטחת תוכן עבור התוסף במניפסט. אם התוסף טוען רק משאבים מעצמו, צריך לרשום את הדברים הבאים:

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

אם התוסף צריך להשתמש ב-WebAssembly או להגדיל את ההגבלות על דפים ב-Sandbox, אפשר להוסיף אותם:

{
  "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 של דפי אינטרנט, סקריפטים של תוכן צריכים לפעול באותו תהליך עיבוד (renderer) כמו דף האינטרנט. כך סקריפטים של תוכן חשופים לדליפת נתונים דרך מתקפות בערוצים צדדיים (למשל, Spectre), וגם להשתלטות של תוקף אם דף אינטרנט זדוני פוגע בתהליך העיבוד.

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

  • צריך להניח שהודעות מסקריפט תוכן עשויות להיות מנוסחות על ידי תוקף (למשל, צריך לאמת ולנקות את כל הקלט ולהגן על הסקריפטים מפני פרצת אבטחה XSS‏ (cross-site scripting)).
  • צריך להניח שכל נתון שנשלח לסקריפט התוכן עלול לדלוף לדף האינטרנט. אל תשלחו מידע אישי רגיש (למשל, סודות מהתוסף, נתונים ממקורות אינטרנט אחרים, היסטוריית גלישה) לסקריפטים של תוכן.
  • להגביל את היקף הפעולות בעלות הרשאות שאפשר להפעיל באמצעות סקריפטים של תוכן. אל תאפשרו לסקריפטים של תוכן להפעיל בקשות לכתובות 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.");
});