Pentesting-Methodologie für Browser-Extensions
Reading time: 28 minutes
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: 
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking: 
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
 - Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
 - Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
 
Grundlegende Informationen
Browser-Extensions werden in JavaScript geschrieben und vom Browser im Hintergrund geladen. Sie haben ihr DOM, können aber mit den DOMs anderer Sites interagieren. Das bedeutet, dass sie die Vertraulichkeit, Integrität und Verfügbarkeit (CIA) anderer Sites beeinträchtigen können.
Hauptkomponenten
Die Architektur einer Extension lässt sich am besten visualisieren und besteht aus drei Komponenten. Schauen wir uns jede Komponente genauer an.
 (1) (1).png)
Content Scripts
Jedes Content Script hat direkten Zugriff auf das DOM einer einzelnen Webseite und ist damit potenziell bösartigen Eingaben ausgesetzt. Das Content Script besitzt jedoch keine Berechtigungen außer der Möglichkeit, Nachrichten an den extension core zu senden.
Extension Core
Der extension core enthält die meisten Privilegien/Zugriffsrechte der Extension, kann jedoch nur über XMLHttpRequest und Content Scripts mit Web-Content interagieren. Außerdem hat der extension core keinen direkten Zugriff auf das Host-System.
Native Binary
Die Extension erlaubt ein natives Binary, das mit den vollen Benutzerprivilegien auf das Host-System zugreifen kann. Das native Binary interagiert mit dem extension core durch die standardmäßige Netscape Plugin Application Programming Interface (NPAPI), die von Flash und anderen Browser-Plug-ins verwendet wird.
Boundaries
caution
Um die vollen Benutzerprivilegien zu erlangen, muss ein Angreifer die Extension dazu bringen, bösartige Eingaben vom Content Script an den extension core und vom extension core an das native Binary weiterzuleiten.
Jede Komponente der Extension ist durch starke Schutzgrenzen voneinander getrennt. Jede Komponente läuft in einem separaten Betriebssystemprozess. Content Scripts und extension cores laufen in Sandbox-Prozessen, die den meisten Betriebssystemdiensten nicht zur Verfügung stehen.
Außerdem sind Content Scripts von ihren zugehörigen Webseiten getrennt, indem sie in einem separaten JavaScript-Heap laufen. Das Content Script und die Webseite haben Zugriff auf dasselbe zugrundeliegende DOM, tauschen jedoch niemals JavaScript-Pointer aus, wodurch das leaking von JavaScript-Funktionalität verhindert wird.
manifest.json
Eine Chrome-Extension ist im Grunde ein ZIP-Ordner mit einer .crx file extension. Der Kern der Extension ist die Datei manifest.json im Root des Ordners, die Layout, Berechtigungen und andere Konfigurationsoptionen festlegt.
Beispiel:
{
"manifest_version": 2,
"name": "My extension",
"version": "1.0",
"permissions": ["storage"],
"content_scripts": [
{
"js": ["script.js"],
"matches": ["https://example.com/*", "https://www.example.com/*"],
"exclude_matches": ["*://*/*business*"]
}
],
"background": {
"scripts": ["background.js"]
},
"options_ui": {
"page": "options.html"
}
}
content_scripts
Content scripts werden geladen, wann immer der Benutzer zu einer passenden Seite navigiert, in unserem Fall jede Seite, die dem https://example.com/* Ausdruck entspricht und nicht dem *://*/*/business* regex. Sie werden wie die eigenen Skripte der Seite ausgeführt und haben uneingeschränkten Zugriff auf das Seiten-Document Object Model (DOM).
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
Um weitere URLs einzuschließen oder auszuschließen, ist es außerdem möglich, include_globs und exclude_globs zu verwenden.
Dies ist ein Beispiel-Content-Script, das der Seite einen Explain-Button hinzufügt, wenn the storage API verwendet wird, um den message-Wert aus dem Speicher der Extension abzurufen.
chrome.storage.local.get("message", (result) => {
let div = document.createElement("div")
div.innerHTML = result.message + " <button>Explain</button>"
div.querySelector("button").addEventListener("click", () => {
chrome.runtime.sendMessage("explain")
})
document.body.appendChild(div)
})
.png)
Eine Nachricht wird vom content script an die extension pages gesendet, wenn dieser Button angeklickt wird — und zwar über die Verwendung der runtime.sendMessage() API. Dies liegt an der Einschränkung, dass content scripts nicht direkt auf alle APIs zugreifen können; storage gehört zu den wenigen Ausnahmen. Für Funktionalitäten, die über diese Ausnahmen hinausgehen, werden Nachrichten an extension pages geschickt, mit denen content scripts kommunizieren können.
warning
Je nach Browser können die Fähigkeiten des content scripts leicht variieren. Für Chromium-basierte Browser ist die Auflistung der Fähigkeiten in der Chrome Developers documentation verfügbar, und für Firefox dient die MDN als Hauptquelle.
Es ist außerdem erwähnenswert, dass content scripts mit background scripts kommunizieren können, wodurch sie Aktionen ausführen und Antworten zurückmelden können.
Zum Anzeigen und Debuggen von content scripts in Chrome kann das Chrome developer tools-Menü über Options > More tools > Developer tools aufgerufen werden ODER durch Drücken von Ctrl + Shift + I.
Wenn die Developer Tools angezeigt werden, klickt man auf den Source-Tab, gefolgt vom Content Scripts-Tab. So können laufende content scripts verschiedener Extensions beobachtet und Breakpoints gesetzt werden, um den Ausführungsfluss nachzuverfolgen.
Injizierte Content Scripts
tip
Beachte, dass Content Scripts nicht zwingend erforderlich sind, da Skripte auch dynamisch bzw. programmgesteuert per tabs.executeScript in Webseiten injiziert werden können. Das bietet tatsächlich feinere Kontrollen.
Für die programmgesteuerte Injektion eines content scripts muss die Extension host permissions für die Seite besitzen, in die die Skripte injiziert werden sollen. Diese Berechtigungen können entweder durch Anforderung im Manifest der Extension gesichert werden oder vorübergehend über activeTab.
Beispiel: activeTab-basierte Extension
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
- JS-Datei bei Klick injizieren:
 
