Browser Extension Pentesting Methodology
Informazioni di base
Le estensioni del browser sono scritte in JavaScript e caricate dal browser in background. Hanno il loro DOM ma possono interagire con i DOM di altri siti. Ciò significa che possono compromettere la riservatezza, l'integrità e la disponibilità (CIA) di altri siti.
Componenti principali
I layout delle estensioni appaiono meglio quando visualizzati e consistono in tre componenti. Esaminiamo ciascun componente in dettaglio.
Script di contenuto
Ogni script di contenuto ha accesso diretto al DOM di una singola pagina web ed è quindi esposto a input potenzialmente dannosi. Tuttavia, lo script di contenuto non contiene permessi se non la possibilità di inviare messaggi al core dell'estensione.
Core dell'estensione
Il core dell'estensione contiene la maggior parte dei privilegi/accessi dell'estensione, ma il core dell'estensione può interagire con i contenuti web solo tramite XMLHttpRequest e script di contenuto. Inoltre, il core dell'estensione non ha accesso diretto alla macchina host.
Binary nativo
L'estensione consente un binary nativo che può accedere alla macchina host con i privilegi completi dell'utente. Il binary nativo interagisce con il core dell'estensione tramite l'interfaccia di programmazione delle applicazioni standard Netscape Plugin (NPAPI) utilizzata da Flash e altri plug-in del browser.
Confini
Per ottenere i privilegi completi dell'utente, un attaccante deve convincere l'estensione a passare input dannosi dallo script di contenuto al core dell'estensione e dal core dell'estensione al binary nativo.
Ogni componente dell'estensione è separato dagli altri da forti confini protettivi. Ogni componente viene eseguito in un processo di sistema operativo separato. Gli script di contenuto e i core delle estensioni vengono eseguiti in processi sandbox non disponibili per la maggior parte dei servizi del sistema operativo.
Inoltre, gli script di contenuto sono separati dalle loro pagine web associate eseguendo in un heap JavaScript separato. Lo script di contenuto e la pagina web hanno accesso allo stesso DOM sottostante, ma i due non scambiano mai puntatori JavaScript, prevenendo la fuoriuscita di funzionalità JavaScript.
manifest.json
manifest.json
Un'estensione di Chrome è semplicemente una cartella ZIP con un'estensione di file .crx. Il core dell'estensione è il file manifest.json
nella radice della cartella, che specifica layout, permessi e altre opzioni di configurazione.
Esempio:
content_scripts
content_scripts
I contenuti degli script vengono caricati ogni volta che l'utente naviga a una pagina corrispondente, nel nostro caso qualsiasi pagina che corrisponde all'espressione https://example.com/*
e non corrisponde all'espressione regolare *://*/*/business*
. Eseguono come gli script della pagina e hanno accesso arbitrario al Document Object Model (DOM) della pagina.
Per includere o escludere più URL, è anche possibile utilizzare include_globs
e exclude_globs
.
Questo è un esempio di script di contenuto che aggiungerà un pulsante di spiegazione alla pagina quando l'API di archiviazione per recuperare il valore message
dallo storage dell'estensione.
Un messaggio viene inviato alle pagine dell'estensione dallo script di contenuto quando questo pulsante viene cliccato, attraverso l'utilizzo dell'API runtime.sendMessage(). Questo è dovuto alla limitazione dello script di contenuto nell'accesso diretto alle API, con storage
che è tra le poche eccezioni. Per funzionalità oltre queste eccezioni, i messaggi vengono inviati alle pagine dell'estensione con cui gli script di contenuto possono comunicare.
A seconda del browser, le capacità dello script di contenuto possono variare leggermente. Per i browser basati su Chromium, l'elenco delle capacità è disponibile nella documentazione degli sviluppatori di Chrome, e per Firefox, il MDN funge da fonte principale. È anche degno di nota che gli script di contenuto hanno la capacità di comunicare con gli script di background, consentendo loro di eseguire azioni e trasmettere risposte.
Per visualizzare e fare debug degli script di contenuto in Chrome, il menu degli strumenti per sviluppatori di Chrome può essere accesso da Opzioni > Altri strumenti > Strumenti per sviluppatori OPPURE premendo Ctrl + Shift + I.
Una volta visualizzati gli strumenti per sviluppatori, è necessario cliccare sulla scheda Sorgente, seguita dalla scheda Script di contenuto. Questo consente di osservare gli script di contenuto in esecuzione da varie estensioni e di impostare punti di interruzione per tracciare il flusso di esecuzione.
Script di contenuto iniettati
Nota che gli script di contenuto non sono obbligatori poiché è anche possibile iniettare dinamicamente script e iniettarli programmaticamente nelle pagine web tramite tabs.executeScript
. Questo fornisce effettivamente più controlli granulari.
Per l'iniezione programmatica di uno script di contenuto, l'estensione deve avere permessi di host per la pagina in cui gli script devono essere iniettati. Questi permessi possono essere ottenuti sia richiedendoli all'interno del manifesto dell'estensione sia su base temporanea tramite activeTab.
Esempio di estensione basata su activeTab
Inietta un file JS al clic:
Inietta una funzione al clic:
Esempio con permessi di scripting
In order to include or exclude more URLs it's also possible to use include_globs
and exclude_globs
.
Content Scripts run_at
run_at
Il campo run_at
controlla quando i file JavaScript vengono iniettati nella pagina web. Il valore preferito e predefinito è "document_idle"
.
I valori possibili sono:
document_idle
: Ogni volta che è possibiledocument_start
: Dopo qualsiasi file dacss
, ma prima che venga costruito qualsiasi altro DOM o che venga eseguito qualsiasi altro script.document_end
: Immediatamente dopo che il DOM è completo, ma prima che le sottorisorse come immagini e frame siano state caricate.
Via manifest.json
manifest.json
Via service-worker.js
background
background
I messaggi inviati dagli script di contenuto vengono ricevuti dalla pagina di background, che svolge un ruolo centrale nel coordinare i componenti dell'estensione. In particolare, la pagina di background persiste per tutta la durata dell'estensione, operando discretamente senza interazione diretta dell'utente. Possiede il proprio Document Object Model (DOM), consentendo interazioni complesse e gestione dello stato.
Punti Chiave:
Ruolo della Pagina di Background: Funziona come il centro nevralgico per l'estensione, garantendo comunicazione e coordinamento tra le varie parti dell'estensione.
Persistenza: È un'entità sempre presente, invisibile all'utente ma fondamentale per la funzionalità dell'estensione.
Generazione Automatica: Se non definita esplicitamente, il browser creerà automaticamente una pagina di background. Questa pagina generata automaticamente includerà tutti gli script di background specificati nel manifesto dell'estensione, garantendo il funzionamento senza soluzione di continuità dei compiti di background dell'estensione.
La comodità fornita dal browser nella generazione automatica di una pagina di background (quando non dichiarata esplicitamente) garantisce che tutti gli script di background necessari siano integrati e operativi, semplificando il processo di configurazione dell'estensione.
Esempio di script di background:
Utilizza l'API runtime.onMessage per ascoltare i messaggi. Quando viene ricevuto un messaggio "explain"
, utilizza l'API tabs per aprire una pagina in una nuova scheda.
Per eseguire il debug dello script di background, puoi andare ai dettagli dell'estensione e ispezionare il service worker, questo aprirà gli strumenti per sviluppatori con lo script di background:
Pagine delle opzioni e altro
Le estensioni del browser possono contenere vari tipi di pagine:
Le pagine di azione vengono visualizzate in un menu a discesa quando si fa clic sull'icona dell'estensione.
Pagine che l'estensione caricherà in una nuova scheda.
Pagine delle opzioni: Questa pagina viene visualizzata sopra l'estensione quando viene cliccata. Nel precedente manifest, nel mio caso, sono riuscito ad accedere a questa pagina in
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
o cliccando:
Nota che queste pagine non sono persistenti come le pagine di background poiché caricano contenuti dinamicamente secondo necessità. Nonostante ciò, condividono alcune capacità con la pagina di background:
Comunicazione con gli script di contenuto: Simile alla pagina di background, queste pagine possono ricevere messaggi dagli script di contenuto, facilitando l'interazione all'interno dell'estensione.
Accesso alle API specifiche dell'estensione: Queste pagine godono di un accesso completo alle API specifiche dell'estensione, soggetto alle autorizzazioni definite per l'estensione.
permissions
& host_permissions
permissions
& host_permissions
permissions
e host_permissions
sono voci del manifest.json
che indicheranno quali autorizzazioni ha l'estensione del browser (memoria, posizione...) e in quali pagine web.
Poiché le estensioni del browser possono essere così privilegiate, una malevola o una compromessa potrebbe consentire all'attaccante diversi mezzi per rubare informazioni sensibili e spiare l'utente.
Controlla come funzionano queste impostazioni e come potrebbero essere abusate in:
BrowExt - permissions & host_permissionscontent_security_policy
content_security_policy
Una politica di sicurezza dei contenuti può essere dichiarata anche all'interno del manifest.json
. Se ce n'è una definita, potrebbe essere vulnerabile.
L'impostazione predefinita per le pagine delle estensioni del browser è piuttosto restrittiva:
Per ulteriori informazioni su CSP e potenziali bypass, controlla:
Content Security Policy (CSP) Bypassweb_accessible_resources
web_accessible_resources
affinché una pagina web possa accedere a una pagina di un'estensione del browser, ad esempio una pagina .html
, questa pagina deve essere menzionata nel campo web_accessible_resources
del manifest.json
.
Ad esempio:
Queste pagine sono accessibili all'URL come:
In public extensions the extension-id è accessibile:
Tuttavia, se il parametro manifest.json
use_dynamic_url
è utilizzato, questo id può essere dinamico.
Nota che anche se una pagina è menzionata qui, potrebbe essere protetta contro il ClickJacking grazie alla Content Security Policy. Quindi devi anche controllarlo (sezione frame-ancestors) prima di confermare che un attacco di ClickJacking sia possibile.
Essere autorizzati ad accedere a queste pagine rende queste pagine potenzialmente vulnerabili al ClickJacking:
BrowExt - ClickJackingConsentire a queste pagine di essere caricate solo dall'estensione e non da URL casuali potrebbe prevenire attacchi di ClickJacking.
Nota che le pagine da web_accessible_resources
e altre pagine dell'estensione sono anche in grado di contattare script di background. Quindi, se una di queste pagine è vulnerabile a XSS, potrebbe aprire una vulnerabilità più grande.
Inoltre, nota che puoi aprire solo le pagine indicate in web_accessible_resources
all'interno di iframe, ma da una nuova scheda è possibile accedere a qualsiasi pagina nell'estensione conoscendo l'ID dell'estensione. Pertanto, se viene trovata una XSS abusando degli stessi parametri, potrebbe essere abusata anche se la pagina non è configurata in web_accessible_resources
.
externally_connectable
externally_connectable
Come indicato nella documentazione, La proprietà di manifest "externally_connectable"
dichiara quali estensioni e pagine web possono connettersi alla tua estensione tramite runtime.connect e runtime.sendMessage.
Se la chiave
externally_connectable
non è dichiarata nel manifest della tua estensione o è dichiarata come"ids": ["*"]
, tutte le estensioni possono connettersi, ma nessuna pagina web può connettersi.Se ID specifici sono specificati, come in
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, solo quelle applicazioni possono connettersi.Se sono specificati matches, quelle web app saranno in grado di connettersi:
Se è specificato come vuoto:
"externally_connectable": {}
, nessuna app o web sarà in grado di connettersi.
Meno estensioni e URL indicati qui, più piccola sarà la superficie di attacco.
Se una pagina web vulnerabile a XSS o takeover è indicata in externally_connectable
, un attaccante sarà in grado di inviare messaggi direttamente allo script di background, bypassando completamente il Content Script e il suo CSP.
Pertanto, questo è un bypass molto potente.
Inoltre, se il client installa un'estensione malevola, anche se non è autorizzata a comunicare con l'estensione vulnerabile, potrebbe iniettare dati XSS in una pagina web consentita o abusare delle API WebRequest
o DeclarativeNetRequest
per manipolare le richieste su un dominio mirato alterando la richiesta di una file JavaScript. (Nota che il CSP sulla pagina mirata potrebbe prevenire questi attacchi). Questa idea proviene da questo writeup.
Riepilogo della comunicazione
Estensione <--> WebApp
Per comunicare tra lo script di contenuto e la pagina web, di solito si utilizzano messaggi post. Pertanto, nell'applicazione web troverai di solito chiamate alla funzione window.postMessage
e nello script di contenuto listener come window.addEventListener
. Nota però che l'estensione potrebbe anche comunicare con l'applicazione web inviando un Post Message (e quindi il web dovrebbe aspettarselo) o semplicemente far caricare al web un nuovo script.
All'interno dell'estensione
Di solito la funzione chrome.runtime.sendMessage
è utilizzata per inviare un messaggio all'interno dell'estensione (di solito gestito dallo script background
) e per riceverlo e gestirlo viene dichiarato un listener chiamando chrome.runtime.onMessage.addListener
.
È anche possibile utilizzare chrome.runtime.connect()
per avere una connessione persistente invece di inviare messaggi singoli, è possibile utilizzarlo per inviare e ricevere messaggi come nel seguente esempio:
Last updated