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

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

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

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

בחירת קבוצות

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

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

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

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

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

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

XMLHttpRequest בין מקורות

תוסף יכול להשתמש ב-XMLHttpRequest רק כדי לקבל משאבים מעצמו ומדומיינים שצוינו בהרשאות.

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

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

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

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

אפשרות חיבור חיצונית

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

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

משאבים נגישים באמצעות האינטרנט

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

{
  ...
  "web_accessible_resources": [
    "images/*.png",
    "style/secure_extension.css",
    "script/secure_extension.js"
  ],
  ...
}

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

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

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

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

אם התוסף צריך לכלול סקריפטים ממארחים ספציפיים, אפשר לכלול אותם:

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
  "content_security_policy": "default-src 'self' https://extension.resource.com"
  "manifest_version": 2
}

הימנעות מממשקי API הניתנים להפעלה

צריך להחליף את ממשקי ה-API שמריצים את הקוד בחלופות בטוחות יותר.

document.write() ו-innerHTML

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

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

eval()

יש להימנע משימוש ב-eval() כשאפשר כדי למנוע התקפות, כי eval() יפעיל כל קוד שמועבר אליו, שעשוי להיות זדוני.

var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    // WARNING! Might be evaluating an evil script!
    var resp = eval("(" + xhr.responseText + ")");
    ...
  }
}
xhr.send();

במקום זאת, עדיף להשתמש בשיטות בטוחות ומהירה יותר כמו JSON.parse()

var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    // JSON.parse does not evaluate the attacker's scripts.
    var resp = JSON.parse(xhr.responseText);
  }
}
xhr.send();

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

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

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

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

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

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

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

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

// 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.");
});

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

function sanitizeInput(input) {
    return input.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
}