40 KiB
Blaaieruitbreiding Pentesting Metodologie
{{#include ../../banners/hacktricks-training.md}}
Basiese Inligting
Blaaieruitbreidings is in JavaScript geskryf en word deur die blaaier in die agtergrond gelaai. Dit het sy eie DOM maar kan met ander sites se DOMs interaksie hê. Dit beteken dat dit die vertroulikheid, integriteit en beskikbaarheid (CIA) van ander sites kan kompromitteer.
Hoofkomponente
Extension layouts lyk die beste wanneer dit gevisualiseer word en bestaan uit drie komponente. Kom ons kyk na elke komponent in diepte.

Content Scripts
Each content script het direkte toegang tot die DOM van 'n single web page en is daarmee blootgestel aan potentially malicious input. Die content script bevat egter geen permissies behalwe die vermoë om boodskappe na die extension core te stuur nie.
Extension Core
Die extension core bevat die meeste van die uitbreiding se voorregte/toegang, maar die extension core kan slegs met webinhoud kommunikeer via XMLHttpRequest en content scripts. Ook het die extension core nie direkte toegang tot die gasheermasjien nie.
Native Binary
Die uitbreiding laat 'n native binary toe wat toegang tot die gasheermasjien met die gebruiker se volle voorregte kan hê. Die native binary kommunikeer met die extension core deur die standaard Netscape Plugin Application Programming Interface (NPAPI) wat deur Flash en ander browser plug-ins gebruik word.
Grense
Caution
Om die gebruiker se volle voorregte te verkry, moet 'n aanvaller die uitbreiding oortuig om malicious input van die content script na die extension core en van die extension core na die native binary deur te gee.
Elke komponent van die uitbreiding is van mekaar geskei deur sterk beskermende grense. Elke komponent loop in 'n afsonderlike operating system process. Content scripts en extension cores loop in sandbox processes wat nie beskikbaar is vir die meeste operating system-dienste nie.
Verder is content scripts van hul geassosieerde webbladsye geskei deur in 'n aparte JavaScript heap te loop. Die content script en webblad het access to the same underlying DOM, maar die twee never exchange JavaScript pointers, wat die leaking van JavaScript-funksionaliteit voorkom.
manifest.json
'n Chrome extension is net 'n ZIP-lêergids met 'n .crx file extension. Die kern van die uitbreiding is die manifest.json
lêer in die wortel van die gids, wat layout, permissies en ander konfigurasie-opsies spesifiseer.
Voorbeeld:
{
"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-skripte 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 word uitgevoer soos die bladsy se eie skripte en het arbitrêre 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-knoppie aan die bladsy sal voeg wanneer the storage API gebruik word om die message
-waarde uit die 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 die content script beperkte direkte toegang tot APIs het, met storage
as een van die paar 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 browsers 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 vermeldenswaardig dat content scripts met background scripts kan kommunikeer, wat dit toelaat om aksies uit te voer en antwoorde terug te stuur.
Om content scripts in Chrome te sien en te debug, kan jy die Chrome developer tools-menu oopmaak via Options > More tools > Developer tools OF deur Ctrl + Shift + I te druk.
Sodra die developer tools gewys word, klik op die Source tab, gevolg deur die Content Scripts tab. Dit maak dit moontlik om lopende content scripts van verskeie extensions te besigtig en breakpoints te stel om die uitvoeringsvloei te volg.
Ingespuitte content scripts
Tip
Let wel dat Content Scripts nie verpligtend is nie, aangesien dit ook moontlik is om skripte dinamies te inspuit en om hulle programmaties in webbladsye in te spuit via
tabs.executeScript
. Dit bied eintlik meer fyn beheer.
Vir die programmatiese inspuiting van 'n content script, moet die extension host permissions hê vir die bladsy waarin die skripte ingespuit gaan word. Hierdie permissies kan verkry word deur hulle binne die manifest van die extension aan te vra of tydelik via activeTab.
Voorbeeld van activeTab-gebaseerde extension
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
- Inject 'n JS-lêer wanneer daar op geklik word:
// 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"],
})
})
- Injekteer 'n function met 'n 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-toestemmings
// 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 URL's 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 ingesit word. Die voorkeur- en standaardwaarde is "document_idle"
.
Die moontlike waardes is:
document_idle
: Wanneer moontlikdocument_start
: Na enige lêers vancss
, maar voordat enige ander DOM opgebou is of enige ander script uitgevoer word.document_end
: Onmiddellik nadat die DOM voltooi is, maar voordat subbronne 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
Boodskappe wat deur content scripts gestuur word, word ontvang deur die agtergrondblad, wat 'n sentrale rol speel in die koördinering van die uitbreiding se komponente. Belangrik is dat die agtergrondblad oor die lewensduur van die uitbreiding voortbestaan en stilweg werk sonder direkte gebruikersinteraksie. Dit het sy eie Document Object Model (DOM), wat ingewikkelde interaksies en toestandbestuur moontlik maak.
Belangrike Punte:
- Rol van die Agtergrondblad: Dien as die senuweesentrum van die uitbreiding en verseker kommunikasie en koördinering tussen verskeie dele van die uitbreiding.
- Persistensie: Dit is 'n steeds-aanwesige entiteit, onsigbaar vir die gebruiker maar integraal tot die uitbreiding se funksionaliteit.
- Outomatiese Generering: As dit nie eksplisiet gedefinieer is nie, sal die browser outomaties 'n agtergrondblad skep. Hierdie outo-gegenereerde blad sal al die agtergrondskripte insluit wat in die uitbreiding se manifest gespesifiseer is, wat die naatlose werking van die uitbreiding se agtergrondtake verseker.
Tip
Die gerief wat die browser bied deur outomaties 'n agtergrondblad te genereer (wanneer dit nie eksplisiet verklaar is nie) verseker dat alle nodige agtergrondskripte geïntegreer en operasioneel is, wat die opstelproses van die uitbreiding vereenvoudig.
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 die "explain"
boodskap ontvang word, gebruik dit tabs API om 'n bladsy in 'n nuwe tabblad oop te maak.
To debug die background script 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 tipes bladsye bevat:
- Action pages word vertoon in 'n drop-down wanneer die extension icon geklik word.
- Bladsye wat die extension sal load in a new tab.
- Option Pages: Hierdie bladsy verskyn bo-op die extension wanneer dit geklik word. In die vorige manifest kon ek hierdie bladsy in my geval toegang kry by
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
of deur te klik:

