Dbaj o bezpieczeństwo

Rozszerzenia mają specjalne uprawnienia w przeglądarce, dzięki czemu są atrakcyjnym celem dla cyberprzestępców. Jeśli rozszerzenie zostanie przejęte, każdy jego użytkownik będzie narażony na złośliwe lub niechciane działania. Stosuj te metody, aby chronić rozszerzenia i użytkowników.

Ochrona kont deweloperów

Kod rozszerzenia jest przesyłany i aktualizowany za pomocą kont Google. Jeśli konto dewelopera zostanie przejęte, haker może wysłać złośliwy kod bezpośrednio na wszystkich użytkowników. Chroń te konta, tworząc specjalnie konta dewelopera i włączając uwierzytelnianie dwuskładnikowe, najlepiej za pomocą klucza bezpieczeństwa .

Wybiórcze grupy

Jeśli korzystasz z publikowania grupowego, grupa powinna być ograniczona do zaufanych deweloperów. Nie przyjmuj próśb o członkostwo od nieznanych osób.

Nigdy nie używaj HTTP

Wysyłając żądanie lub wysyłając dane, unikaj połączenia HTTP. Załóżmy, że wszystkie połączenia HTTP zawierają treści podsłuchujące lub zawierają modyfikacje. Protokół HTTPS powinien zawsze być preferowany, ponieważ ma wbudowane zabezpieczenia, które umożliwiają obejście większości ataków typu „man in the middle”.

Poproś o minimalne uprawnienia

Przeglądarka Chrome ogranicza dostęp rozszerzenia do uprawnień, o które prosisz w pliku manifestu. Rozszerzenia powinny zminimalizować uprawnienia, rejestrując tylko interfejsy API i witryny, od których są zależne. Dowolny kod należy ograniczyć do minimum.

Ograniczenie uprawnień dotyczących rozszerzeń ogranicza to, co może wykorzystać osoba przeprowadzająca atak.

Międzyźródłowe żądanie XMLHttpRequest

Rozszerzenie może używać żądania XMLHttpRequest tylko do pobierania zasobów z samego siebie i z domen określonych w uprawnieniach.

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

To rozszerzenie prosi o dostęp do wszystkich treści w witrynie developers.chrome.com i subdomenach Google, dodając w uprawnieniach uprawnienia "/*" i "https://*google.com/". Jeśli rozszerzenie zostanie przejęte, wciąż będzie miało uprawnienia do interakcji tylko ze stronami zgodnymi z wzorcem dopasowania. Osoba przeprowadzająca atak nie będzie mogła uzyskać dostępu do witryny "https://user_bank_info.com" ani wejść w interakcję z interfejsem "https://malicious_website.com".

Ogranicz pola manifestu

Uwzględnienie zbędnych rejestracji w pliku manifestu tworzy luki w zabezpieczeniach i sprawia, że rozszerzenie jest lepiej widoczne. Ogranicz pola w pliku manifestu do pól, na których działa rozszerzenie, i włącz rejestrację w określonym polu.

Możliwość podłączenia z zewnątrz

W polu externally_connectable możesz określić, z którymi zewnętrznymi rozszerzeniami i stronami internetowymi rozszerzenie będzie wymieniać informacje. Ogranicz osoby, z którymi rozszerzenie może nawiązywać zewnętrzne połączenia, do zaufanych źródeł.

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

Zasoby dostępne przez internet

Jeśli udostępnisz zasoby w internecie w sekcji web_accessible_resources, witryny i osoby przeprowadzające ataki będą wykrywalne rozszerzenie.

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

Im więcej dostępnych zasobów internetowych znajdziesz w internecie, tym więcej możliwości może wykorzystać potencjalny przeprowadzający atak. Ogranicz ich liczbę do minimum.

Uwzględnij zasadę bezpieczeństwa treści dla pełnoletnich

Dodaj do pliku manifestu politykę bezpieczeństwa treści rozszerzenia, aby zapobiec atakom typu cross-site scripting. Jeśli rozszerzenie wczytuje zasoby tylko od samego siebie, zarejestruj te elementy:

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

Jeśli rozszerzenie musi zawierać skrypty z określonych hostów, możesz je dodać:

{
  "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
}

Unikanie wykonywalnych interfejsów API

Interfejsy API, które wykonują kod, należy zastąpić bezpieczniejszymi alternatywami.

document.write() i innerHTML

Chociaż dynamiczne tworzenie elementów HTML za pomocą document.write() i innerHTML może być prostsze, to opuszcza rozszerzenie i strony internetowe, od których to rozszerzenie jest uzależnione, ale hakerzy mogą wstawiać złośliwe skrypty. Zamiast tego ręcznie twórz węzły DOM i wstawiaj zawartość dynamiczną przy użyciu metody innerText.

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

eval()

Gdy tylko jest to możliwe, unikaj używania metody eval(), aby zapobiegać atakom, ponieważ eval() wykonuje każdy przekazany do niego kod, który może być złośliwy.

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();

Zamiast tego używaj bezpieczniejszych i szybszych metod takich jak 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();

Ostrożnie korzystaj ze skryptów treści

Chociaż skrypty treści mieszkają w odizolowanym świecie, nie są odporne na ataki:

  • Skrypty treści to jedyna część rozszerzenia, która wchodzi w bezpośrednią interakcję ze stroną internetową. Z tego powodu wrogie strony internetowe mogą manipulować częściami DOM, od których zależy skrypt treści, lub wykorzystywać zaskakujące działanie standardu internetowego, np. w postaci elementów z nazwą.
  • Aby wejść w interakcję z DOM stron internetowych, skrypty treści muszą być wykonywane w tym samym procesie renderowania co strona internetowa. To sprawia, że skrypty treści są podatne na wyciek danych w ramach ataków z kanałów dodatkowych (np. Spectre) i przejęta przez atakującego, jeśli szkodliwa strona internetowa naruszy mechanizm renderowania.

Poufne informacje powinny być wykonywane w ramach dedykowanego procesu, np. w skrypcie w tle rozszerzenia. Unikaj przypadkowego nadawania uprawnień związanych z rozszerzeniem skryptom treści:

Rejestrowanie i oczyszczenie danych wejściowych

Chroń rozszerzenie przed złośliwymi skryptami, ograniczając słuchacze tylko do tego, czego oczekuje rozszerzenie, weryfikowając nadawców przychodzących danych i oczyszczając wszystkie dane wejściowe.

Rozszerzenie można zarejestrować tylko pod kątem runtime.onRequestExternal, jeśli oczekuje ono komunikacji z zewnętrznej witryny lub rozszerzenia. Zawsze sprawdzaj, czy nadawca pasuje do zaufanego źródła.

// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.id === kFriendlyExtensionId)
      doSomething();
});

Nawet wiadomości wysyłane przez zdarzenie runtime.onMessage z samego rozszerzenia powinny być sprawdzane, aby mieć pewność, że MessageSender nie pochodzi z przejętego skryptu treści.

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

Zablokuj możliwość wykonywania skryptu ataku przez rozszerzenie, oczyszczając dane wejściowe użytkowników i dane przychodzące, nawet z samego rozszerzenia i zatwierdzonych źródeł. Unikaj wykonywalnych interfejsów API.

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