Оставайтесь в безопасности

Расширения обладают особыми привилегиями в браузере, что делает их привлекательной целью для злоумышленников. Если расширение скомпрометировано, каждый пользователь этого расширения становится уязвимым для вредоносного и нежелательного вторжения. Обеспечьте безопасность расширения и защиту его пользователей, внедрив следующие методы.

Защита учетных записей разработчиков

Код расширения загружается и обновляется через учетные записи Google. Если учетные записи разработчиков будут взломаны, злоумышленник сможет напрямую распространить вредоносный код среди всех пользователей. Защитите эти учетные записи, включив двухфакторную аутентификацию , предпочтительно с использованием ключа безопасности .

Используйте соответствующие роли участников.

Если у вашего издателя несколько сотрудников , убедитесь, что роль, предоставленная каждому пользователю, соответствует его статусу.

Никогда не используйте HTTP

При запросе или отправке данных избегайте HTTP-соединений. Предполагайте, что любые HTTP-соединения будут содержать перехватчики или содержать изменения. Всегда следует отдавать предпочтение HTTPS, поскольку он имеет встроенную защиту, предотвращающую большинство атак типа «человек посередине» .

Запросить минимальные разрешения

Браузер Chrome ограничивает доступ расширения к тем правам, которые были явно запрошены в манифесте . Расширениям следует минимизировать свои разрешения, регистрируя только API и веб-сайты, от которых они зависят.

Ограничение прав доступа расширения ограничивает возможности потенциального злоумышленника по использованию уязвимостей.

Cross origin 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/*" ]
    }
  ]
  ...
}

Чем больше доступных в интернете ресурсов, тем больше возможностей для злоумышленника может использовать уязвимость. Сведите количество таких файлов к минимуму.

Включите явную политику безопасности контента.

Включите в манифест политику безопасности контента для расширения, чтобы предотвратить атаки межсайтового скриптинга. Если расширение загружает ресурсы только само с себя, зарегистрируйте следующее:

{
  "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 или усилить ограничения на страницы в изолированной среде , их можно добавить:

{
  "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 ), а также для захвата злоумышленником, если вредоносная веб-страница скомпрометирует процесс рендеринга.

Операции, использующие конфиденциальные данные (например, личную информацию пользователя) или API Chrome с доступом к функциям браузера, следует выполнять в сервис-воркере расширений. Избегайте случайного раскрытия прав доступа расширений скриптам контента:

  • Предположим, что сообщения из скрипта контента могли быть созданы злоумышленником (например, необходимо проверять и очищать все входные данные и защищать ваши скрипты от межсайтового скриптинга ).
  • Следует исходить из того, что любые данные, отправляемые в скрипт контента, могут попасть на веб-страницу. Не отправляйте конфиденциальные данные (например, секреты расширения, данные с других веб-ресурсов, историю просмотров) в скрипты контента.
  • Ограничьте область действия привилегированных действий, которые могут быть запущены скриптами содержимого. Не позволяйте скриптам содержимого запускать запросы к произвольным 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 из самого расширения, следует тщательно проверять, чтобы убедиться, что отправитель сообщения не является результатом использования скомпрометированного скрипта содержимого .

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.allowedAction)
    console.log("This is an allowed action.");
});