// content-script.js
document.body.style.backgroundColor = "orange"
//service-worker.js - Inject the JS file
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"],
})
})
- Funktion injizieren bei Klick:
 
//service-worker.js - Inject a function
function injectedFunction() {
document.body.style.backgroundColor = "orange"
}
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: injectedFunction,
})
})
Beispiel mit scripting permissions
// service-workser.js
chrome.scripting.registerContentScripts([
{
id: "test",
matches: ["https://*.example.com/*"],
excludeMatches: ["*://*/*business*"],
js: ["contentScript.js"],
},
])
// Another example
chrome.tabs.executeScript(tabId, { file: "content_script.js" })
Um mehr URLs einzuschließen oder auszuschließen, ist es außerdem möglich, include_globs und exclude_globs zu verwenden.
Content Scripts run_at
Das Feld run_at steuert wann JavaScript-Dateien in die Webseite injiziert werden. Der bevorzugte und standardmäßige Wert ist "document_idle".
Die möglichen Werte sind:
document_idle: Wann immer möglichdocument_start: Nach allen Dateien auscss, aber bevor das DOM aufgebaut wird oder andere Skripte ausgeführt werden.document_end: Unmittelbar nachdem das DOM vollständig ist, jedoch bevor Subressourcen wie Bilder und Frames geladen sind.
Via manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
Über service-worker.js
chrome.scripting.registerContentScripts([
{
id: "test",
matches: ["https://*.example.com/*"],
runAt: "document_idle",
js: ["contentScript.js"],
},
])
background
Nachrichten, die von Content-Skripten gesendet werden, werden von der Hintergrundseite empfangen, die eine zentrale Rolle bei der Koordination der Komponenten der Erweiterung spielt. Bemerkenswert ist, dass die Hintergrundseite über die gesamte Lebensdauer der Erweiterung hinweg bestehen bleibt und unauffällig ohne direkte Benutzerinteraktion arbeitet. Sie verfügt über ihr eigenes Document Object Model (DOM), was komplexe Interaktionen und Zustandsverwaltung ermöglicht.
Wichtige Punkte:
- Rolle der Hintergrundseite: Fungiert als Schaltzentrale für die Erweiterung und stellt die Kommunikation und Koordination zwischen den verschiedenen Teilen der Erweiterung sicher.
 - Persistenz: Sie ist eine stets vorhandene Entität, für den Benutzer unsichtbar, aber integraler Bestandteil der Funktionalität der Erweiterung.
 - Automatische Erstellung: Falls nicht explizit definiert, erstellt der Browser automatisch eine Hintergrundseite. Diese automatisch erzeugte Seite wird alle im Manifest der Erweiterung angegebenen Hintergrundskripte enthalten und so den nahtlosen Betrieb der Hintergrundaufgaben der Erweiterung sicherstellen.
 
