Dbaj o bezpieczeństwo

Rozszerzenia mają dostęp do specjalnych uprawnień w przeglądarce, co czyni je atrakcyjnym celem dla atakujących. Jeśli rozszerzenie zostanie przejęte, każdy użytkownik tego rozszerzenia staje się podatny na złośliwe i niechciane wtargnięcia. Zadbaj o bezpieczeństwo rozszerzenia i ochronę jego użytkowników, stosując te praktyki.

Ochrona kont deweloperów

Kod rozszerzenia jest przesyłany i aktualizowany za pomocą kont Google. Jeśli konta deweloperów zostaną przejęte, atakujący może przesłać złośliwy kod bezpośrednio do wszystkich użytkowników. Zabezpiecz te konta, tworząc specjalne konta dewelopera i włączając uwierzytelnianie dwuskładnikowe, najlepiej za pomocą klucza bezpieczeństwa .

Zachowaj grupy selektywne

Jeśli korzystasz z publikowania grupowego, ogranicz grupę do zaufanych deweloperów. Nie akceptuj próśb o dołączenie do grupy od nieznanych osób.

Nigdy nie używaj HTTP

Podczas wysyłania danych lub przesyłania próśb o nie unikaj połączenia HTTP. Załóż, że połączenia HTTP będą podsłuchiwane lub modyfikowane. Zawsze należy preferować protokół HTTPS, ponieważ ma on wbudowane zabezpieczenia, które pozwalają uniknąć większości ataków typu „man in the middle”.

Prośba o minimalne uprawnienia

Przeglądarka Chrome ogranicza dostęp rozszerzenia do uprawnień, o które wyraźnie poproszono w pliku manifestu. Rozszerzenia powinny ograniczać swoje uprawnienia, rejestrując tylko interfejsy API i strony, od których są zależne. Należy ograniczyć do minimum dowolny kod.

Ograniczenie uprawnień rozszerzenia ogranicza możliwości potencjalnego atakującego.

XMLHttpRequest z innej domeny

Rozszerzenie może używać 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 żąda dostępu do wszystkich treści na stronie developer.chrome.com i w subdomenach Google, co jest określone w uprawnieniach za pomocą symboli "/*""https://*google.com/". Jeśli rozszerzenie zostanie przejęte, nadal będzie miało uprawnienia tylko do interakcji ze stronami internetowymi, które spełniają wzorzec dopasowania. Atakujący nie będzie mógł uzyskać dostępu do "https://user_bank_info.com" ani wchodzić w interakcje z "https://malicious_website.com".

Ograniczanie pól pliku manifestu

Umieszczanie w pliku manifestu niepotrzebnych rejestracji stwarza luki w zabezpieczeniach i zwiększa widoczność rozszerzenia. Ogranicz pola pliku manifestu do tych, na których polega rozszerzenie, i podaj konkretną rejestrację pola.

Można połączyć zewnętrznie

W polu externally_connectable zadeklaruj, z którymi zewnętrznymi rozszerzeniami i stronami internetowymi rozszerzenie będzie wymieniać informacje. Ograniczanie możliwości łączenia się rozszerzenia ze źródłami zewnętrznymi do zaufanych źródeł.

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

Zasoby dostępne w internecie

Udostępnienie zasobów w internecie w sekcji web_accessible_resources sprawi, że rozszerzenie będzie wykrywalne przez witryny i osoby atakujące.

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

Im więcej zasobów dostępnych w internecie, tym więcej możliwości wykorzystania przez potencjalnego atakującego. Ogranicz liczbę tych plików do minimum.

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

W pliku manifestu rozszerzenia umieść zasady bezpieczeństwa treści, aby zapobiec atakom typu cross-site scripting. Jeśli rozszerzenie wczytuje zasoby tylko z 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 ma zawierać skrypty z określonych hostów, można je uwzględnić w ten sposób:

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

Unikaj interfejsów API, które można wykonywać

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

document.write() i innerHTML

Dynamiczne tworzenie elementów HTML za pomocą funkcji document.write()innerHTML może być prostsze, ale naraża rozszerzenie i strony internetowe, od których zależy, na wstawianie przez osoby atakujące złośliwych skryptów. Zamiast tego ręcznie utwórz węzły DOM i użyj innerText, aby wstawić treści dynamiczne.

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

eval()

Jeśli to możliwe, unikaj używania eval(), aby zapobiegać atakom, ponieważ eval() wykona 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 wybieraj bezpieczniejsze i szybsze metody, takie 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 dotyczących zawartości

Chociaż skrypty treści działają w izolowanym środowisku, 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 modelu DOM, od których zależy skrypt treści, lub wykorzystywać zaskakujące zachowania standardów internetowych, takie jak nazwane elementy.
  • Aby skrypty treści mogły wchodzić w interakcje z modelem DOM stron internetowych, muszą być wykonywane w tym samym procesie renderowania co strona internetowa. Sprawia to, że skrypty treści są podatne na wyciek danych w wyniku ataków z użyciem kanałów bocznych (np. Spectre) i na przejęcie przez atakującego, jeśli złośliwa strona internetowa naruszy proces renderowania.

Operacje wymagające zachowania poufności powinny być wykonywane w ramach dedykowanego procesu, np. w skrypcie działającym w tle rozszerzenia. Unikaj przypadkowego udostępniania uprawnień rozszerzenia skryptom dotyczącym zawartości:

  • Załóż, że wiadomości ze skryptu treści mogły zostać przygotowane przez osobę przeprowadzającą atak (np. sprawdzaj i oczyszczaj wszystkie dane wejściowe oraz chroń skrypty przed atakiem typu cross-site scripting).
  • Załóż, że wszystkie dane wysyłane do skryptu treści mogą wyciec na stronę internetową. Nie wysyłaj danych wrażliwych (np. kluczy tajnych z rozszerzenia, danych z innych źródeł internetowych, historii przeglądania) do skryptów treści.
  • Ograniczanie zakresu działań uprzywilejowanych, które mogą być wywoływane przez skrypty treści. Nie zezwalaj skryptom treści na wysyłanie żądań do dowolnych adresów URL ani na przekazywanie dowolnych argumentów do interfejsów API rozszerzeń (np. nie zezwalaj na przekazywanie dowolnych adresów URL do interfejsów API fetch lub chrome.tabs.create).

Rejestrowanie i oczyszczanie danych wejściowych

Chroń rozszerzenie przed złośliwymi skryptami, ograniczając detektory tylko do tych, których rozszerzenie oczekuje, weryfikując nadawców przychodzących danych i oczyszczając wszystkie dane wejściowe.

Rozszerzenie powinno rejestrować się w przypadku zdarzenia runtime.onRequestExternal tylko wtedy, gdy oczekuje komunikacji z zewnętrzną witryną lub rozszerzeniem. Zawsze sprawdzaj, czy nadawca pochodzi z 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ć dokładnie sprawdzane, aby upewnić się, że MessageSender nie pochodzi ze skompromitowanego skryptu treści.

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

Uniemożliwiaj rozszerzeniu wykonywanie skryptu atakującego, oczyszczając dane wejściowe użytkownika i dane przychodzące, nawet z samego rozszerzenia i zatwierdzonych źródeł. Unikaj interfejsów API, które można uruchamiać.

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