Blaaier-uitbreiding Pentesting Metodologie

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Basiese Inligting

Blaaier-uitbreidings word in JavaScript geskryf en deur die blaaier op die agtergrond gelaai. Dit het sy eie DOM maar kan met ander webwerwe se DOMs interakteer. Dit beteken dat dit die vertroulikheid, integriteit en beskikbaarheid (CIA) van ander werwe kan benadeel.

Hoofkomponente

Extension layouts lyk die beste wanneer dit gevisualiseer word en bestaan uit drie komponente. Kom ons kyk na elke komponent in diepte.

http://webblaze.cs.berkeley.edu/papers/Extensions.pdf

Content Scripts

Each content script has direct access to the DOM of a single web page and is thereby exposed to potentially malicious input. However, the content script contains no permissions other than the ability to send messages to the extension core.

Extension Core

The extension core contains most of the extension privileges/access, but the extension core can only interact with web content via XMLHttpRequest and content scripts. Also, the extension core does not have direct access to the host machine.

Native Binary

The extension allows a native binary that can access the host machine with the user’s full privileges. The native binary interacts with the extension core through the standard Netscape Plugin Application Programming Interface (NPAPI) used by Flash and other browser plug-ins.

Boundaries

Caution

Om die gebruiker se volle privileges te verkry, moet ’n aanvaller die uitbreiding oortuig om kwaadwillige invoer van die content script na die extension core en van die extension core na die native binary deur te gee.

Each component of the extension is separated from each other by strong protective boundaries. Each component runs in a separate operating system process. Content scripts and extension cores run in sandbox processes unavailable to most operating system services.

Moreover, content scripts separate from their associated web pages by running in a separate JavaScript heap. The content script and web page have access to the same underlying DOM, but the two never exchange JavaScript pointers, preventing the leak of JavaScript functionality.

manifest.json

A Chrome extension is just a ZIP folder with a .crx file extension. The extension’s core is the manifest.json file at the root of the folder, which specifies layout, permissions, and other configuration options.

Example:

{
"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 word gelaai wanneer die gebruiker na ’n ooreenstemmende bladsy navigeer, in ons geval enige bladsy wat ooreenstem met die https://example.com/* uitdrukking en nie ooreenstem met die *://*/*/business* regex nie. Hulle voer uit soos die bladsy se eie scripts en het willekeurige toegang tot die bladsy se Document Object Model (DOM).

"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],

Om meer URLs in te sluit of uit te sluit, is dit ook moontlik om include_globs en exclude_globs te gebruik.

Dit is ’n voorbeeld content script wat ’n explain button by die bladsy sal voeg wanneer the storage API gebruik word om die message waarde uit extension’s storage te haal.

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)
})

Wanneer hierdie knoppie geklik word, stuur die content script ’n boodskap na die extension pages deur gebruik te maak van die runtime.sendMessage() API. Dit is omdat content scripts beperkte direkte toegang tot APIs het, met storage as een van die enkele uitsonderings. Vir funksionaliteit buite hierdie uitsonderings word boodskappe na extension pages gestuur waarmee content scripts kan kommunikeer.

Warning

Afhangend van die blaaier kan die vermoëns van die content script effens verskil. Vir Chromium-gebaseerde blaaiers is die lys van vermoëns beskikbaar in die Chrome Developers documentation, en vir Firefox dien die MDN as die primêre bron.
Dit is ook noemenswaardig dat content scripts die vermoë het om met background scripts te kommunikeer, wat hulle in staat stel om aksies uit te voer en antwoorde terug te stuur.

Om content scripts in Chrome te bekyk en te debug, kan die Chrome developer tools-menu bereik word via Options > More tools > Developer tools OF deur Ctrl + Shift + I te druk.

Wanneer die developer tools vertoon word, klik op die Source tab, gevolg deur die Content Scripts tab. Dit maak dit moontlik om die lopende content scripts van verskeie extensions te besigtig en breakpoints te stel om die uitvoeringsvloei na te spoor.

Ingevoegde content scripts

Tip