tip
Die Bequemlichkeit, die der Browser durch die automatische Erstellung einer Hintergrundseite (wenn diese nicht explizit deklariert ist) bietet, stellt sicher, dass alle notwendigen Hintergrundskripte integriert und einsatzbereit sind und vereinfacht so den Einrichtungsprozess der Erweiterung.
Beispiel für ein Hintergrundskript:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request == "explain") {
chrome.tabs.create({ url: "https://example.net/explanation" })
}
})
Es verwendet die runtime.onMessage API, um Nachrichten zu lauschen. Wenn eine "explain"-Nachricht empfangen wird, nutzt es die tabs API, um eine Seite in einem neuen Tab zu öffnen.
Um das background script zu debuggen, kannst du zu den extension details and inspect the service worker, gehen; das öffnet die developer tools mit dem background script:
Options pages and other
Browser extensions können verschiedene Arten von Seiten enthalten:
- Action pages are displayed in a drop-down when the extension icon is clicked.
 - Seiten, die die Extension load in a new tab.
 - Option Pages: Diese Seite wird oben auf der Extension angezeigt, wenn sie angeklickt wird. In meinem vorherigen manifest konnte ich diese Seite unter 
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjcaerreichen oder durch Klicken: 
.png)
Beachte, dass diese Seiten nicht persistent wie background pages sind, da sie Inhalte dynamisch nach Bedarf laden. Trotz dessen teilen sie bestimmte Fähigkeiten mit der background page:
- Communication with Content Scripts: Ähnlich zur background page können diese Seiten Nachrichten von content scripts empfangen und so die Interaktion innerhalb der Extension ermöglichen.
 - Access to Extension-Specific APIs: Diese Seiten haben umfassenden Zugriff auf extension-specific APIs, vorbehaltlich der für die Extension definierten Berechtigungen.
 