Let wel dat hierdie bladsye nie persistent is soos background pages nie, aangesien hulle dinamies content laai wanneer nodig. Ten spyte hiervan deel hulle sekere vermoëns met die background page:
- Communication with Content Scripts: Soortgelyk aan die background page, kan hierdie bladsye boodskappe van content scripts ontvang, wat 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 webbladsye.
Aangesien browser extensions so privileged kan wees, kan 'n kwaadwillige een of een wat gekompromitteer is die aanvaller toelaat verskeie maniere om sensitiewe inligting te steel en die gebruiker te bespioneer.
Kyk hoe hierdie instellings werk en hoe hulle misbruik kan word in:
{{#ref}} browext-permissions-and-host_permissions.md {{#endref}}
content_security_policy
'n content security policy kan ook binne die manifest.json
gedefinieer word. Indien een gedefinieer is, kan dit kwesbaar wees.
Die standaardinstelling vir browser extension-bladsye is redelik beperkend:
script-src 'self'; object-src 'self';
Vir meer inligting oor CSP en potensiële bypasses, sien:
{{#ref}} ../content-security-policy-csp-bypass/ {{#endref}}
web_accessible_resources
Sodat 'n webblad toegang tot 'n bladsy van 'n Browser Extension (byvoorbeeld 'n .html
bladsy) kan kry, moet hierdie bladsy in die web_accessible_resources
veld van die manifest.json
genoem word.
Byvoorbeeld:
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
Hierdie bladsye is beskikbaar via URL's soos:
chrome-extension://<extension-id>/message.html
In openbare uitbreidings is die extension-id toeganklik:

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 dalk teen ClickJacking beskerm is danksy die Content Security Policy. Jy moet dit dus ook nagaan (frame-ancestors section) voordat jy bevestig dat 'n ClickJacking-aanval moontlik is.
Dat toegang tot hierdie bladsye toegestaan is, maak hulle potensieel kwesbaar vir ClickJacking:
{{#ref}} browext-clickjacking.md {{#endref}}
Tip
Deur toe te laat dat hierdie bladsye slegs deur die uitbreiding gelaai word en nie deur ewekansige URLs nie, kan ClickJacking-aanvalle voorkom word.
Caution
Let wel dat die bladsye uit
web_accessible_resources
en ander bladsye van die uitbreiding ook in staat is om contact te maak met background scripts. Dus, as een van hierdie bladsye kwesbaar is vir XSS kan dit 'n groter kwesbaarheid oopmaak.Verder, let op dat jy slegs bladsye wat in
web_accessible_resources
aangedui is binne iframes kan open, maar vanaf 'n nuwe tab is dit moontlik om enige bladsy in die uitbreiding te toegang te kry as jy die extension ID ken. Daarom, as 'n XSS gevind word wat dieselfde parameters misbruik, kan dit misbruik word selfs al is die bladsy nie inweb_accessible_resources
gekonfigureer nie.
externally_connectable
Volgens die docs verklaar die "externally_connectable"
manifest-eienskap watter extensions en webbladsye kan koppel aan jou uitbreiding via runtime.connect en runtime.sendMessage.
- As die
externally_connectable
sleutel nie in jou uitbreiding se manifest verklaar is nie, of dit verklaar is as"ids": ["*"]
, kan alle extensions koppel, maar geen webbladsye kan koppel nie. - As spesifieke IDs aangedui is, soos in
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, kan slegs daardie toepassings koppel. - As matches gespesifiseer is, 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 webwerf in staat wees om te koppel nie.
Hoe minder extensies en URL's hier aangedui word, hoe kleiner sal die aanvalsvlak wees.
Caution
Indien 'n webbladsy kwetsbaar vir XSS of takeover in
externally_connectable
aangedui word, sal 'n aanvaller in staat wees om boodskappe direk na die background script te stuur, en die Content Script en sy CSP heeltemal te omseil.Daarom is dit 'n baie kragtige bypass.
Verder, as die kliënt 'n rogue extension installeer, selfs al is dit nie toegelaat om met die kwesbare extension te kommunikeer nie, kan dit XSS data in 'n toegelate web page injekteer of
WebRequest
ofDeclarativeNetRequest
APIs misbruik om versoeke op 'n geteikende domein te manipuleer deur 'n blad se versoek na 'n JavaScript file te verander. (Let daarop dat CSP op die geteikende blad hierdie aanvalle kan voorkom). This idea comes 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 web application 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 web application deur 'n Post Message te stuur (en dus behoort die web dit te verwag) of eenvoudig die web laat 'n nuwe script 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 listener 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 enkel boodskappe te stuur; dit kan gebruik word om send en receive messages 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 van 'n background script na 'n content script wat in 'n spesifieke tab geleë is, te stuur deur **`chrome.tabs.sendMessage`** aan te roep, waar jy die **ID of the tab** moet aandui om die boodskap na te stuur.
### Van toegelate `externally_connectable` na die extension
**Web apps en eksterne browser extensions wat toegelaat is** in die `externally_connectable` konfigurasie kan versoeke stuur met behulp van :
```javascript
chrome.runtime.sendMessage(extensionId, ...
Waar dit nodig is om die extension ID.
Native Messaging
Dit is moontlik vir die background scripts om met binaries binne die stelsel te kommunikeer, wat gevoelig 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 opereer en waar die gasheerbladsye bestaan, is van mekaar geskei, wat isolasie verseker. Ten spyt van hierdie isolasie het beide die vermoë om met die bladsy se Document Object Model (DOM), 'n gedeelde hulpbron, te kommunikeer. Vir die gasheerbladsy om met die content script te kommunikeer, of indirek met die extension deur die content script, moet dit die DOM wat deur albei partye toeganklik is, 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 egtheid 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 getrigger is- Die content script mag net 'n boodskap verwag as die gebruiker 'n aksie uitvoer
- origin domain: kan 'n boodskap slegs van 'n allowlist van domeine verwag
- If a regex is used, be very careful
- Source:
received_message.source !== window
kan gebruik word om te kontroleer of die boodskap van dieselfde venster was waarin die Content Script luister.
Die vorige kontroles, selfs as dit gedoen is, kan kwesbaar wees, so kyk op die volgende bladsy na potensiële Post Message bypasses:
{{#ref}} ../postmessage-vulnerabilities/ {{#endref}}
Iframe
Nog 'n moontlike kommunikasieweg kan deur Iframe URLs wees, jy kan 'n voorbeeld vind in:
{{#ref}} browext-xss-example.md {{#endref}}
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 sommige 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 aan XSS kwesbaar is) en die Content Script kompromitteer.
Jy kan ook 'n voorbeeld vind van 'n DOM gebaseerde XSS om 'n browser extension te kompromitteer in:
{{#ref}} browext-xss-example.md {{#endref}}
Content Script ↔︎ Background Script Communication
'n Content Script kan die funksies runtime.sendMessage() or tabs.sendMessage() gebruik om 'n eenmalige JSON-serializable boodskap te stuur.
Om die response te hanteer, gebruik die teruggegewe Promise. Alhoewel, vir agterwaartse versoenbaarheid, kan jy steeds 'n callback as die laaste argument deurgee.
Die stuur van 'n versoek vanaf 'n content script lyk soos volg:
;(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 boodskap na die content script in die selected 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 ontvangende kant moet jy 'n runtime.onMessage event listener opstel om die boodskap te hanteer. Dit lyk dieselfde vanuit '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 uitgeligde voorbeeld is sendResponse()
sinchronies uitgevoer. Om die onMessage
event handler vir asynchrone uitvoering van sendResponse()
te wysig, is dit noodsaaklik om return true;
in te voeg.
'n Belangrike oorweging is dat in scenario's waar meerdere bladsye ingestel is om onMessage
events te ontvang, die eerste bladsy wat sendResponse()
vir 'n spesifieke event uitvoer die enigste een sal wees wat die response effektief kan lewer. Enige daaropvolgende responses op dieselfde event sal nie in ag geneem word nie.
Wanneer nuwe extensions geskep word, behoort die voorkeur aan promises bo callbacks te wees. Met betrekking tot die gebruik van callbacks word die sendResponse()
funksie slegs as geldig beskou indien dit direk binne die sinchroniese konteks uitgevoer word, of indien die event handler 'n asynchrone operasie aandui deur return true;
terug te gee. Indien geen van die handlers return true;
teruggee nie, of indien die sendResponse()
funksie uit geheue verwyder word (garbage-collected), sal die callback geassosieer met die sendMessage()
funksie standaard getrigger word.
Native Messaging
Browser extensions laat ook toe om met binaries in die stelsel 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 vanuit die agtergrondskripte van die blaaieruitbreiding te kommunikeer. Die path
is die pad na die binêre, daar is net 1 geldige type
wat stdio is (gebruik stdin en stdout) en die allowed_origins
dui die extensies aan wat toegang daartoe het (en kan nie 'n wildcard hê nie).
Chrome/Chromium sal na hierdie json soek in sekere Windows-register en in sekere paaie op macOS en Linux (meer inligting in die docs).
Tip
Die blaaieruitbreiding het ook die
nativeMessaing
permission nodig wat verklaar moet word om hierdie kommunikasie te kan gebruik.
So lyk dit wanneer 'n agtergrondskrip kode boodskappe na 'n native toepassing stuur:
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)
In this blog post, 'n kwesbare patroon wat native messages misbruik, word voorgestel:
- Browser-uitbreiding het 'n wildcard-patroon vir content script.
- Content script stuur
postMessage
-boodskappe na die background script metsendMessage
. - Background script stuur die boodskap aan die native application met
sendNativeMessage
. - Die native application hanteer die boodskap op 'n gevaarlike wyse, wat lei tot code execution.
En daarin word 'n voorbeeld verduidelik van hoe om van enige bladsy na RCE te gaan deur 'n browser-uitbreiding te misbruik.
Sensitiewe Inligting in Geheue/Kode/Kleefbord
As 'n blaaier-uitbreiding sensitiewe inligting in sy geheue stoor, kan dit uitgelaai (veral op Windows-masjiene) en daarna vir daardie inligting deurgesoek word.
Daarom moet die geheue van die blaaier-uitbreiding nie as veilig beskou word nie en sensitiewe inligting soos aanmeldbewyse of mnemoniese frases moet nie gestoor word nie.
Plaas natuurlik nie sensitiewe inligting in die kode nie, aangesien dit publiek sal wees.
Om geheue van die blaaier te onttrek kan jy byvoorbeeld die prosesgeheue uitgelaai, of na die instellings van die blaaier-uitbreiding gaan en op Inspect pop-up
klik -> In die Memory
afdeling -> Take a snaphost
en CTRL+F
gebruik om binne die snapshot na sensitiewe inligting te soek.
Verder moet uiters sensitiewe inligting soos mnemoniese sleutels of wagwoorde nie in die kleefbord toegelaat word om gekopieer te word nie (of veral dit binne 'n paar sekondes uit die kleefbord verwyder), omdat prosesse wat die kleefbord monitor dit kan kry.
Loading an Extension in the Browser
- Laai die blaaier-uitbreiding af en pak dit uit
- Gaan na
chrome://extensions/
en aktiveer dieDeveloper Mode
- Klik die
Load unpacked
knoppie
In Firefox gaan jy na about:debugging#/runtime/this-firefox
en klik op die Load Temporary Add-on
knoppie.
Getting the source code from the store
Die bronkode van 'n Chrome extension kan deur verskeie metodes verkry word. Hieronder is gedetaileerde 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 via die opdraglyn afgelaai word. Dit behels die gebruik van curl
om die ZIP-lêer van 'n spesifieke URL te kry en daarna die inhoud daarvan na 'n gids te onttrek. Hier is die stappe:
- Vervang
"extension_id"
met die werklike ID van die extension. - 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
Gebruik die CRX Viewer extension
Nog 'n handige 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 source code van die viewer is beskikbaar in sy GitHub repository.
Bekyk die bron van lokaal geïnstalleerde extension
Chrome extensions wat lokaal geïnstalleer is, kan ook ondersoek word. So doen jy dit:
- Gaan na jou Chrome lokale profielgids deur
chrome://version/
te besoek en die "Profile Path" veld te soek. - Gaan na die
Extensions/
subgids binne die profielgids. - Hierdie vouer bevat alle geïnstalleerde extensions, tipies met hul source code in 'n leesbare formaat.
Om extensions te identifiseer, kan jy hul IDs aan name koppel:
- Skakel Developer Mode aan op die
about:extensions
blad om die IDs van elke extension te sien. - Binne elke extension se gids bevat die
manifest.json
lêer 'n leesbarename
veld wat help om die extension te identifiseer.
Gebruik 'n File Archiver of Unpacker
Gaan na die Chrome Web Store en laai die extension af. Die lêer sal 'n .crx
uitbreiding hê. Verander die lêeruitbreiding van .crx
na .zip
. Gebruik enige file archiver (soos WinRAR, 7-Zip, ens.) om die inhoud van die ZIP-lêer uit te pak.
Gebruik Developer Mode in Chrome
Maak Chrome oop en gaan na chrome://extensions/
. Skakel "Developer mode" bo-aan regs aan. Klik op "Load unpacked extension...". Navigeer na die gids van jou extension. Dit laai nie die source code af nie, maar dit is nuttig om die kode van 'n reeds afgelaaide of ontwikkelde extension te sien en te wysig.
Chrome extension manifest dataset
Om kwesbare browser extensions te probeer opspoor, kan jy die https://github.com/palant/chrome-extension-manifests-dataset gebruik en hul manifest-lêers vir moontlike kwetsbare tekens nagaan. Byvoorbeeld, om te kyk vir extensions met meer as 25000 gebruikers, content_scripts
en die 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.
{{#ref}} forced-extension-load-preferences-mac-forgery-windows.md {{#endref}}
Sekuriteitsoudit Kontrolelys
Alhoewel Browser Extensions 'n beperkte aanvalsoorvlak het, kan sommige van hulle s kwesbaarhede of potensiële verhardingsverbeterings bevat. Die volgende is die mees algemene:
- Beperk so veel as moontlik die aangevraagde
permissions
- Beperk so veel as moontlik
host_permissions
- Gebruik 'n sterk
content_security_policy
- Beperk so veel as moontlik die
externally_connectable
; as geen nodig is en moontlik, laat dit nie verstek staan nie — spesifiseer{}
- As 'n URL wat vatbaar is vir XSS of vir takeover hier genoem word, sal 'n aanvaller in staat wees om boodskappe direk na die background scripts te stuur. Baie kragtige omseiling.
- Beperk so veel as moontlik die
web_accessible_resources
, selfs leë as moontlik. - As
web_accessible_resources
nie leeg is nie, kyk vir ClickJacking - As enige kommunikasie van die extension na die webblad plaasvind, kontroleer vir XSS kwesbaarhede wat in die kommunikasie veroorsaak kan word.
- As Post Messages gebruik word, kontroleer vir Post Message vulnerabilities.
- As die Content Script toegang tot DOM-besonderhede het, kyk dat dit nie 'n XSS inbring as dit deur die web gewysig word nie
- Maak 'n spesiale klem as hierdie kommunikasie ook betrokke is by die Content Script -> Background script communication
- As die background script kommunikeer via native messaging, vergewis jouself dat die kommunikasie veilig en gesanitiseer is
- Gevoelige inligting moet nie gestoor word binne die Browser Extension kode nie
- Gevoelige inligting moet nie gestoor word binne die Browser Extension geheue nie
- Gevoelige inligting moet nie onbeskermd gestoor word op die lêerstelsel nie
Risiko's van Browser Extensions
- Die app https://crxaminer.tech/ analiseer sekere data soos die permissies wat 'n browser extension versoek om 'n risikovlak vir die gebruik van die extension te gee.
Gereedskap
Tarnish
- Trek enige Chrome extension vanaf 'n gegewe Chrome webstore skakel.
- manifest.json kijker: vertoon eenvoudig 'n JSON-pragvrye 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 direktef fest. Hierdie kan potensieel kwesbaar wees vir clickjacking afhangende 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 plek 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 aanvaar. Dit is nuttig om die oppervlakte van 'n extension te verstaan en potensiële punte te soek om kwaadwillig-opgemaakte data na die extension te stuur.
- Beide die Dangerous Function(s) en Entry Point(s) skanners lewer die volgende vir hul gegenereerde waarskuwings:
- Relevante kodefragment en lyn wat die waarskuwing veroorsaak het.
- Beskrywing van die kwessie.
- 'n “View File” knoppie om die volle bronlêer wat die kode bevat te sien.
- Die pad van die gewaarsku lde lêer.
- Die volle Chrome extension URI van die gewaarsku lde lêer.
- Die tipe lêer wat dit is, 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 word sowel as die tipe van daardie bladsye, en web_accessible_resource status.
- Content Security Policy (CSP) analyzer and bypass checker: Sal swakhede in jou extension se CSP uitwys en ook enige potensiële maniere om jou CSP te omseil verklaar weens witgeplakte CDNs, ens.
- Known Vulnerable Libraries: Gebruik Retire.js om te kyk vir enige gebruik van bekende-kwesbare JavaScript-biblioteke.
- Laai extension en geformateerde weergawes af.
- Laai die oorspronklike extension af.
- Laai 'n verfraaide weergawe van die extension af (outomaties gepretified HTML en JavaScript).
- Outomatiese kas van skanresultate; die eerste keer wat 'n extension geskan word sal dit 'n geruime tyd neem. Die tweede keer, mits die extension nie opgedateer is nie, sal dit byna onmiddellik wees as gevolg van kasresultate.
- Deelbare verslag-URL's, maklik om iemand anders na 'n Extension verslag wat deur tarnish gegenereer is te skakel.
Neto
Project Neto is 'n Python 3 pakket wat ontwerp is om verborge funksies van browser plugins en extensions vir bekende blaaiers soos Firefox en Chrome te ontleed en te ontrafel. Dit outomatiseer die proses om gepakte lêers uit te pak om hierdie funksies uit relevante bronne in 'n extension soos manifest.json
, lokalisasie-gidse of JavaScript- en HTML-bronkode-lêers te onttrek.
Verwante bronne
- Dank aan @naivenom vir die hulp met hierdie metodologie
- 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
{{#include ../../banners/hacktricks-training.md}}