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 działania. 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. Chroń te konta, włączając uwierzytelnianie dwuskładnikowe, najlepiej za pomocą klucza bezpieczeństwa.
Używaj odpowiednich ról członków
Jeśli wydawca ma wielu członków, sprawdź, czy rola przyznana każdemu użytkownikowi jest odpowiednia.
Nigdy nie używaj HTTP
Podczas wysyłania danych lub przesyłania żądań unikaj połączenia HTTP. Załóż, że połączenia HTTP będą podsłuchiwane lub modyfikowane. Zawsze należy preferować HTTPS, ponieważ ma 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 zależą.
Ograniczenie uprawnień rozszerzenia ogranicza możliwości potencjalnego atakującego.
Pobieranie z innej domeny
Rozszerzenie może używać tylko fetch() i XMLHttpRequest(), aby pobierać zasoby z rozszerzenia i z domen określonych w uprawnieniach. Pamiętaj, że wywołania obu tych funkcji są przechwytywane przez moduł obsługi fetch w usłudze Service Worker.
{
"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
}
Rozszerzenie w przykładzie powyżej żąda dostępu do wszystkich treści na stronie developer.chrome.com i w subdomenach Google, co jest określone przez "https://developer.chrome.com/*" i "https://*.google.com/*" na liście uprawnień. 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 będzie mieć ograniczoną możliwość dostępu do "https://user_bank_info.com" lub interakcji z "https://malicious_website.com".
Ograniczanie pól pliku manifestu
Umieszczanie w pliku manifestu niepotrzebnych kluczy i uprawnień stwarza luki w zabezpieczeniach i zwiększa widoczność rozszerzenia. Ogranicz pola pliku manifestu do tych, na których polega rozszerzenie.
Możliwość połączenia zewnętrznego
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 z zewnętrznymi zaufanymi źródłami.
{
"name": "Super Safe Extension",
"externally_connectable": {
"ids": [
"iamafriendlyextensionhereisdatas"
],
"matches": [
"https://developer.chrome.com/*",
"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": [
{
"resources": [ "test1.png", "test2.png" ],
"matches": [ "https://web-accessible-resources-1.glitch.me/*" ]
}
]
...
}
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.
zawierać wyraźną politykę bezpieczeństwa treści;
W pliku manifestu rozszerzenia umieść zasady bezpieczeństwa treści, aby zapobiec atakom typu cross-site scripting. Jeśli rozszerzenie wczytuje tylko zasoby z samego siebie, zarejestruj te elementy:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": {
"extension_pages": "default-src 'self'"
},
"manifest_version": 3
}
Jeśli rozszerzenie musi korzystać z WebAssembly lub zwiększyć ograniczenia dotyczące stron w piaskownicy, można je dodać:
{
"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
}
Unikaj document.write() i innerHTML
Dynamiczne tworzenie elementów HTML za pomocą document.write() i 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);
}
Ostrożnie korzystaj ze skryptów treś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 wchodzić w interakcję z DOM stron internetowych, skrypty treści 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 mogą zostać przejęte przez atakującego, jeśli złośliwa strona internetowa naruszy proces renderowania.
Operacje wykorzystujące dane wrażliwe (np. prywatne informacje użytkownika) lub interfejsy API Chrome z dostępem do funkcji przeglądarki powinny być wykonywane w skrypcie service worker rozszerzenia. Unikaj przypadkowego udostępniania uprawnień rozszerzenia skryptom treści:
- Załóż, że wiadomości ze skryptu treści mogły zostać przygotowane przez osobę atakującą (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. informacji tajnych z rozszerzenia, danych z innych źródeł internetowych, historii przeglądania) do skryptów treści.
- Ograniczanie zakresu działań z podwyższonymi uprawnieniami, które mogą być wywoływane przez skrypty treści. Nie zezwalaj skryptom treści na wywoływanie żą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 metod
fetch()anibrowser.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.onMessageExternal tylko wtedy, gdy oczekuje komunikacji z zewnętrzną witryną lub rozszerzeniem. Zawsze sprawdzaj, czy nadawca jest zaufanym źródłem.
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";
browser.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.
browser.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.allowedAction)
console.log("This is an allowed action.");
});