permissions & host_permissions
permissions und host_permissions sind Einträge in der manifest.json, die angeben, welche permissions die browser extensions hat (storage, location...) und in welchen web pages.
Da browser extensions so privileged sein können, könnte eine bösartige oder kompromittierte Extension einem Angreifer different means to steal sensitive information and spy on the user ermöglichen.
Prüfe, wie diese Einstellungen funktionieren und wie sie missbraucht werden könnten in:
BrowExt - permissions & host_permissions
content_security_policy
Eine content security policy kann ebenfalls in der manifest.json deklariert werden. Wenn eine definiert ist, könnte sie vulnerable sein.
Die Standardkonfiguration für browser extension pages ist relativ restriktiv:
script-src 'self'; object-src 'self';
Für weitere Informationen zu CSP und möglichen Bypässen siehe:
Content Security Policy (CSP) Bypass
web_accessible_resources
Damit eine Webseite auf eine Seite einer Browser-Erweiterung zugreifen kann, z. B. eine .html-Seite, muss diese Seite im Feld web_accessible_resources der manifest.json aufgeführt sein.
Zum Beispiel:
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
Diese Seiten sind unter URLs wie folgt erreichbar:
chrome-extension://<extension-id>/message.html
In öffentlichen Extensions ist die extension-id zugänglich:
.png)
Wenn jedoch der manifest.json-Parameter use_dynamic_url verwendet wird, kann diese ID dynamisch sein.
tip
Beachte, dass selbst wenn hier eine Seite erwähnt wird, sie dank der Content Security Policy gegen ClickJacking geschützt sein kann. Du musst also auch diese (frame-ancestors Abschnitt) prüfen, bevor du bestätigst, dass ein ClickJacking-Angriff möglich ist.
Der erlaubte Zugriff auf diese Seiten macht sie potenziell für ClickJacking anfällig:
tip
Das Zulassen, dass diese Seiten nur von der Extension und nicht von beliebigen URLs geladen werden, kann ClickJacking-Angriffe verhindern.
caution
Beachte, dass die Seiten aus web_accessible_resources und andere Seiten der Extension ebenfalls in der Lage sind, contacting background scripts. Wenn also eine dieser Seiten für XSS verwundbar ist, kann dies eine größere Schwachstelle eröffnen.
Außerdem kannst du nur Seiten, die in web_accessible_resources angegeben sind, innerhalb von iframes öffnen; in einem neuen Tab ist es jedoch möglich, jede Seite der Extension aufzurufen, wenn man die Extension-ID kennt. Daher könnte ein XSS, das dieselben Parameter ausnutzt, missbraucht werden, selbst wenn die Seite nicht in web_accessible_resources konfiguriert ist.
externally_connectable
Laut den docs deklariert die Manifest-Eigenschaft "externally_connectable", welche Extensions und Webseiten sich mit deiner Extension via runtime.connect und runtime.sendMessage verbinden können.
- Wenn der 
externally_connectable-Schlüssel nicht im Manifest deiner Extension deklariert ist oder er als"ids": ["*"]angegeben ist, können alle Extensions eine Verbindung herstellen, aber keine Webseiten. - Wenn konkrete IDs angegeben sind, wie in 
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], können nur diese Anwendungen eine Verbindung herstellen. - Wenn matches angegeben sind, können diese Web-Apps eine Verbindung herstellen:
 
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
- Wenn es als leer angegeben ist: 
"externally_connectable": {}, wird keine App oder Website eine Verbindung herstellen können. 
Je weniger extensions und URLs hier angegeben sind, desto kleiner die Angriffsfläche.
caution
Wenn eine Webseite vulnerable to XSS or takeover in externally_connectable angegeben ist, kann ein Angreifer Nachrichten direkt an das background script senden, wodurch das Content Script und dessen CSP vollständig umgangen werden.
Daher ist dies ein sehr mächtiger bypass.
Außerdem, wenn der Client eine bösartige Extension installiert, selbst wenn sie nicht erlaubt ist, mit der verwundbaren Extension zu kommunizieren, könnte sie XSS data in an allowed web page injizieren oder die WebRequest- bzw. DeclarativeNetRequest-APIs missbrauchen, um Anfragen für eine zielgerichtete Domain zu manipulieren und so die Anforderung einer Seite für eine JavaScript file zu verändern. (Beachte, dass CSP auf der zielgerichteten Seite diese Angriffe verhindern könnte). Diese Idee stammt from this writeup.
Kommunikationsübersicht
Extension <--> WebApp
Um zwischen dem Content Script und der Webseite zu kommunizieren, werden üblicherweise post messages verwendet. Daher findet man in der Webanwendung normalerweise Aufrufe der Funktion window.postMessage und im Content Script Listener wie window.addEventListener. Beachte jedoch, dass die Extension auch mit der Webanwendung kommunizieren kann, indem sie eine Post Message sendet (und die Webanwendung dies daher erwarten sollte) oder einfach die Seite ein neues Script laden lässt.
Innerhalb der Extension
Normalerweise wird die Funktion chrome.runtime.sendMessage verwendet, um eine Nachricht innerhalb der Extension zu senden (meist vom background script verarbeitet). 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 statt einzelner Nachrichten zu haben; damit kann man send und receive messages wie im folgenden Beispiel verwenden:
chrome.runtime.connect() Beispiel
var port = chrome.runtime.connect()
// Listen for messages from the web page
window.addEventListener(
"message",
(event) => {
// Only accept messages from the same window
if (event.source !== window) {
return
}
// Check if the message type is "FROM_PAGE"
if (event.data.type && event.data.type === "FROM_PAGE") {
console.log("Content script received: " + event.data.text)
// Forward the message to the background script
port.postMessage({ type: "FROM_PAGE", text: event.data.text })
}
},
false
)
// Listen for messages from the background script
port.onMessage.addListener(function (msg) {
console.log("Content script received message from background script:", msg)
// Handle the response message from the background script
})
Es ist auch möglich, Nachrichten von einem Hintergrundskript an ein Content-Skript in einem bestimmten Tab zu senden, indem man chrome.tabs.sendMessage aufruft, wobei Sie die ID des Tabs angeben müssen, an den die Nachricht gesendet werden soll.
Von erlaubten externally_connectable zur Erweiterung
Web-Apps und externe Browser-Erweiterungen, die in der externally_connectable-Konfiguration erlaubt sind, können Anfragen senden using :
chrome.runtime.sendMessage(extensionId, ...
Wo es nötig ist, die extension ID zu erwähnen.
Native Messaging
Es ist möglich, dass background scripts mit binaries im System kommunizieren, die anfällig für kritische Sicherheitslücken wie RCEs sein können, wenn diese Kommunikation nicht richtig abgesichert ist. Mehr dazu später.
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)
Web ↔︎ Content Script Kommunikation
Die Umgebungen, in denen content scripts ausgeführt werden, und die Host-Seiten sind voneinander separiert, wodurch Isolation gewährleistet wird. Trotz dieser Isolation können beide mit dem Document Object Model (DOM) der Seite interagieren, einer gemeinsamen Ressource. Damit die Host-Seite mit dem content script kommunizieren kann oder indirekt mit der extension über das content script, muss sie das für beide zugängliche DOM als Kommunikationskanal verwenden.
Post Messages
// This is like "chrome.runtime.sendMessage" but to maintain the connection
var port = chrome.runtime.connect()
window.addEventListener(
"message",
(event) => {
// We only accept messages from ourselves
if (event.source !== window) {
return
}
if (event.data.type && event.data.type === "FROM_PAGE") {
console.log("Content script received: " + event.data.text)
// Forward the message to the background script
port.postMessage(event.data.text)
}
},
false
)
document.getElementById("theButton").addEventListener(
"click",
() => {
window.postMessage(
{ type: "FROM_PAGE", text: "Hello from the webpage!" },
"*"
)
},
false
)
Eine sichere Post Message-Kommunikation sollte die Authentizität der empfangenen Nachricht prüfen; das kann durch folgende Checks erfolgen:
event.isTrusted: Dies ist True nur, wenn das Event durch eine Benutzeraktion ausgelöst wurde- Das Content Script könnte nur dann Nachrichten erwarten, wenn der Nutzer eine Aktion ausführt
 - origin domain: könnte so konfiguriert sein, dass nur eine Allowlist von Domains Nachrichten akzeptiert
 - Wenn ein Regex verwendet wird, sei sehr vorsichtig
 - Source: 
