ایمن بمان

افزونه‌ها به امتیازات ویژه‌ای در مرورگر دسترسی دارند و همین امر آنها را به هدف جذابی برای مهاجمان تبدیل می‌کند. اگر یک افزونه به خطر بیفتد، هر کاربر آن افزونه در برابر نفوذ مخرب و ناخواسته آسیب‌پذیر می‌شود. با به‌کارگیری این شیوه‌ها، افزونه و کاربران آن را ایمن نگه دارید.

محافظت از حساب‌های توسعه‌دهندگان

کد افزونه از طریق حساب‌های گوگل آپلود و به‌روزرسانی می‌شود. اگر حساب‌های توسعه‌دهندگان به خطر بیفتد، یک مهاجم می‌تواند کد مخرب را مستقیماً به همه کاربران ارسال کند. با ایجاد حساب‌های کاربری مخصوص توسعه‌دهندگان و فعال کردن احراز هویت دو مرحله‌ای ، ترجیحاً با یک کلید امنیتی ، از این حساب‌ها محافظت کنید.

گروه‌ها را گزینشی نگه دارید

اگر از انتشار گروهی استفاده می‌کنید، گروه را محدود به توسعه‌دهندگان مورد اعتماد نگه دارید. درخواست‌های عضویت از افراد ناشناس را نپذیرید.

هرگز از HTTP استفاده نکنید، هرگز

هنگام درخواست یا ارسال داده، از اتصال HTTP خودداری کنید. فرض کنید که هرگونه اتصال HTTP دارای استراق سمع یا حاوی تغییرات خواهد بود. HTTPS همیشه باید ترجیح داده شود، زیرا دارای امنیت داخلی است که اکثر حملات مرد میانی را دور می‌زند.

درخواست حداقل مجوزها

مرورگر کروم دسترسی افزونه‌ها را به مجوزهایی که صریحاً در مانیفست درخواست شده‌اند، محدود می‌کند. افزونه‌ها باید مجوزهای خود را تنها با ثبت APIها و وب‌سایت‌هایی که به آنها وابسته هستند، به حداقل برسانند. کدهای دلخواه باید به حداقل برسند.

محدود کردن امتیازات یک افزونه، سوءاستفاده‌های احتمالی یک مهاجم را محدود می‌کند.

XMLHttpRequest چندمنبعی

یک افزونه فقط می‌تواند از XMLHttpRequest برای دریافت منابع از خودش و از دامنه‌های مشخص شده در مجوزها استفاده کند.

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

این افزونه با فهرست کردن "/*" و "https://*google.com/" در مجوزها، درخواست دسترسی به هر چیزی در developer.chrome.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"
  ],
  ...
}

هرچه منابع وب قابل دسترسی بیشتری در دسترس باشد، راه‌های بیشتری برای سوءاستفاده مهاجمان بالقوه وجود دارد. این فایل‌ها را به حداقل برسانید.

یک سیاست امنیتی محتوای صریح را لحاظ کنید

برای جلوگیری از حملات اسکریپت‌نویسی بین‌سایتی، یک سیاست امنیتی محتوا برای افزونه در مانیفست قرار دهید. اگر افزونه فقط منابع را از خودش بارگذاری می‌کند، موارد زیر را ثبت کنید:

{
  "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() هر کدی که به آن ارسال شود و ممکن است مخرب باشد را اجرا خواهد کرد.

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های دلخواه به fetch یا chrome.tabs.create API را ندهید).

ثبت و پاکسازی ورودی‌ها

با محدود کردن شنونده‌ها به آنچه افزونه انتظار دارد، اعتبارسنجی فرستنده‌های داده‌های ورودی و پاکسازی تمام ورودی‌ها، از یک افزونه در برابر اسکریپت‌های مخرب محافظت کنید.

یک افزونه فقط در صورتی باید برای 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;');
}