Let wel dat Content Scripts nie verpligtend is nie, aangesien dit ook moontlik is om skripte dynamies te invoeg en om dit programmaties in webbladsye in te voeg via tabs.executeScript. Dit bied eintlik meer gedetailleerde beheer.

Vir die programmatiese invoeging van ’n content script, moet die extension host permissions hê vir die bladsy waarin die skripte ingevoeg gaan word. Hierdie permissies kan óf deur dit in die manifest van die extension te versoek verkry word óf tydelik deur activeTab.

Voorbeeld activeTab-gebaseerde extension

{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
  • Inspuit ’n JS file by klik:
// 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"],
})
})
  • Inject ’n funksie op klik:
//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,
})
})

Voorbeeld met 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" })

Om meer URLs in te sluit of uit te sluit is dit ook moontlik om include_globs en exclude_globs te gebruik.

Content-skripte run_at

Die run_at veld beheer wanneer JavaScript-lêers in die webblad ingespuit word. Die voorkeur- en verstekwaarde is "document_idle".

Die moontlike waardes is:

  • document_idle: Wanneer moontlik
  • document_start: Na enige lêers van css, maar voordat enige ander DOM opgebou word of enige ander script uitgevoer word.
  • document_end: Onmiddellik nadat die DOM voltooi is, maar voordat subhulpbronne soos beelde en rame gelaai is.

Deur manifest.json

{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}

Deur service-worker.js

chrome.scripting.registerContentScripts([
{
id: "test",
matches: ["https://*.example.com/*"],
runAt: "document_idle",
js: ["contentScript.js"],
},
])

background

Berigte wat deur content scripts gestuur word, word deur die agtergrondbladsy ontvang, wat ’n sentrale rol vervul in die koördinering van die uitbreiding se komponente. Noemenswaardig, die agtergrondbladsy bly gedurende die uitbreiding se lewensduur bestaan en funksioneer diskreet sonder direkte gebruikersinteraksie. Dit het sy eie Document Object Model (DOM), wat komplekse interaksies en toestandsbestuur moontlik maak.

Belangrike punte:

  • Rol van die agtergrondbladsy: Dien as die senuweesentrum van die uitbreiding, en verseker kommunikasie en koördinering tussen die verskillende dele van die uitbreiding.
  • Persistensie: Dit is ’n voortdurend teenwoordige entiteit, onsigbaar vir die gebruiker maar integraal tot die uitbreiding se funksionaliteit.
  • Outomatiese generering: As dit nie eksplisiet gedefinieer is nie, sal die blaaier outomaties ’n agtergrondbladsy skep. Hierdie outo-genereerde bladsy sal alle background scripts insluit wat in die uitbreiding se manifest gespesifiseer is, en sodoende die naatlose werking van die uitbreiding se agtergrondtake verseker.

Tip

Die gerief wat deur die blaaier gebied word deur outomaties ’n agtergrondbladsy te genereer (wanneer dit nie eksplisiet verklaar is nie) verseker dat alle nodige background scripts geïntegreer en funksioneel is, en vereenvoudig die uitbreiding se instellingsproses.

Example background script:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request == "explain") {
chrome.tabs.create({ url: "https://example.net/explanation" })
}
})

Dit gebruik runtime.onMessage API om na boodskappe te luister. Wanneer ’ “explain” ’ boodskap ontvang word, gebruik dit tabs API om ’n bladsy in ’n nuwe oortjie oop te maak.

Om die background script te debug kan jy na die extension details and inspect the service worker, gaan; dit sal die developer tools met die background script oopmaak:

Options pages and other

Browser extensions kan verskeie soorte bladsye bevat:

  • Action pages word vertoon in ’n drop-down when the extension icon wanneer dit geklik word.
  • Bladsye wat die extension sal load in a new tab.
  • Option Pages: Hierdie bladsy word bo-op die extension vertoon wanneer dit geklik word. In die vorige manifest kon ek in my geval hierdie bladsy toegang kry in chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca of deur te klik:

Neem kennis dat hierdie bladsye nie persistent is soos background pages nie aangesien hulle inhoud dinamies laai volgens behoefte. Nietemin deel hulle sekere vermoëns met die background page:

  • Communication with Content Scripts: Vergelykbaar met die background page, kan hierdie bladsye boodskappe vanaf content scripts ontvang en sodoende interaksie binne die extension vergemaklik.
  • Access to Extension-Specific APIs: Hierdie bladsye het uitgebreide toegang tot extension-specific APIs, onderhewig aan die permissions wat vir die extension gedefinieer is.

permissions & host_permissions

permissions en host_permissions is inskrywings in die manifest.json wat aandui watter permissions die browser extension het (storage, location…) en in watter web bladsye.

Aangesien browser extensions so privileged kan wees, kan ’n kwaadwillige een of een wat gekompromitteer is die aanvaller toelaat om verskeie maniere te hê om sensitiewe inligting te steel en die gebruiker te spioeneer.

Kyk hoe hierdie instellings werk en hoe hulle misbruik kan word in:

BrowExt - permissions & host_permissions

content_security_policy

’n content security policy kan ook binne die manifest.json verklaar word. As een gedefinieer is, kan dit kwesbaar wees.

Die verstekinstelling vir browser extension-bladsye is redelik beperk:

script-src 'self'; object-src 'self';

Vir meer inligting oor CSP en potensiële bypasses, sien:

Content Security Policy (CSP) Bypass

web_accessible_resources

Sodat ’n webblad toegang tot ’n bladsy van ’n blaaieruitbreiding kan kry, byvoorbeeld ’n .html bladsy, moet hierdie bladsy in die web_accessible_resources veld van die manifest.json.\
Byvoorbeeld:

{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}

Hierdie bladsye is beskikbaar by URL’s soos:

chrome-extension://<extension-id>/message.html

In openbare extensions is die extension-id toeganklik:

Asook, as die manifest.json parameter use_dynamic_url gebruik word, kan hierdie id dinamies wees.

Tip

Let wel dat selfs al word ’n bladsy hier genoem, dit moontlik teen ClickJacking beskerm is danksy die Content Security Policy. Jy moet dit ook (frame-ancestors section) nagaan voordat jy bevestig dat ’n ClickJacking-aanval moontlik is.

Dat hierdie bladsye toeganklik is, maak hulle potensieel kwesbaar vir ClickJacking:

BrowExt - ClickJacking

Tip

Om hierdie bladsye slegs deur die extension te laat laai en nie deur lukrake URLs nie, kan ClickJacking-aanvalle voorkom.

Caution

Let wel dat die bladsye in web_accessible_resources en ander bladsye van die extension ook in staat is om background scripts te kontak. As een van hierdie bladsye aan XSS onderhewig is, kan dit ’n groter kwesbaarheid blootlê.

Verder, let daarop dat jy slegs bladsye aangedui in web_accessible_resources binne iframes kan oopmaak, maar vanaf ’n nuwe tab is dit moontlik om enige bladsy in die extension te bereik as jy die extension ID ken. Daarom, as ’n XSS gevind word wat dieselfde parameters misbruik, kan dit uitgebuit word selfs al is die bladsy nie in web_accessible_resources gekonfigureer nie.

externally_connectable

Volgens die docs, verklaar die "externally_connectable" manifest-eiendom watter extensions en web bladsye aan jou extension kan koppel via runtime.connect en runtime.sendMessage.

  • As die externally_connectable sleutel nie in jou extension se manifest verklaar is of dit verklaar is as "ids": ["*"], kan alle extensions koppel, maar geen web bladsye kan koppel nie.
  • As spesifieke IDs gespesifiseer is, soos in "ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], kan slegs daardie toepassings koppel.
  • As matches gespesifiseer word, sal daardie web-apps in staat wees om te koppel:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
  • As dit as leeg gespesifiseer is: "externally_connectable": {}, sal geen app of web daarmee kan koppel.

Hoe minder extensions en URLs hier aangedui word, hoe kleiner sal die attack surface wees.

Caution

As ’n webbladsy kwesbaar vir XSS of takeover in externally_connectable aangetoon word, sal ’n aanvaller in staat wees om boodskappe direk na die background script te stuur, die Content Script en sy CSP heeltemal te omseil.