received_message.source !== windowkann verwendet werden, um zu prüfen, ob die Nachricht from the same window stammt, in dem das Content Script lauscht. 
Die vorherigen Checks können, selbst wenn sie durchgeführt werden, verwundbar sein — siehe auf der folgenden Seite potential Post Message bypasses:
Iframe
Eine weitere mögliche Kommunikationsart kann über Iframe URLs erfolgen; ein Beispiel dazu findest du in:
DOM
Das ist nicht „genau“ eine Kommunikationsart, aber web und das Content Script haben Zugriff auf den web DOM. Wenn das content script also Informationen daraus liest und trusting the web DOM, könnte das web diese modify this data (weil dem web nicht vertraut werden sollte oder weil das web für XSS verwundbar ist) und damit compromise the Content Script.
Ein Beispiel für eine DOM based XSS to compromise a browser extension findest du ebenfalls in:
Content Script ↔︎ Background Script Communication
Ein Content Script kann die Funktionen runtime.sendMessage() oder tabs.sendMessage() verwenden, um eine one-time JSON-serializable Nachricht zu senden.
Um die response zu verarbeiten, nutze das zurückgegebene Promise. Zur Abwärtskompatibilität kannst du jedoch weiterhin einen callback als letztes Argument übergeben.
Das Senden einer Anfrage aus einem content script sieht so aus:
;(async () => {
const response = await chrome.runtime.sendMessage({ greeting: "hello" })
// do something with response here, not outside the function
console.log(response)
})()
Senden einer Anfrage von der extension (in der Regel ein background script). Beispiel, wie man eine Nachricht an das content script im ausgewählten tab sendet:
// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
;(async () => {
const [tab] = await chrome.tabs.query({
active: true,
lastFocusedWindow: true,
})
const response = await chrome.tabs.sendMessage(tab.id, { greeting: "hello" })
// do something with response here, not outside the function
console.log(response)
})()
Auf der Empfängerseite müssen Sie einen runtime.onMessage event listener einrichten, um die Nachricht zu verarbeiten. Das sieht sowohl im content script als auch in einer extension page gleich aus.
// From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
console.log(
sender.tab
? "from a content script:" + sender.tab.url
: "from the extension"
)
if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
})
Im hervorgehobenen Beispiel wurde sendResponse() synchron ausgeführt. Um den onMessage-Event-Handler für eine asynchrone Ausführung von sendResponse() anzupassen, ist es zwingend erforderlich, return true; einzufügen.
Eine wichtige Überlegung ist, dass in Szenarien, in denen mehrere Seiten onMessage-Events empfangen sollen, die erste Seite, die sendResponse() für ein bestimmtes Event ausführt, die einzige ist, die die Antwort effektiv liefern kann. Alle nachfolgenden Antworten auf dasselbe Event werden nicht berücksichtigt.
Beim Erstellen neuer Extensions sollte Promises gegenüber callbacks bevorzugt werden. Bei Verwendung von callbacks ist die Funktion sendResponse() nur dann gültig, wenn sie direkt im synchronen Kontext ausgeführt wird oder wenn der Event-Handler durch Rückgabe von true eine asynchrone Operation signalisiert. Wenn keiner der Handler true zurückgibt oder wenn die sendResponse()-Funktion aus dem Speicher entfernt (garbage-collected) wird, wird standardmäßig der Callback von sendMessage() ausgelöst.
Native Messaging
Browser extensions ermöglichen außerdem die Kommunikation mit binaries im System über stdin. Die Anwendung muss eine json installieren, die dies angibt — beispielsweise eine json wie:
{
"name": "com.my_company.my_application",
"description": "My Application",
"path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
"type": "stdio",
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
}
Dabei ist name der String, der an runtime.connectNative() oder runtime.sendNativeMessage() übergeben wird, um von den Hintergrundskripten der Browser-Erweiterung mit der Anwendung zu kommunizieren. Der path ist der Pfad zur Binary, es gibt nur einen gültigen type, nämlich stdio (Verwendung von stdin und stdout), und die allowed_origins geben die Erweiterungen an, die darauf zugreifen können (Wildcard ist nicht erlaubt).
Chrome/Chromium sucht dieses json in bestimmten Windows-Registry-Einträgen und in einigen Pfaden unter macOS und Linux (mehr Infos in den docs).
tip
Die Browser-Erweiterung benötigt außerdem die deklarierte Berechtigung nativeMessaing, um diese Kommunikation nutzen zu können.
So sieht ein Beispiel für Code eines Hintergrundskripts aus, das Nachrichten an eine native Anwendung sendet:
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)
In this blog post, wird ein verwundbares Muster zum Missbrauch von native messages vorgeschlagen:
- Browser extension hat ein Wildcard-Pattern für das content script.
 - Content script leitet 
