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

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

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

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

שמירה על קבוצות בררניות

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

לעולם לא להשתמש ב-HTTP

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

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

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

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

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

תוסף יכול להשתמש ב-fetch() וב-XMLHttpRequest() רק כדי לקבל משאבים מהתוסף ומדומיינים שצוינו בהרשאות. חשוב לזכור שהקריאות לשניהם מנותבות על ידי הטיפול ב-fetch בקובץ השירות.

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

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

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

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

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

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

תוסף צריך להירשם ל-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.");
});