Daarom is dit ’n baie kragtige bypass.

Boonop, as die kliënt ’n rouge extension installeer, selfs al mag dit nie met die kwesbare extension kommunikeer nie, kan dit XSS data in ’n toegelate webbladsy inject of WebRequest of DeclarativeNetRequest APIs misbruik om versoeke op ’n geteikende domein te manipuleer deur die versoek van ’n bladsy vir ’n JavaScript file te verander. (Let wel: CSP op die geteikende bladsy kan hierdie aanvalle voorkom). Hierdie idee kom from this writeup.

Kommunikasie opsomming

Extension <–> WebApp

Om te kommunikeer tussen die content script en die webblad gebruik mens gewoonlik post messages. Daarom sal jy in die webtoepassing gewoonlik oproepe na die funksie window.postMessage vind en in die content script luisteraars soos window.addEventListener. Neem egter kennis dat die extension ook kan kommunikeer met die webtoepassing deur ’n Post Message te stuur (en dus behoort die web dit te verwag) of eenvoudig die web ’n nuwe script laat laai.

Binne die extension

Gewoonlik word die funksie chrome.runtime.sendMessage gebruik om ’n boodskap binne die extension te stuur (gewoonlik hanteer deur die background script) en om dit te ontvang en te hanteer word ’n luisteraar gedeclareer wat chrome.runtime.onMessage.addListener aanroep.

Dit is ook moontlik om chrome.runtime.connect() te gebruik om ’n volgehoue verbinding te hê in plaas van enkelboodskappe te stuur; dit kan gebruik word om boodskappe te stuur en te ontvang soos in die volgende voorbeeld:

chrome.runtime.connect() voorbeeld ```javascript 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 })

</details>

Dit is ook moontlik om boodskappe te stuur vanaf 'n background script na 'n content script wat in 'n spesifieke tab geleë is deur **`chrome.tabs.sendMessage`** aan te roep, waar jy die **ID van die tab** moet aandui om die boodskap na te stuur.

### Van toegelate `externally_connectable` na die extension

**Web apps en eksterne browser extensions wat in die `externally_connectable` konfigurasie toegelaat is** kan versoeke stuur deur gebruik te maak van :
```javascript
chrome.runtime.sendMessage(extensionId, ...

Waar dit nodig is om die extension ID te noem.

Native Messaging

Dit is moontlik dat die background scripts met binaries binne die stelsel kan kommunikeer, wat vatbaar kan wees vir kritieke kwesbaarhede soos RCEs as hierdie kommunikasie nie behoorlik beveilig is nie. More on this later.

chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)

Web ↔︎ Content Script Kommunikasie

Die omgewings waar content scripts werk en waar die gasheerbladsye bestaan, is van mekaar geskei, wat isolasie verseker. Ten spyte van hierdie isolasie, kan beide met die bladsy se Document Object Model (DOM) interageer, ’n gedeelde hulpbron. Vir die gasheerbladsy om in kommunikasie te tree met die content script, of indirek met die extension deur die content script, moet dit die DOM wat deur beide partye bereik kan word as die kommunikasiekanaal gebruik.

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
)

’n Veilige Post Message-kommunikasie moet die outentisiteit van die ontvangde boodskap nagaan; dit kan gedoen word deur te kontroleer:

  • event.isTrusted: Dit is True slegs as die gebeurtenis deur ’n gebruiker se aksie veroorsaak is
  • Die content script mag net ’n boodskap verwag as die gebruiker ’n aksie uitvoer
  • origin domain: kan net ’n boodskap verwag van ’n allowlist van domains.
  • As ’n regex gebruik word, wees baie versigtig
  • Source: received_message.source !== window kan gebruik word om te bepaal of die boodskap van dieselfde venster is waar die Content Script luister.

Die voorafgaande kontroles, selfs al word hulle uitgevoer, kan kwesbaar wees—sien op die volgende bladsy potential Post Message bypasses:

PostMessage Vulnerabilities

Iframe

Nog ’n moontlike kommunikasiepad kan via Iframe URLs wees; jy kan ’n voorbeeld vind in:

BrowExt - XSS Example

DOM

Dit is nie presies ’n kommunikasieweg nie, maar die web en die content script sal toegang tot die web DOM hê. Dus, as die content script sekere inligting daaruit lees en die web DOM vertrou, kan die web hierdie data wysig (omdat die web nie vertrou behoort te word nie, of omdat die web kwesbaar is vir XSS) en die Content Script kompromitteer.

Jy kan ook ’n voorbeeld van ’n DOM based XSS to compromise a browser extension vind in:

BrowExt - XSS Example

Content Script ↔︎ Background Script Kommunikasie

A Content Script kan die funksies runtime.sendMessage() of tabs.sendMessage() gebruik om ’n one-time JSON-serializable boodskap te stuur.

Om die response te hanteer, gebruik die teruggegewe Promise. Vir agteruitskompatibiliteit kan jy egter steeds ’n callback as die laaste argument deurgee.

Om ’n versoek vanaf ’n content script te stuur lyk so:

;(async () => {
const response = await chrome.runtime.sendMessage({ greeting: "hello" })
// do something with response here, not outside the function
console.log(response)
})()

Stuur ’n versoek vanaf die extension (gewoonlik ’n background script). Voorbeeld van hoe om ’n message aan die content script in die geselekteerde tab te stuur:

// 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)
})()

Aan die ontvangkant moet jy ’n runtime.onMessage event listener opstel om die boodskap te hanteer. Dit lyk dieselfde vanaf ’n content script of extension page.

// 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" })
})

In die voorbeeld wat uitgelig is, is sendResponse() sinchronies uitgevoer. Om die onMessage-gebeurtenishanteraar aan te pas vir asynchrone uitvoering van sendResponse(), is dit noodsaaklik om return true; in te sluit.

’n Belangrike oorweging is dat in scenario’s waar meerdere bladsye ingestel is om onMessage-gebeurtenisse te ontvang, die eerste bladsy wat sendResponse() vir ’n spesifieke gebeurtenis uitvoer die enigste een sal wees wat die antwoord effektief kan lewer. Enige daaropvolgende antwoorde op dieselfde gebeurtenis sal nie in ag geneem word nie.

Wanneer nuwe uitbreidings geskep word, behoort die voorkeur aan promises te wees eerder as callbacks. Met betrekking tot die gebruik van callbacks, word die sendResponse()-funksie slegs as geldig beskou as dit direk binne die sinchroniese konteks uitgevoer word, of as die gebeurtenishanteraar ’n asynchrone bewerking aandui deur true terug te gee. As geen van die hanteraars true teruggee nie, of as die sendResponse()-funksie van die geheue verwyder word (garbage-collected), sal die callback wat met die sendMessage()-funksie geassosieer is standaard geaktiveer word.

Native Messaging

Browser-uitbreidings laat ook toe om met binaries in the system via stdin te kommunikeer. Die toepassing moet ’n json installeer wat dit aandui in ’n json soos:

{
"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/"]
}

Waar die name die string is wat aan runtime.connectNative() of runtime.sendNativeMessage() deurgegee word om met die toepassing te kommunikeer vanaf die achtergrondskripte van die blaaieruitbreiding. Die path is die pad na die binary, daar is net 1 geldige type wat stdio is (gebruik stdin en stdout) en die allowed_origins dui die uitbreidings aan wat toegang daartoe het (en mag geen wildcard hê nie).

Chrome/Chromium sal vir hierdie json in sekere Windows-register en in sekere paaie op macOS en Linux soek (meer info in die docs).

Tip

Die blaaieruitbreiding het ook die nativeMessaing permission verklaar nodig om hierdie kommunikasie te kan gebruik.

So lyk dit wanneer ’n agtergrondskrip kode boodskappe aan ’n native toepassing stuur:

chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)

In this blog post, word ’n kwesbare patroon voorgestel wat native messages misbruik:

  1. Browser extension het ’n wildcard-patroon vir content script.
  2. Content script stuur postMessage-boodskappe na die background script met behulp van sendMessage.
  3. Background script gee die boodskap aan die native application deur sendNativeMessage.
  4. Native application hanteer die boodskap gevaarlik, wat tot code execution lei.