postMessage-Nachrichten an das background script weiter, indem essendMessageverwendet. - Background script leitet die Nachricht an die native application weiter mittels 
sendNativeMessage. - Native application verarbeitet die Nachricht unsicher, was zu code execution führen kann.
 
Darin wird ein Beispiel erklärt, wie man von jeder Seite zu RCE gelangen kann, indem man eine Browser extension ausnutzt.
Sensitive Information in Memory/Code/Clipboard
Wenn eine Browser Extension sensible Informationen im Arbeitsspeicher speichert, könnten diese (insbesondere auf Windows-Maschinen) gedumpt und nach diesen Informationen durchsucht werden.
Deshalb sollte der Arbeitsspeicher der Browser Extension nicht als sicher angesehen werden und sensible Informationen wie Credentials oder mnemonic phrases sollten nicht gespeichert werden.
Lege natürlich keine sensiblen Informationen in den Code, da dieser öffentlich sein wird.
Um den Speicher des Browsers zu dumpen, kannst du entweder den Prozessspeicher dumpen oder in die Einstellungen der Browser Extension gehen, auf Inspect pop-up klicken -> im Memory Bereich -> Take a snaphost und mit CTRL+F innerhalb des Snapshots nach sensiblen Informationen suchen.
Außerdem sollte es nicht erlaubt sein, hochsensible Informationen wie mnemonic keys oder Passwörter in die clipboard zu kopieren (oder sie zumindest nach ein paar Sekunden wieder daraus zu entfernen), da Prozesse, die die clipboard überwachen, sonst darauf zugreifen können.
Loading an Extension in the Browser
- Herunterladen der Browser Extension & entpacken
 - Gehe zu 
chrome://extensions/und aktiviere denDeveloper Mode - Klicke auf den Button 
Load unpacked 
In Firefox gehst du zu about:debugging#/runtime/this-firefox und klickst auf den Button Load Temporary Add-on.
Getting the source code from the store
Der Quellcode einer Chrome-Erweiterung kann auf verschiedene Weisen beschafft werden. Im Folgenden findest du detaillierte Erklärungen und Anleitungen für jede Option.
Download Extension as ZIP via Command Line
Der Quellcode einer Chrome-Erweiterung kann per Kommandozeile als ZIP-Datei heruntergeladen werden. Dazu wird curl verwendet, um die ZIP-Datei von einer bestimmten URL zu holen und anschließend den Inhalt der ZIP-Datei in ein Verzeichnis zu entpacken. Hier sind die Schritte:
- Ersetze 
"extension_id"durch die tatsächliche ID der Erweiterung. - Führe die folgenden Befehle aus:
 
