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 böswillige und unerwünschte Eingriffe. Wenn Sie diese Praktiken anwenden, können Sie Erweiterungen und ihre Nutzer schützen.
Entwicklerkonten schützen
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.
Geeignete Mitgliederrollen verwenden
Wenn Ihr Verlag mehrere Mitglieder hat, achten Sie darauf, dass die Rolle, die jedem Nutzer zugewiesen wird, angemessen ist.
Nie HTTP verwenden
Vermeiden Sie beim Anfordern oder Senden von Daten eine HTTP-Verbindung. Gehen Sie davon aus, dass HTTP-Verbindungen abgehört werden oder Änderungen enthalten. HTTPS sollte immer bevorzugt werden, da es integrierte Sicherheitsfunktionen hat, die die meisten Man-in-the-Middle-Angriffe verhindern.
Minimale Berechtigungen anfordern
Der Chrome-Browser beschränkt den Zugriff einer Erweiterung auf Berechtigungen, die im Manifest explizit angefordert wurden. Erweiterungen sollten ihre Berechtigungen minimieren, indem sie nur APIs und Websites registrieren, von denen sie abhängig sind.
Wenn Sie die Berechtigungen einer Erweiterung einschränken, begrenzen Sie auch, was ein potenzieller Angreifer ausnutzen kann.
ursprungsübergreifende fetch()-Aufrufe
Eine Erweiterung kann nur fetch() und XMLHttpRequest() verwenden, um Ressourcen aus der Erweiterung und aus Domains abzurufen, die in den Berechtigungen angegeben sind. Beachten Sie, dass Aufrufe an beide vom fetch-Handler im Service Worker abgefangen werden.
{
"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
}
Für diese Erweiterung im Beispiel oben wird Zugriff auf alle Inhalte auf developer.chrome.com und Subdomains von Google angefordert, indem "https://developer.chrome.com/*" und "https://*.google.com/*" in den Berechtigungen aufgeführt werden. Wenn die Erweiterung manipuliert würde, hätte sie weiterhin nur die Berechtigung, mit Websites zu interagieren, die dem Muster entsprechen. Der Angreifer hätte nur eingeschränkten Zugriff auf "https://user_bank_info.com" oder könnte nur eingeschränkt mit "https://malicious_website.com" interagieren.
Manifestfelder einschränken
Wenn Sie unnötige Schlüssel und Berechtigungen in das Manifest aufnehmen, entstehen Sicherheitslücken und die Erweiterung wird sichtbarer. Beschränken Sie die Manifestfelder auf die Felder, auf die sich die Erweiterung stützt.
Extern verbindbar
Verwenden Sie das Feld "externally_connectable", um anzugeben, mit welchen externen Erweiterungen und Webseiten die Erweiterung Informationen austauschen wird. Einschränken, 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
},
...
}
Webressourcen
Wenn Ressourcen über das Web unter "web_accessible_resources" zugänglich gemacht werden, können Websites und Angreifer die Erweiterung erkennen.
{
...
"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, diese auszunutzen. Halten Sie die Anzahl dieser Dateien so gering wie möglich.
Explizite Content Security Policy einfügen
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 aus 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 WebAssembly verwenden oder die Einschränkungen für Sandbox-Seiten erhöhen muss, können sie hinzugefügt werden:
{
"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()“ und „innerHTML“ vermeiden
Es kann einfacher sein, HTML-Elemente dynamisch mit document.write() und innerHTML zu erstellen. Dadurch sind die Erweiterung und die Webseiten, von denen die Erweiterung abhängt, jedoch anfällig für Angreifer, die schädliche Skripts einfügen. Erstellen Sie stattdessen DOM-Knoten manuell und verwenden Sie innerText, um dynamische Inhalte einzufügen.
function constructDOM() {
let newTitle = document.createElement('h1');
newTitle.innerText = host;
document.appendChild(newTitle);
}
Inhaltskripte mit Bedacht verwenden
Content-Scripts werden zwar in einer isolierten Welt ausgeführt, sind aber nicht vor Angriffen geschützt:
- Inhaltsskripte sind der einzige Teil einer Erweiterung, der direkt mit der Webseite interagiert. Aus diesem Grund können schädliche Webseiten Teile des DOM manipulieren, von denen das Inhaltsscript abhängt, oder überraschendes Verhalten von Webstandards wie benannte Elemente ausnutzen.
- Damit Content-Scripts mit dem DOM von Webseiten interagieren können, müssen sie im selben Renderer-Prozess wie die Webseite ausgeführt werden. Dadurch sind Content-Scripts anfällig für Datenlecks über Seitenkanalangriffe (z.B. Spectre) und für die Übernahme durch einen Angreifer, wenn eine schädliche Webseite den Renderer-Prozess kompromittiert.
Vorgänge mit vertraulichen Daten (z. B. private Informationen eines Nutzers) oder Chrome-APIs mit Zugriff auf die Funktionen des Browsers sollten im Service Worker der Erweiterung ausgeführt werden. So vermeiden Sie, dass Erweiterungsberechtigungen versehentlich für Inhaltskripte freigegeben werden:
- Gehen Sie davon aus, dass Nachrichten von einem Content-Script von einem Angreifer stammen könnten. Validieren und bereinigen Sie beispielsweise alle Eingaben und schützen Sie Ihre Skripts vor Cross-Site-Scripting.
- Gehen Sie davon aus, dass alle Daten, die an das Inhaltsscript gesendet werden, an die Webseite weitergegeben werden könnten. Senden Sie keine sensiblen Daten (z.B. Secrets aus der Erweiterung, Daten aus anderen Webursprüngen, Browserverlauf) an Content-Scripts.
- Beschränken Sie den Umfang privilegierter Aktionen, die durch Inhaltsskripts ausgelöst werden können. Content-Scripts dürfen keine Anfragen an beliebige URLs auslösen oder beliebige Argumente an Erweiterungs-APIs übergeben (z.B. dürfen keine beliebigen URLs an die Methoden
fetch()oderchrome.tabs.create()übergeben werden).
Eingaben registrieren und bereinigen
Schützen Sie eine Erweiterung vor schädlichen Skripts, indem Sie Listener auf das beschränken, was die Erweiterung erwartet, die Absender eingehender Daten validieren und alle Eingaben bereinigen.
Eine Erweiterung sollte sich nur für runtime.onMessageExternal registrieren, wenn sie eine Kommunikation von einer externen Website oder Erweiterung erwartet. Prüfen Sie immer, ob der Absender mit einer vertrauenswürdigen Quelle übereinstimmt.
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id === kFriendlyExtensionId)
doSomething();
});
Sogar Nachrichten über das runtime.onMessage-Ereignis von der Erweiterung selbst sollten genau geprüft werden, um sicherzustellen, dass der MessageSender nicht von einem manipulierten Inhaltsscript stammt.
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.allowedAction)
console.log("This is an allowed action.");
});