En daarin word ’n voorbeeld van om van enige bladsy na RCE deur ’n browser extension te misbruik verduidelik.

Gevoelige Inligting in Geheue/Kode/Klembord

As ’n blaaieruitbreiding gevoelige inligting in sy geheue stoor, kan dit gedump word (veral op Windows-masjiene) en gesoek word na daardie inligting.

Daarom behoort die geheue van die blaaieruitbreiding nie as veilig beskou te word nie en gevoelige inligting soos credentials of mnemonic phrases moet nie gestoor word nie.

Natuurlik, plaas nie gevoelig inligting in die kode nie, aangesien dit openbaar sal wees.

Om geheue van die blaaier te dump kan jy die prosesgeheue dump of gaan na die instellings van die blaaieruitbreiding en klik op Inspect pop-up -> In die Memory afdeling -> Take a snaphost en gebruik CTRL+F om binne die snapshot na sensitiewe inligting te soek.

Verder behoort uiters sensitiewe inligting soos mnemonic keys of wagwoorde nie in die klembord toegelaat te word om gekopieer te word nie (of ten minste dit na ’n paar sekondes uit die klembord te verwyder) aangesien prosesse wat die klembord monitor dit dan kan kry.

Laai ’n Extension in die Blaaier

  1. Download die Browser Extension & unzip
  2. Gaan na chrome://extensions/ en skakel aan die Developer Mode
  3. Klik die Load unpacked knoppie

In Firefox gaan jy na about:debugging#/runtime/this-firefox en klik die Load Temporary Add-on knoppie.

Kry die bronkode vanaf die store

Die bronkode van ’n Chrome extension kan deur verskeie metodes verkry word. Hieronder is gedetailleerde verduidelikings en instruksies vir elke opsie.

Download Extension as ZIP via Command Line

Die bronkode van ’n Chrome extension kan as ’n ZIP-lêer afgelaai word met behulp van die command line. Dit behels die gebruik van curl om die ZIP-lêer van ’n spesifieke URL te kry en dan die inhoud van die ZIP-lêer na ’n gids uit te pak. Hier is die stappe:

  1. Vervang "extension_id" met die werklike ID van die extension.
  2. Voer die volgende opdragte uit:
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"

Gebruik die CRX Viewer-webwerf

https://robwu.nl/crxviewer/

Gebruik die CRX Viewer-uitbreiding

Nog ’n gerieflike metode is om die Chrome Extension Source Viewer te gebruik, wat ’n open-source projek is. Dit kan vanaf die Chrome Web Store geïnstalleer word. Die bronkode van die viewer is beskikbaar in sy GitHub repository.

Bekyk bron van lokaal geïnstalleerde uitbreiding

Chrome-uitbreidings wat plaaslik geïnstalleer is, kan ook ondersoek word. Só doen jy dit:

  1. Gaan na jou Chrome-lokale profielgids deur chrome://version/ te besoek en die “Profile Path” veld te vind.
  2. Navigeer na die Extensions/ submap binne die profielgids.
  3. Hierdie gids bevat al die geïnstalleerde uitbreidings, gewoonlik met hul bronkode in ’n leesbare formaat.

Om uitbreidings te identifiseer, kan jy hul IDs aan name koppel:

  • Skakel “Developer Mode” aan op die about:extensions bladsy om die IDs van elke uitbreiding te sien.
  • Binnenin elke uitbreiding se gids bevat die manifest.json lêer ’n leesbare name veld wat jou help om die uitbreiding te identifiseer.

Gebruik ’n lêargiefprogram of uitpakker

Gaan na die Chrome Web Store en laai die uitbreiding af. Die lêer sal ’n .crx uitbreiding hê. Verander die lêeruitbreiding van .crx na .zip. Gebruik enige lêargiefprogram (soos WinRAR, 7-Zip, ens.) om die inhoud van die ZIP-lêer uit te pak.

Gebruik Developer Mode in Chrome