extension_id=your_extension_id   # Replace with the actual extension ID
curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc"
unzip -d "$extension_id-source" "$extension_id.zip"
Die CRX Viewer-Website verwenden
Die CRX Viewer-Erweiterung verwenden
Eine weitere bequeme Methode ist die Verwendung des Chrome Extension Source Viewer, ein Open-Source-Projekt. Es kann aus dem Chrome Web Store installiert werden. Der Quellcode des Viewers ist in seinem GitHub repository verfügbar.
Quellcode einer lokal installierten Erweiterung anzeigen
Lokal installierte Chrome-Erweiterungen können ebenfalls inspiziert werden. So geht's:
- Rufen Sie Ihr lokales Chrome-Profilverzeichnis auf, indem Sie 
chrome://version/öffnen und das Feld "Profile Path" finden. - Navigieren Sie zum Unterordner 
Extensions/im Profilverzeichnis. - Dieser Ordner enthält alle installierten Erweiterungen, typischerweise mit ihrem Quellcode in lesbarem Format.
 
Um Erweiterungen zu identifizieren, können Sie deren IDs den Namen zuordnen:
- Aktivieren Sie Developer Mode auf der 
about:extensions-Seite, um die IDs jeder Erweiterung zu sehen. - Innerhalb jedes Erweiterungsordners enthält die 
manifest.json-Datei ein lesbaresname-Feld, das bei der Identifikation hilft. 
Einen Datei-Archivierer oder Unpacker verwenden
Gehen Sie zum Chrome Web Store und laden Sie die Erweiterung herunter. Die Datei hat die Erweiterung .crx. Ändern Sie die Dateiendung von .crx zu .zip. Verwenden Sie einen beliebigen Datei-Archivierer (wie WinRAR, 7-Zip, etc.), um den Inhalt der ZIP-Datei zu extrahieren.
Developer Mode in Chrome verwenden
Öffnen Sie Chrome und gehen Sie zu chrome://extensions/. Aktivieren Sie "Developer mode" oben rechts. Klicken Sie auf "Load unpacked extension...". Navigieren Sie zum Verzeichnis Ihrer Erweiterung. Dadurch wird der Quellcode nicht heruntergeladen, aber es ist nützlich, um den Code einer bereits heruntergeladenen oder entwickelten Erweiterung anzusehen und zu modifizieren.
Chrome extension manifest dataset
In order to try to spot vulnerable browser extensions you could use thehttps://github.com/palant/chrome-extension-manifests-dataset and check their manifest files for potentially vulnerable signs. For example to check for extensions with more than 25000 users, content_scripts and the permission nativeMessaing:
# Query example from https://spaceraccoon.dev/universal-code-execution-browser-extensions/
node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.length > 0 && manifest.permissions?.includes('nativeMessaging')"
Post-exploitation: Forced extension load & persistence (Windows)
Stealthy technique to backdoor Chromium by directly editing per-user Preferences and forging valid HMACs, causing the browser to accept and activate an arbitrary unpacked extension without prompts or flags.
Forced Extension Load Preferences Mac Forgery Windows
Security Audit Checklist
Auch wenn Browser Extensions eine begrenzte Angriffsfläche haben, können einige von ihnen Vulnerabilities oder mögliche Härtungsverbesserungen enthalten. Die folgenden Punkte sind die häufigsten:
- 
Beschränke so weit wie möglich die angeforderten 
permissions - 
Beschränke so weit wie möglich 
host_permissions - 
Verwende eine starke 
content_security_policy - 
Beschränke so weit wie möglich das 
externally_connectable; wenn keines benötigt wird, lasse es nicht standardmäßig offen, setze{} - Wenn hier eine URL vulnerable to XSS or to takeover erwähnt wird, kann ein Angreifer directly send messages to the background scripts. Sehr mächtiger Bypass.
 - 
Beschränke so weit wie möglich die 
web_accessible_resources, idealerweise leer wenn möglich. - 
Falls 
web_accessible_resourcesnicht leer ist, prüfe auf ClickJacking - Wenn irgendeine Kommunikation von der Extension zur Webseite erfolgt, prüfe auf XSS Vulnerabilities, die durch die Kommunikation verursacht werden könnten.
 - Wenn Post Messages verwendet werden, prüfe auf Post Message vulnerabilities.
 - Wenn das Content Script auf DOM-Details zugreift, stelle sicher, dass dadurch keine XSS eingeführt werden, falls diese vom Web modifiziert werden
 - Lege besonderen Wert auf diese Kommunikation, wenn sie in der Content Script -> Background script communication involviert ist
 - Wenn das background script über native messaging kommuniziert, prüfe, dass die Kommunikation sicher ist und Eingaben sanitisiert werden
 - Sensitive information shouldn't be stored inside the Browser Extension code
 - Sensitive information shouldn't be stored inside the Browser Extension memory
 - Sensitive information shouldn't be stored inside the file system unprotected
 
