Erweiterungen haben Zugriff auf spezielle Berechtigungen im Browser, was sie zu einem attraktiven Ziel für Angreifer macht. Wenn eine Erweiterung manipuliert wird, ist jeder Nutzer dieser Erweiterung anfällig für schädliche und unerwünschte Eingriffe. Wenn Sie diese Praktiken anwenden, können Sie die Sicherheit einer Erweiterung und ihrer Nutzer gewährleisten.
Entwicklerkonten schützen
Der Erweiterungscode wird über Google-Konten hochgeladen und aktualisiert. Wenn die Konten von Entwicklern manipuliert werden, kann ein Angreifer schädlichen Code direkt an alle Nutzer senden. Schützen Sie diese Konten, indem Sie die 2-Faktor-Authentifizierung aktivieren, vorzugsweise mit einem Sicherheitsschlüssel.
Gruppen klein halten
Wenn Sie die Gruppenveröffentlichung verwenden, sollten Sie die Gruppe auf vertrauenswürdige Entwickler beschränken. Akzeptieren Sie keine Beitrittsanfragen von unbekannten Personen.
Nie HTTP verwenden
Vermeiden Sie beim Anfordern oder Senden von Daten eine HTTP-Verbindung. Angenommen, alle HTTP-Verbindungen werden abgehört oder enthalten Änderungen. HTTPS sollte immer bevorzugt werden, da es integrierte Sicherheitsfunktionen hat, die die meisten Man-in-the-Middle-Angriffe umgehen.
Mindestberechtigungen anfordern
Der Chrome-Browser schränkt den Zugriff einer Erweiterung auf Berechtigungen ein, die im manifest explizit angefordert wurden. Erweiterungen sollten ihre Berechtigungen minimieren, indem sie nur APIs und Websites registrieren, von denen sie abhängig sind.
Durch das Einschränken der Berechtigungen einer Erweiterung wird eingeschränkt, welche Informationen ein potenzieller Angreifer ausnutzen kann.
Cross-origin fetch()
Eine Erweiterung kann nur fetch()
und XMLHttpRequest()
verwenden, um Ressourcen aus der Erweiterung und aus den in den Berechtigungen angegebenen Domains abzurufen. Aufrufe beider werden vom fetch-Handler im Service Worker abgefangen.
{
"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
}
Mit dieser Erweiterung im Beispiel oben wird der Zugriff auf alle Inhalte auf developer.chrome.com und Subdomains von Google angefordert. Dazu werden "https://developer.chrome.com/*"
und "https://*.google.com/*"
in den Berechtigungen aufgeführt. Selbst wenn die Erweiterung manipuliert würde, hätte sie weiterhin nur die Berechtigung, mit Websites zu interagieren, die dem Abgleichsmuster entsprechen. Der Angreifer kann nur eingeschränkt auf "https://user_bank_info.com"
zugreifen oder mit "https://malicious_website.com"
interagieren.
Manifestfelder begrenzen
Wenn Sie unnötige Schlüssel und Berechtigungen in das Manifest aufnehmen, entstehen Sicherheitslücken und die Erweiterung wird sichtbarer. Beschränke Manifest-Felder auf die Felder, auf die sich die Erweiterung stützt.
Extern erreichbar
Verwenden Sie das Feld "externally_connectable"
, um anzugeben, mit welchen externen Erweiterungen und Webseiten die Erweiterung Informationen austauschen soll. Beschränken Sie, mit wem die Erweiterung extern eine Verbindung zu vertrauenswürdigen Quellen herstellen kann.
{
"name": "Super Safe Extension",
"externally_connectable": {
"ids": [
"iamafriendlyextensionhereisdatas"
],
"matches": [
"https://developer.chrome.com/*",
"https://*.google.com/*"
],
"accepts_tls_channel_id": false
},
...
}
Webzugriff
Wenn Sie Ressourcen unter "web_accessible_resources"
für das Web zugänglich machen, wird eine Erweiterung von Websites und Angreifern erkannt.
{
...
"web_accessible_resources": [
{
"resources": [ "test1.png", "test2.png" ],
"matches": [ "https://web-accessible-resources-1.glitch.me/*" ]
}
]
...
}
Je mehr webzugängliche Ressourcen verfügbar sind, desto mehr Möglichkeiten hat ein potenzieller Angreifer. Verwenden Sie möglichst wenige dieser Dateien.
Eine explizite Content Security Policy einschließen
Fügen Sie dem Manifest eine Content Security Policy für die Erweiterung hinzu, um Cross-Site-Scripting-Angriffe zu verhindern. Wenn die Erweiterung nur Ressourcen von sich selbst lädt, registrieren Sie Folgendes:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": {
"extension_pages": "default-src 'self'"
},
"manifest_version": 3
}
Wenn die Erweiterung Web Assembly verwenden oder die Einschränkungen für Sandbox-Seiten erhöhen muss, können Sie Folgendes hinzufügen:
{
"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
}
Vermeiden Sie „document.write()“ und „innerHTML“
Es ist zwar einfacher, HTML-Elemente mit document.write()
und innerHTML
dynamisch zu erstellen, aber dadurch sind die Erweiterung und die von ihr abhängigen Webseiten anfällig für Angreifer, die schädliche Scripts einschleusen. Erstellen Sie stattdessen manuell DOM-Knoten und fügen Sie mit innerText
dynamische Inhalte ein.
function constructDOM() {
let newTitle = document.createElement('h1');
newTitle.innerText = host;
document.appendChild(newTitle);
}
Inhaltsscripts mit Bedacht verwenden
Auch wenn Content-Scripts in einer abgeschirmten Umgebung laufen, sind sie nicht vor Angriffen gefeit:
- Inhaltsskripte sind der einzige Teil einer Erweiterung, der direkt mit der Webseite interagiert. Daher können schädliche Webseiten Teile des DOM manipulieren, von denen das Inhaltsskript abhängt, oder überraschendes Verhalten von Webstandards ausnutzen, z. B. benannte Elemente.
- Damit Sie mit dem DOM von Webseiten interagieren können, müssen Inhaltsskripte im selben Renderer-Prozess wie die Webseite ausgeführt werden. Dadurch sind Inhaltsscripts anfällig für Datenlecks über Side-Channel-Angriffe (z.B. Spectre) und von einem Angreifer übernommen werden, wenn eine schädliche Webseite den Renderingprozess manipuliert.
Vorgänge, bei denen vertrauliche Daten (z. B. personenbezogene Daten eines Nutzers) oder Chrome APIs mit Zugriff auf die Funktionen des Browsers verwendet werden, sollten im Service Worker der Erweiterung ausgeführt werden. So vermeiden Sie, dass Erweiterungsberechtigungen versehentlich für Inhaltsscripts freigegeben werden:
- Gehen Sie davon aus, dass Nachrichten aus einem Inhaltsskript von einem Angreifer erstellt wurden. Validieren und bereinigen Sie daher alle Eingaben und schützen Sie Ihre Scripts vor Cross-Site-Scripting.
- Angenommen, alle an das Inhaltsskript gesendeten Daten können an die Webseite weitergegeben werden. Senden Sie keine sensiblen Daten (z.B. Secrets aus der Erweiterung, Daten aus anderen Web-Quellen, Browserverlauf) an Inhaltsscripts.
- Begrenzen Sie den Umfang der privilegierten Aktionen, die durch Inhaltsscripts ausgelöst werden können. Es darf nicht möglich sein, dass Inhaltsscripts Anfragen an beliebige URLs auslösen oder beliebige Argumente an Erweiterungs-APIs übergeben. Das Übergeben beliebiger URLs an die Methoden
fetch()
oderchrome.tabs.create()
ist beispielsweise nicht zulässig.
Eingaben registrieren und bereinigen
Schützen Sie eine Erweiterung vor schädlichen Scripts, indem Sie Listener auf das beschränken, was von der Erweiterung erwartet wird, die Absender eingehender Daten validieren und alle Eingaben bereinigen.
Eine Erweiterung sollte sich nur dann für runtime.onMessageExternal
registrieren, wenn sie eine Kommunikation von einer externen Website oder Erweiterung erwartet. Prüfen Sie immer, ob der Absender einer vertrauenswürdigen Quelle entspricht.
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id === kFriendlyExtensionId)
doSomething();
});
Auch Nachrichten, die über das Ereignis runtime.onMessage von der Erweiterung selbst gesendet werden, sollten überprüft werden, um sicherzustellen, dass MessageSender nicht von einem manipulierten Inhaltsskript stammt.
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.allowedAction)
console.log("This is an allowed action.");
});