Open Chrome en gaan na chrome://extensions/. Skakel “Developer mode” regs bo aan. Klik op “Load unpacked extension…”. Navigeer na die gids van jou uitbreiding. Dit laai nie die bronkode af nie, maar dit is nuttig om die kode van ’n reeds afgelaaide of ontwikkelde uitbreiding te bekyk en te wysig.

Chrome extension manifest dataset

Om kwesbare browser-uitbreidings te probeer opspoor, kan jy die https://github.com/palant/chrome-extension-manifests-dataset gebruik en hul manifestlêers vir moontlike kwesbare tekens nagaan. Byvoorbeeld, om uitbreidings te soek met meer as 25000 gebruikers, content_scripts en die toestemming 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)

Diskrete tegniek om Chromium te backdoor deur per-user Preferences direk te wysig en geldige HMACs te vervals, sodat die browser ’n ewekansige unpacked extension sonder prompts of flags aanvaar en aktiveer.

Forced Extension Load Preferences Mac Forgery Windows

Detecting Malicious Extension Updates (Static Version Diffing)

Supply-chain compromises kom dikwels voor as malicious updates aan voorheen goedaardige extensions. ’n Praktiese, lae-ruis benadering is om ’n nuwe extension package teenoor die laaste known-good version te vergelyk met behulp van static analysis (byvoorbeeld, Assemblyline). Die doel is om op high-signal deltas te waarsku eerder as op enige verandering.

Workflow

  • Submit both versions (old + new) na dieselfde static-analysis profiel.
  • Flag new or updated background/service worker scripts (persistence + privileged logic).
  • Flag new or updated content scripts (DOM access en data-insameling).
  • Flag new permissions/host_permissions wat by manifest.json gevoeg is.
  • Flag new domains onttrek uit code (potensiële C2/exfil endpoints).
  • Flag new static-analysis detections (bv. base64 decode, cookie harvesting, network-request builders, obfuscation patterns).
  • Flag statistical anomalies soos skerp entropy spronge of uitskieters in z-scores in veranderde scripts.

Detecting script changes accurately

  • New script added → detecteer via manifest.json diff.
  • Existing script modified (manifest unchanged) → vergelyk per-file hashes van die uitgepakke file tree (bv. Assemblyline Extract output). Dit vang stealthy updates aan bestaande workers of content scripts.

Pre-disclosure detections

Om “easy mode” detections gebaseer op reeds-bekende IOCs te vermy, deaktiveer threat-intel-fed services en vertrou op intrinsieke seine (domains, heuristic signatures, script deltas, entropy anomalies). Dit verhoog die kans om malicious updates voor publieke rapportering te betrap.

Example high-confidence alert logic

  • Low-noise combo: new domains + new static-analysis detections + updated background/service worker + updated of added content scripts.
  • Broader catch: new domain + new or updated background/service worker (hogere recall, meer noise).

Key Assemblyline services vir hierdie workflow:

  • Extract: pak die extension uit en gee per-file hashes.
  • Characterize: bereken file kenmerke (bv. entropy).
  • JsJAWS / FrankenStrings / URLCreator: verskaf JS heuristieke, strings, en domains om tussen weergawes te diff.

Security Audit Checklist

Alhoewel Browser Extensions ’n beperkte attack surface het, kan sommige van hulle vulnerabilities of potential hardening improvements bevat. Die volgende is die mees algemene:

  • Limit soveel as moontlik versoekte permissions
  • Limit soveel as moontlik host_permissions
  • Gebruik ’n strong content_security_policy
  • Limit soveel as moontlik die externally_connectable; as geen nodig is nie, moenie dit per verstek laat staan nie—spesifiseer {}
  • As URL vulnerable to XSS or to takeover hier genoem word, kan ’n aanvaller direk messages to the background scripts stuur. Baie kragtige bypass.
  • Limit soveel as moontlik die web_accessible_resources, selfs leeg indien moontlik.
  • As web_accessible_resources nie none is nie, kyk vir ClickJacking
  • As enige communication vanaf die extension na die web page plaasvind, check for XSS vulnerabilities in daardie kommunikasie.
  • As Post Messages gebruik word, kyk vir Post Message vulnerabilities.
  • As die Content Script toegang tot DOM besonderhede het, vergewis jou dat dit nie ’n XSS inleiding indien dit deur die web gemodifiseer word nie.
  • Beklemtoon veral as hierdie kommunikasie betrokke is by Content Script -> Background script communication
  • As die background script kommunikeer via native messaging, vergewis jou dat die kommunikasie veilig en gesanitize is
  • Sensitive information shouldn’t be stored binne die Browser Extension code
  • Sensitive information shouldn’t be stored binne die Browser Extension memory
  • Sensitive information shouldn’t be stored op die file system unprotected