Browser Extension Risks
- Die App https://crxaminer.tech/ analysiert einige Daten wie die angeforderten permissions einer Browser Extension, um ein Risikoniveau für die Nutzung der Browser Extension anzugeben.
 
Tools
Tarnish
- Lädt jede Chrome extension von einem angegebenen Chrome webstore link herunter.
 - manifest.json viewer: zeigt einfach eine JSON-prettified Version des Manifests der Extension an.
 - Fingerprint Analysis: Erkennung von web_accessible_resources und automatische Generierung von Chrome extension fingerprinting JavaScript.
 - Potential Clickjacking Analysis: Erkennung von Extension-HTML-Seiten mit der web_accessible_resources-Direktive. Diese können je nach Zweck der Seiten potentiell für Clickjacking anfällig sein.
 - Permission Warning(s) viewer: zeigt eine Liste aller Chrome permission prompt warnings, die angezeigt werden, wenn ein Benutzer versucht, die Extension zu installieren.
 - Dangerous Function(s): zeigt die Position potenziell gefährlicher Funktionen, die von einem Angreifer ausgenutzt werden könnten (z. B. Funktionen wie innerHTML, chrome.tabs.executeScript).
 - Entry Point(s): zeigt, wo die Extension Benutzer-/externe Eingaben entgegennimmt. Nützlich, um die Angriffsfläche einer Extension zu verstehen und potenzielle Stellen zu finden, um bösartig gestaltete Daten an die Extension zu senden.
 - Sowohl die Dangerous Function(s)- als auch die Entry Point(s)-Scanner liefern für ihre generierten Alerts Folgendes:
- Relevanter Code-Snippet und die Zeile, die den Alert ausgelöst hat.
 - Beschreibung des Problems.
 - Einen „View File“-Button, um die komplette Quelldatei mit dem Code anzusehen.
 - Den Pfad der betroffenen Datei.
 - Die vollständige Chrome extension URI der betroffenen Datei.
 - Den Dateityp, z. B. Background Page script, Content Script, Browser Action usw.
 - Falls die verwundbare Zeile in einer JavaScript-Datei ist, die Pfade aller Seiten, in denen sie eingebunden ist, sowie den Typ dieser Seiten und ihren web_accessible_resource-Status.
 
 - Content Security Policy (CSP) analyzer and bypass checker: Hebt Schwächen in der CSP deiner Extension hervor und zeigt mögliche Umgehungen der CSP durch erlaubte CDNs usw. auf.
 - Known Vulnerable Libraries: Verwendet Retire.js zur Überprüfung auf bekannte verwundbare JavaScript-Bibliotheken.
 - Download der Extension und formatierte Versionen.
 - Download der Original-Extension.
 - Download einer beautified Version der Extension (automatisch prettified HTML und JavaScript).
 - Automatisches Caching der Scan-Ergebnisse; der erste Scan einer Extension kann einige Zeit dauern. Beim zweiten Scan (sofern die Extension nicht aktualisiert wurde) ist das Ergebnis fast sofort verfügbar, da es gecached wurde.
 - Linkbare Report-URLs, um jemandem einfach einen Link zu einem von tarnish erstellten Extension-Report zu geben.
 
Neto
Project Neto ist ein Python 3 Paket, das entwickelt wurde, um versteckte Features von Browser plugins und extensions für bekannte Browser wie Firefox und Chrome zu analysieren und aufzudecken. Es automatisiert das Entpacken der gepackten Dateien, um relevante Ressourcen aus einer Extension wie manifest.json, Lokalisierungsordnern oder Javascript- und HTML-Quellfiles zu extrahieren.
References
- Thanks to @naivenom for the help with this methodology
 - https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing
 - https://palant.info/2022/08/10/anatomy-of-a-basic-extension/
 - https://palant.info/2022/08/24/attack-surface-of-extension-pages/
 - https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/
 - https://help.passbolt.com/assets/files/PBL-02-report.pdf
 - https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts
 - https://developer.chrome.com/docs/extensions/mv2/background-pages
 - https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/
 - https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0
 
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: 
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking: 
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
 - Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
 - Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
 
HackTricks