Browser Extension Pentesting Methodology
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Browsererweiterungen sind in JavaScript geschrieben und werden vom Browser im Hintergrund geladen. Sie haben ihr eigenes DOM, können jedoch mit den DOMs anderer Seiten interagieren. Das bedeutet, dass sie die Vertraulichkeit, Integrität und Verfügbarkeit (CIA) anderer Seiten gefährden können.
Die Layouts von Erweiterungen sehen am besten aus, wenn sie visualisiert werden, und bestehen aus drei Komponenten. Lassen Sie uns jede Komponente im Detail betrachten.
Jedes Inhalts-Skript hat direkten Zugriff auf das DOM einer einzelnen Webseite und ist damit potenziell schädlichem Input ausgesetzt. Das Inhalts-Skript enthält jedoch keine Berechtigungen, außer der Fähigkeit, Nachrichten an den Erweiterungskern zu senden.
Der Erweiterungskern enthält die meisten Berechtigungen/Zugriffe der Erweiterung, kann jedoch nur über XMLHttpRequest und Inhalts-Skripte mit Webinhalten interagieren. Außerdem hat der Erweiterungskern keinen direkten Zugriff auf die Hostmaschine.
Die Erweiterung erlaubt eine native Binärdatei, die auf die Hostmaschine mit den vollständigen Berechtigungen des Benutzers zugreifen kann. Die native Binärdatei interagiert über die standardmäßige Netscape Plugin Application Programming Interface (NPAPI), die von Flash und anderen Browser-Plug-ins verwendet wird, mit dem Erweiterungskern.
Um die vollständigen Berechtigungen des Benutzers zu erhalten, muss ein Angreifer die Erweiterung überzeugen, schädlichen Input vom Inhalts-Skript an den Kern der Erweiterung und vom Kern der Erweiterung an die native Binärdatei weiterzugeben.
Jede Komponente der Erweiterung ist durch starke Schutzgrenzen voneinander getrennt. Jede Komponente läuft in einem separaten Betriebssystemprozess. Inhalts-Skripte und Erweiterungskerne laufen in Sandbox-Prozessen, die für die meisten Betriebssystemdienste nicht verfügbar sind.
Darüber hinaus sind Inhalts-Skripte von ihren zugehörigen Webseiten getrennt, indem sie in einem separaten JavaScript-Heap ausgeführt werden. Das Inhalts-Skript und die Webseite haben Zugriff auf dasselbe zugrunde liegende DOM, aber die beiden tauschen niemals JavaScript-Zeiger aus, was das Leaken von JavaScript-Funktionalität verhindert.
manifest.json
Eine Chrome-Erweiterung ist einfach ein ZIP-Ordner mit einer .crx-Dateiendung. Der Kern der Erweiterung ist die manifest.json
-Datei im Stammordner, die Layout, Berechtigungen und andere Konfigurationsoptionen angibt.
Beispiel:
content_scripts
Inhalts-Skripte werden geladen, wann immer der Benutzer zu einer übereinstimmenden Seite navigiert, in unserem Fall zu jeder Seite, die dem https://example.com/*
Ausdruck entspricht und nicht dem *://*/*/business*
Regex entspricht. Sie werden wie die eigenen Skripte der Seite ausgeführt und haben beliebigen Zugriff auf das Document Object Model (DOM) der Seite.
Um weitere URLs einzuschließen oder auszuschließen, ist es auch möglich, include_globs
und exclude_globs
zu verwenden.
Dies ist ein Beispielinhaltsskript, das einen Erklärungsbutton zur Seite hinzufügt, wenn die Storage-API verwendet wird, um den message
-Wert aus dem Speicher der Erweiterung abzurufen.
Eine Nachricht wird an die Erweiterungsseiten vom Inhalts-Skript gesendet, wenn dieser Button geklickt wird, durch die Nutzung der runtime.sendMessage() API. Dies liegt an der Einschränkung des Inhalts-Skripts im direkten Zugriff auf APIs, wobei storage
zu den wenigen Ausnahmen gehört. Für Funktionalitäten über diese Ausnahmen hinaus werden Nachrichten an Erweiterungsseiten gesendet, mit denen Inhalts-Skripte kommunizieren können.
Je nach Browser können die Fähigkeiten des Inhalts-Skripts leicht variieren. Für Chromium-basierte Browser ist die Liste der Fähigkeiten in der Chrome Developers-Dokumentation verfügbar, und für Firefox dient das MDN als primäre Quelle. Es ist auch bemerkenswert, dass Inhalts-Skripte die Fähigkeit haben, mit Hintergrund-Skripten zu kommunizieren, was es ihnen ermöglicht, Aktionen auszuführen und Antworten zurückzugeben.
Um Inhalts-Skripte in Chrome anzuzeigen und zu debuggen, kann das Menü der Chrome-Entwicklertools über Optionen > Weitere Tools > Entwicklertools oder durch Drücken von Ctrl + Shift + I aufgerufen werden.
Sobald die Entwicklertools angezeigt werden, ist der Quell-Tab anzuklicken, gefolgt vom Inhalts-Skripte-Tab. Dies ermöglicht die Beobachtung von laufenden Inhalts-Skripten aus verschiedenen Erweiterungen und das Setzen von Haltepunkten, um den Ausführungsfluss zu verfolgen.
Beachten Sie, dass Inhalts-Skripte nicht zwingend erforderlich sind, da es auch möglich ist, Skripte dynamisch zu injizieren und sie programmatisch in Webseiten über tabs.executeScript
zu injizieren. Dies bietet tatsächlich mehr granulare Kontrollen.
Für die programmatische Injektion eines Inhalts-Skripts muss die Erweiterung Host-Berechtigungen für die Seite haben, in die die Skripte injiziert werden sollen. Diese Berechtigungen können entweder durch Anforderung innerhalb des Manifests der Erweiterung oder vorübergehend über activeTab gesichert werden.
Injiziere eine JS-Datei beim Klicken:
Funktion beim Klicken injizieren:
Um weitere URLs einzuschließen oder auszuschließen, ist es auch möglich, include_globs
und exclude_globs
zu verwenden.
run_at
Das Feld run_at
steuert wann JavaScript-Dateien in die Webseite injiziert werden. Der bevorzugte und Standardwert ist "document_idle"
.
Die möglichen Werte sind:
document_idle
: Wann immer möglich
document_start
: Nach allen Dateien von css
, aber bevor andere DOM-Elemente erstellt oder andere Skripte ausgeführt werden.
document_end
: Unmittelbar nachdem das DOM vollständig ist, aber bevor Unterressourcen wie Bilder und Frames geladen wurden.
manifest.json
Über service-worker.js
background
Nachrichten, die von Inhalts-Skripten gesendet werden, werden von der Hintergrundseite empfangen, die eine zentrale Rolle bei der Koordination der Komponenten der Erweiterung spielt. Bemerkenswerterweise bleibt die Hintergrundseite während der gesamten Lebensdauer der Erweiterung bestehen und arbeitet diskret ohne direkte Benutzerinteraktion. Sie verfügt über ihr eigenes Document Object Model (DOM), das komplexe Interaktionen und Zustandsverwaltung ermöglicht.
Wichtige Punkte:
Rolle der Hintergrundseite: Dient als Nervenzentrum für die Erweiterung und sorgt für Kommunikation und Koordination zwischen den verschiedenen Teilen der Erweiterung.
Persistenz: Es ist eine stets präsente Entität, die für den Benutzer unsichtbar, aber für die Funktionalität der Erweiterung unerlässlich ist.
Automatische Generierung: Wenn nicht ausdrücklich definiert, wird der Browser automatisch eine Hintergrundseite erstellen. Diese automatisch generierte Seite enthält alle Hintergrundskripte, die im Manifest der Erweiterung angegeben sind, und gewährleistet den nahtlosen Betrieb der Hintergrundaufgaben der Erweiterung.
Der Komfort, den der Browser bei der automatischen Generierung einer Hintergrundseite (wenn nicht ausdrücklich deklariert) bietet, stellt sicher, dass alle notwendigen Hintergrundskripte integriert und betriebsbereit sind, was den Einrichtungsprozess der Erweiterung vereinfacht.
Beispiel für ein Hintergrundskript:
Es verwendet die runtime.onMessage API, um Nachrichten zu empfangen. Wenn eine "explain"
-Nachricht empfangen wird, verwendet es die tabs API, um eine Seite in einem neuen Tab zu öffnen.
Um das Hintergrundskript zu debuggen, können Sie zu den Erweiterungsdetails gehen und den Dienstarbeiter inspizieren. Dies öffnet die Entwicklertools mit dem Hintergrundskript:
Browsererweiterungen können verschiedene Arten von Seiten enthalten:
Aktionsseiten werden in einem Dropdown angezeigt, wenn das Erweiterungssymbol angeklickt wird.
Seiten, die die Erweiterung in einem neuen Tab lädt.
Optionsseiten: Diese Seite wird oben auf der Erweiterung angezeigt, wenn sie angeklickt wird. Im vorherigen Manifest konnte ich auf diese Seite zugreifen unter chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
oder durch Klicken:
Beachten Sie, dass diese Seiten nicht persistent sind wie Hintergrundseiten, da sie dynamisch Inhalte nach Bedarf laden. Trotz dessen teilen sie bestimmte Fähigkeiten mit der Hintergrundseite:
Kommunikation mit Inhalts-Skripten: Ähnlich wie die Hintergrundseite können diese Seiten Nachrichten von Inhalts-Skripten empfangen, was die Interaktion innerhalb der Erweiterung erleichtert.
Zugriff auf erweiterungsspezifische APIs: Diese Seiten haben umfassenden Zugriff auf erweiterungsspezifische APIs, vorbehaltlich der für die Erweiterung definierten Berechtigungen.
permissions
& host_permissions
permissions
und host_permissions
sind Einträge aus der manifest.json
, die anzeigen, welche Berechtigungen die Browsererweiterung hat (Speicher, Standort...) und in welchen Webseiten.
Da Browsererweiterungen so privilegiert sein können, könnte eine bösartige oder kompromittierte Erweiterung dem Angreifer verschiedene Mittel ermöglichen, um sensible Informationen zu stehlen und den Benutzer auszuspionieren.
Überprüfen Sie, wie diese Einstellungen funktionieren und wie sie missbraucht werden könnten in:
BrowExt - permissions & host_permissionscontent_security_policy
Eine Content-Sicherheitsrichtlinie kann auch innerhalb der manifest.json
deklariert werden. Wenn eine definiert ist, könnte sie anfällig sein.
Die Standardeinstellung für Seiten von Browsererweiterungen ist eher restriktiv:
Für weitere Informationen zu CSP und potenziellen Umgehungen siehe:
Content Security Policy (CSP) Bypassweb_accessible_resources
Damit eine Webseite auf eine Seite einer Browsererweiterung zugreifen kann, beispielsweise eine .html
-Seite, muss diese Seite im web_accessible_resources
-Feld der manifest.json
erwähnt werden.
Zum Beispiel:
Diese Seiten sind über URLs wie zugänglich:
In öffentlichen Erweiterungen ist die extension-id zugänglich:
Wenn jedoch der manifest.json
Parameter use_dynamic_url
verwendet wird, kann diese id dynamisch sein.
Beachten Sie, dass selbst wenn eine Seite hier erwähnt wird, sie möglicherweise gegen ClickJacking geschützt ist, dank der Content Security Policy. Daher müssen Sie dies auch überprüfen (frame-ancestors Abschnitt), bevor Sie bestätigen, dass ein ClickJacking-Angriff möglich ist.
Der Zugriff auf diese Seiten macht diese Seiten potenziell anfällig für ClickJacking:
BrowExt - ClickJackingWenn diese Seiten nur von der Erweiterung und nicht von zufälligen URLs geladen werden dürfen, könnte dies ClickJacking-Angriffe verhindern.
Beachten Sie, dass die Seiten aus web_accessible_resources
und andere Seiten der Erweiterung ebenfalls in der Lage sind, Hintergrundskripte zu kontaktieren. Wenn eine dieser Seiten anfällig für XSS ist, könnte dies eine größere Verwundbarkeit eröffnen.
Darüber hinaus beachten Sie, dass Sie nur Seiten, die in web_accessible_resources
angegeben sind, innerhalb von iframes öffnen können, aber von einem neuen Tab aus ist es möglich, auf jede Seite in der Erweiterung zuzugreifen, wenn Sie die Erweiterungs-ID kennen. Daher könnte, wenn ein XSS gefunden wird, das dieselben Parameter missbraucht, dies auch ausgenutzt werden, selbst wenn die Seite nicht in web_accessible_resources
konfiguriert ist.
externally_connectable
Laut den Docs erklärt die "externally_connectable"
Manifest-Eigenschaft, welche Erweiterungen und Webseiten sich über runtime.connect und runtime.sendMessage mit Ihrer Erweiterung verbinden können.
Wenn der externally_connectable
Schlüssel nicht im Manifest Ihrer Erweiterung deklariert ist oder als "ids": ["*"]
deklariert ist, können alle Erweiterungen verbinden, aber keine Webseiten können verbinden.
Wenn spezifische IDs angegeben sind, wie in "ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, können nur diese Anwendungen verbinden.
Wenn Übereinstimmungen angegeben sind, können diese Webanwendungen sich verbinden:
Wenn es als leer angegeben ist: "externally_connectable": {}
, kann keine App oder Webseite eine Verbindung herstellen.
Je weniger Erweiterungen und URLs hier angegeben sind, desto kleiner wird die Angriffsfläche sein.
Wenn eine Webseite, die anfällig für XSS oder Übernahme ist, in externally_connectable
angegeben ist, kann ein Angreifer Nachrichten direkt an das Hintergrundskript senden, wodurch das Content-Skript und dessen CSP vollständig umgangen werden.
Daher ist dies ein sehr mächtiger Bypass.
Darüber hinaus, wenn der Client eine bösartige Erweiterung installiert, könnte diese, selbst wenn sie nicht mit der anfälligen Erweiterung kommunizieren darf, XSS-Daten in eine erlaubte Webseite injizieren oder die WebRequest
oder DeclarativeNetRequest
APIs missbrauchen, um Anfragen auf einer gezielten Domain zu manipulieren und eine Anfrage für eine JavaScript-Datei zu ändern. (Beachten Sie, dass CSP auf der gezielten Seite diese Angriffe verhindern könnte). Diese Idee stammt aus diesem Bericht.
Um zwischen dem Content-Skript und der Webseite zu kommunizieren, werden normalerweise Post-Nachrichten verwendet. Daher finden Sie in der Webanwendung normalerweise Aufrufe der Funktion window.postMessage
und im Content-Skript Listener wie window.addEventListener
. Beachten Sie jedoch, dass die Erweiterung auch mit der Webanwendung kommunizieren könnte, indem sie eine Post-Nachricht sendet (und daher die Webseite dies erwarten sollte) oder einfach die Webseite dazu bringt, ein neues Skript zu laden.
Normalerweise wird die Funktion chrome.runtime.sendMessage
verwendet, um eine Nachricht innerhalb der Erweiterung zu senden (normalerweise vom background
-Skript verarbeitet), und um sie zu empfangen und zu verarbeiten, wird ein Listener deklariert, der chrome.runtime.onMessage.addListener
aufruft.
Es ist auch möglich, chrome.runtime.connect()
zu verwenden, um eine persistente Verbindung anstelle von einzelnen Nachrichten zu haben. Es ist möglich, es zu verwenden, um Nachrichten zu senden und zu empfangen, wie im folgenden Beispiel:
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)