Browser Extension Risks

  • Die app https://crxaminer.tech/ ontleed sekere data soos die permissions wat ’n browser extension versoek om ’n risk level van die extension se gebruik te gee.

Tools

Tarnish

  • Trek enige Chrome extension van ’n gegewe Chrome webstore link.
  • manifest.json viewer: wys ’n JSON-prettified weergawe van die extension se manifest.
  • Fingerprint Analysis: Opsporing van web_accessible_resources en outomatiese generering van Chrome extension fingerprinting JavaScript.
  • Potential Clickjacking Analysis: Opsporing van extension HTML bladsye met die web_accessible_resources directive ingestel. Hierdie kan potensieel kwesbaar wees vir clickjacking, afhangend van die doel van die bladsye.
  • Permission Warning(s) viewer: wys ’n lys van al die Chrome permission prompt waarskuwings wat vertoon sal word wanneer ’n gebruiker probeer om die extension te installeer.
  • Dangerous Function(s): wys die ligging van gevaarlike funksies wat moontlik deur ’n aanvaller uitgebuit kan word (bv. funksies soos innerHTML, chrome.tabs.executeScript).
  • Entry Point(s): wys waar die extension gebruikers-/eksterne insette ontvang. Dit help om die extension se surface area te verstaan en potensiële punte te vind om kwaadwillig-saamgestelde data na die extension te stuur.
  • Beide die Dangerous Function(s) en Entry Point(s) scanners se gegenereerde alerts bevat:
  • Relevante code snippet en lyn wat die alert veroorsaak het.
  • Beskrywing van die kwessie.
  • ’n “View File” knoppie om die volledige bronlêer met die kode te sien.
  • Die pad van die geflagde lêer.
  • Die volledige Chrome extension URI van die geflagde lêer.
  • Die tipe lêer, soos ’n Background Page script, Content Script, Browser Action, ens.
  • As die kwesbare lyn in ’n JavaScript-lêer is, die paaie van al die bladsye waar dit ingesluit is asook daardie bladsye se tipe, en web_accessible_resource status.
  • Content Security Policy (CSP) analyzer and bypass checker: Wys swakpunte in jou extension se CSP en belig moontlike maniere om die CSP te omseil as gevolg van witgelyste CDNs, ens.
  • Known Vulnerable Libraries: Gebruik Retire.js om te kontroleer vir gebruik van bekende kwesbare JavaScript-biblioteke.
  • Download extension en geformatteerde weergawes.
  • Download die oorspronklike extension.
  • Download ’n beautified weergawe van die extension (outomaties prettified HTML en JavaScript).
  • Outomatiese caching van scan resultate; ’n extension scan neem ’n goeie bietjie tyd die eerste keer wat jy dit hardloop. Maar die tweede keer, veronderstel die extension is nie opgedateer nie, sal dit byna onmiddellik wees weens die resultate wat in die cache is.
  • Linkable Report URLs, maklik om iemand anders ’n extension report gegenereer deur tarnish te skakel.

Neto

Project Neto is ’n Python 3 pakket geskep om versteekte kenmerke van browser plugins en extensions vir bekende browsers soos Firefox en Chrome te ontleed en te openbaar. Dit outomatiseer die proses om die gepakte lêers uit te pak om hierdie kenmerke uit relevante hulpbronne in ’n extension soos manifest.json, localization folders of Javascript en HTML bronlêers te onttrek.

References

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks