לתוספים יש גישה להרשאות מיוחדות בדפדפן, ולכן הם מהווים יעד אטרקטיבי לתוקפים. אם תוסף נפרץ, כל משתמש בתוסף הזה הופך לפגיע לפריצות זדוניות ולחדירות לא רצויות. כדי לשמור על האבטחה של התוסף ועל ההגנה על המשתמשים, כדאי להשתמש בשיטות הבאות.
הגנה על חשבונות פיתוח
קוד התוסף מועלה ומתעדכן דרך חשבונות Google. אם חשבונות המפתחים ייפרצו, התוקף יוכל להעביר קוד זדוני ישירות לכל המשתמשים. כדי להגן על החשבונות האלה, כדאי ליצור חשבונות מפתחים ספציפיים ולהפעיל אימות דו-שלבי, רצוי באמצעות מפתח אבטחה .
שמירת קבוצות באופן סלקטיבי
אם משתמשים בפרסום קבוצתי, חשוב להגביל את הקבוצה למפתחים מהימנים. אל תאשרו בקשות הצטרפות מאנשים שאתם לא מכירים.
לעולם לא להשתמש ב-HTTP
כשמבקשים או שולחים נתונים, צריך להימנע מחיבור HTTP. צריך להניח שחיבורי HTTP יהיו חשופים להאזנות או לשינויים. תמיד עדיף להשתמש ב-HTTPS, כי יש לו אבטחה מובנית שמונעת את רוב המתקפות מסוג Man-in-the-middle.
בקשת הרשאות מינימליות
דפדפן 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"
],
...
}
ככל שיש יותר משאבים שנגישים דרך האינטרנט, כך יש לתוקף פוטנציאלי יותר דרכים לנצל אותם. כדאי להקטין את מספר הקבצים האלה.
לכלול מדיניות מפורשת לאבטחת תוכן
כדי למנוע מתקפות שמקורן בפרצת אבטחה XSS (cross-site scripting), צריך לכלול מדיניות אבטחת תוכן עבור התוסף במניפסט. אם התוסף טוען רק משאבים מעצמו, צריך לרשום את הדברים הבאים:
{
"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 של דפי אינטרנט, סקריפטים של תוכן צריכים לפעול באותו תהליך עיבוד (renderer) כמו דף האינטרנט. כך סקריפטים של תוכן חשופים לדליפת נתונים דרך מתקפות בערוצים צדדיים (למשל, Spectre), וגם להשתלטות של תוקף אם דף אינטרנט זדוני פוגע בתהליך העיבוד.
צריך לבצע עבודה רגישה בתהליך ייעודי, כמו סקריפט הרקע של התוסף. כדי להימנע מחשיפה לא מכוונת של הרשאות התוסף לסקריפטים של תוכן:
- צריך להניח שהודעות מסקריפט תוכן עשויות להיות מנוסחות על ידי תוקף (למשל, צריך לאמת ולנקות את כל הקלט ולהגן על הסקריפטים מפני פרצת אבטחה XSS (cross-site scripting)).
- צריך להניח שכל נתון שנשלח לסקריפט התוכן עלול לדלוף לדף האינטרנט. אל תשלחו מידע אישי רגיש (למשל, סודות מהתוסף, נתונים ממקורות אינטרנט אחרים, היסטוריית גלישה) לסקריפטים של תוכן.
- להגביל את היקף הפעולות בעלות הרשאות שאפשר להפעיל באמצעות סקריפטים של תוכן. אין לאפשר לסקריפטים של תוכן להפעיל בקשות לכתובות 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, '&').replace(/</g, '<').replace(/"/g, '"');
}