Browser Extension Pentesting Methodology
Basic Information
Ekstenzije pretraživača su napisane u JavaScript-u i učitavaju se u pozadini od strane pretraživača. Ima svoj DOM ali može da interaguje sa DOM-ovima drugih sajtova. To znači da može ugroziti poverljivost, integritet i dostupnost (CIA) drugih sajtova.
Main Components
Izgledi ekstenzije izgledaju najbolje kada su vizualizovani i sastoje se od tri komponente. Pogledajmo svaku komponentu detaljno.
Content Scripts
Svaki sadržajni skript ima direktan pristup DOM-u jedne web stranice i stoga je izložen potencijalno zloćudnom unosu. Međutim, sadržajni skript ne sadrži dozvole osim sposobnosti slanja poruka jezgru ekstenzije.
Extension Core
Jezgro ekstenzije sadrži većinu privilegija/pristupa ekstenzije, ali jezgro ekstenzije može da interaguje sa web sadržajem samo putem XMLHttpRequest i sadržajnih skripti. Takođe, jezgro ekstenzije nema direktan pristup host mašini.
Native Binary
Ekstenzija omogućava nativni binarni fajl koji može pristupiti host mašini sa punim privilegijama korisnika. Nativni binarni fajl interaguje sa jezgrom ekstenzije putem standardnog Netscape Plugin Application Programming Interface (NPAPI) koji koriste Flash i drugi browser plug-in-ovi.
Boundaries
Da bi dobio pune privilegije korisnika, napadač mora ubediti ekstenziju da prenese zloćudni unos iz sadržajnog skripta u jezgro ekstenzije i iz jezgra ekstenzije u nativni binarni fajl.
Svaka komponenta ekstenzije je odvojena jedna od druge jakim zaštitnim granicama. Svaka komponenta se izvršava u odvojenom procesu operativnog sistema. Sadržajni skripti i jezgra ekstenzije se izvršavaju u sandbox procesima koji nisu dostupni većini usluga operativnog sistema.
Štaviše, sadržajni skripti su odvojeni od svojih povezanih web stranica izvršavanjem u odvojenom JavaScript heap-u. Sadržajni skript i web stranica imaju pristup istom osnovnom DOM-u, ali se njih dvoje nikada ne razmenjuju JavaScript pokazivače, sprečavajući curenje JavaScript funkcionalnosti.
manifest.json
manifest.json
Chrome ekstenzija je samo ZIP folder sa .crx ekstenzijom fajla. Jezgro ekstenzije je manifest.json
fajl u korenu foldera, koji specificira raspored, dozvole i druge opcije konfiguracije.
Example:
content_scripts
content_scripts
Skripte sadržaja se učitavaju svaki put kada korisnik navigira na odgovarajuću stranicu, u našem slučaju bilo koja stranica koja odgovara https://example.com/*
izrazu i ne odgovara *://*/*/business*
regex-u. Izvršavaju se poput skripti same stranice i imaju proizvoljan pristup Modelu objekta dokumenta (DOM) stranice.
Da bi se uključilo ili isključilo više URL-ova, takođe je moguće koristiti include_globs
i exclude_globs
.
Ovo je primer sadržajnog skripta koji će dodati dugme za objašnjenje na stranicu kada API za skladištenje preuzme message
vrednost iz skladišta ekstenzije.
Poruka se šalje na stranice ekstenzije putem sadržajnog skripta kada se pritisne ovaj dugme, korišćenjem runtime.sendMessage() API. To je zbog ograničenja sadržajnog skripta u direktnom pristupu API-ima, pri čemu je storage
jedan od retkih izuzetaka. Za funkcionalnosti izvan ovih izuzetaka, poruke se šalju na stranice ekstenzije sa kojima sadržajni skripti mogu komunicirati.
U zavisnosti od pregledača, mogućnosti sadržajnog skripta mogu se malo razlikovati. Za pregledače zasnovane na Chromium-u, lista mogućnosti je dostupna u Chrome Developers dokumentaciji, a za Firefox, MDN služi kao primarni izvor. Takođe je važno napomenuti da sadržajni skripti imaju sposobnost da komuniciraju sa pozadinskim skriptima, omogućavajući im da izvršavaju radnje i prenose odgovore nazad.
Za pregledanje i debagovanje sadržajnih skripti u Chrome-u, meni alata za programere može se pristupiti iz Opcije > Više alata > Alati za programere ili pritiskom na Ctrl + Shift + I.
Kada se prikažu alati za programere, treba kliknuti na Source tab, a zatim na Content Scripts tab. Ovo omogućava posmatranje aktivnih sadržajnih skripti iz različitih ekstenzija i postavljanje tačaka prekida za praćenje toka izvršenja.
Umetnuti sadržajni skripti
Napomena: Sadržajni skripti nisu obavezni jer je takođe moguće dinamički umetati skripte i programatski ih umetati na web stranice putem tabs.executeScript
. Ovo zapravo pruža više granularnih kontrola.
Za programatsko umetanje sadržajnog skripta, ekstenzija mora imati host permissions za stranicu u koju se skripte umetaju. Ove dozvole mogu se obezbediti ili zahtevom unutar manifest fajla ekstenzije ili privremeno putem activeTab.
Primer ekstenzije zasnovane na activeTab
Ubacite JS datoteku na klik:
Umetnite funkciju na klik:
Primer sa dozvolama za skripting
Da bi se uključilo ili isključilo više URL-ova, takođe je moguće koristiti include_globs
i exclude_globs
.
Content Scripts run_at
run_at
Polje run_at
kontroliše kada se JavaScript datoteke ubacuju u web stranicu. Preferirana i podrazumevana vrednost je "document_idle"
.
Moguće vrednosti su:
document_idle
: Kada god je to mogućedocument_start
: Nakon bilo kojih datoteka izcss
, ali pre nego što se konstruira bilo koji drugi DOM ili se pokrene bilo koji drugi skript.document_end
: Odmah nakon što je DOM završen, ali pre nego što se učitaju podresursi poput slika i okvira.
Via manifest.json
manifest.json
Putem service-worker.js
background
background
Poruke koje šalju sadržajni skripti primaju se na pozadinskoj stranici, koja ima centralnu ulogu u koordinaciji komponenti ekstenzije. Važno je napomenuti da pozadinska stranica opstaje tokom celog trajanja ekstenzije, delujući diskretno bez direktne interakcije korisnika. Ima svoj vlastiti Model objekta dokumenta (DOM), što omogućava složene interakcije i upravljanje stanjem.
Ključne tačke:
Uloga pozadinske stranice: Deluje kao nervni centar za ekstenziju, obezbeđujući komunikaciju i koordinaciju među različitim delovima ekstenzije.
Postojanost: To je uvek prisutna entitet, nevidljiva korisniku, ali integralna za funkcionalnost ekstenzije.
Automatska generacija: Ako nije eksplicitno definisana, pretraživač će automatski kreirati pozadinsku stranicu. Ova automatski generisana stranica će uključivati sve pozadinske skripte navedene u manifestu ekstenzije, obezbeđujući nesmetano funkcionisanje pozadinskih zadataka ekstenzije.
Pogodnost koju pretraživač pruža automatskim generisanjem pozadinske stranice (kada nije eksplicitno deklarisana) osigurava da su sve potrebne pozadinske skripte integrisane i operativne, pojednostavljujući proces postavljanja ekstenzije.
Primer pozadinske skripte:
Koristi runtime.onMessage API za slušanje poruka. Kada se primi poruka "explain"
, koristi tabs API da otvori stranicu u novoj kartici.
Da biste debagovali pozadinski skript, možete otići na detalje ekstenzije i inspektovati servisnog radnika, što će otvoriti alate za programere sa pozadinskim skriptom:
Opcione stranice i druge
Ekstenzije pretraživača mogu sadržati razne vrste stranica:
Akcione stranice se prikazuju u ispod kada se klikne na ikonu ekstenzije.
Stranice koje će ekstenzija učitati u novoj kartici.
Opcione stranice: Ova stranica se prikazuje na vrhu ekstenzije kada se klikne. U prethodnom manifestu, u mom slučaju, mogao sam da pristupim ovoj stranici u
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
ili klikom:
Napomena da ove stranice nisu trajne kao pozadinske stranice jer dinamički učitavaju sadržaj po potrebi. I pored toga, dele određene mogućnosti sa pozadinskom stranicom:
Komunikacija sa sadržajnim skriptama: Slično pozadinskoj stranici, ove stranice mogu primati poruke od sadržajnih skripti, olakšavajući interakciju unutar ekstenzije.
Pristup API-jevima specifičnim za ekstenziju: Ove stranice uživaju sveobuhvatan pristup API-jevima specifičnim za ekstenziju, podložnim dozvolama definisanim za ekstenziju.
permissions
& host_permissions
permissions
& host_permissions
permissions
i host_permissions
su unosi iz manifest.json
koji će označiti koje dozvole ekstenzija pretraživača ima (skladištenje, lokacija...) i u koje web stranice.
Kako ekstenzije pretraživača mogu biti tako privilegovane, zlonamerna ili kompromitovana ekstenzija mogla bi omogućiti napadaču različite načine da ukrade osetljive informacije i špijunira korisnika.
Proverite kako ove postavke funkcionišu i kako bi mogle biti zloupotrebljene u:
BrowExt - permissions & host_permissionscontent_security_policy
content_security_policy
Politika bezbednosti sadržaja može biti deklarisana i unutar manifest.json
. Ako je jedna definisana, mogla bi biti ranjiva.
Podrazumevana postavka za stranice ekstenzije pretraživača je prilično restriktivna:
Za više informacija o CSP-u i potencijalnim zaobilaženjima, proverite:
Content Security Policy (CSP) Bypassweb_accessible_resources
web_accessible_resources
Da bi veb stranica imala pristup stranici ekstenzije pregledača, na primer, .html
stranici, ova stranica mora biti pomenuta u web_accessible_resources
polju manifest.json
.
Na primer:
Ove stranice su dostupne na URL-u kao:
U javnim ekstenzijama extension-id je dostupan:
Međutim, ako se koristi parametar manifest.json
use_dynamic_url
, ovaj id može biti dinamičan.
Imajte na umu da čak i ako je stranica ovde pomenuta, može biti zaštićena od ClickJacking zahvaljujući Content Security Policy. Takođe treba da proverite (odeljak frame-ancestors) pre nego što potvrdite da je ClickJacking napad moguć.
Mogućnost pristupa ovim stranicama čini ih potencijalno ranjivim na ClickJacking:
BrowExt - ClickJackingDozvoljavanje da se ove stranice učitavaju samo putem ekstenzije, a ne putem nasumičnih URL-ova, moglo bi sprečiti ClickJacking napade.
Imajte na umu da stranice iz web_accessible_resources
i druge stranice ekstenzije takođe mogu kontaktirati pozadinske skripte. Dakle, ako je jedna od ovih stranica ranjiva na XSS, to bi moglo otvoriti veću ranjivost.
Pored toga, imajte na umu da možete otvoriti samo stranice navedene u web_accessible_resources
unutar iframe-ova, ali iz nove kartice je moguće pristupiti bilo kojoj stranici u ekstenziji poznavajući ID ekstenzije. Stoga, ako se pronađe XSS koji zloupotrebljava iste parametre, može se zloupotrebiti čak i ako stranica nije konfigurisana u web_accessible_resources
.
externally_connectable
externally_connectable
Prema docs, manifest svojstvo "externally_connectable"
deklarira koje ekstenzije i web stranice mogu da se povežu sa vašom ekstenzijom putem runtime.connect i runtime.sendMessage.
Ako ključ
externally_connectable
nije deklarisan u manifestu vaše ekstenzije ili je deklarisan kao"ids": ["*"]
, sve ekstenzije mogu da se povežu, ali nijedna web stranica ne može da se poveže.Ako su specifični ID-ovi navedeni, kao u
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, samo te aplikacije mogu da se povežu.Ako su match-ovi navedeni, te web aplikacije će moći da se povežu:
Ako je navedeno kao prazno:
"externally_connectable": {}
, nijedna aplikacija ili veb neće moći da se poveže.
Što je manje ekstenzija i URL-ova ovde navedeno, to će biti manja površina napada.
Ako je veb stranica ranjiva na XSS ili preuzimanje navedena u externally_connectable
, napadač će moći da pošalje poruke direktno u pozadinski skript, potpuno zaobilazeći Content Script i njegov CSP.
Stoga, ovo je veoma moćan zaobilazni način.
Štaviše, ako klijent instalira lažnu ekstenziju, čak i ako nije dozvoljeno da komunicira sa ranjivom ekstenzijom, mogla bi da ubrizga XSS podatke u dozvoljenu veb stranicu ili zloupotrebi WebRequest
ili DeclarativeNetRequest
API-je da manipuliše zahtevima na ciljanom domenu menjajući zahtev stranice za JavaScript datoteku. (Imajte na umu da CSP na ciljnoj stranici može sprečiti ove napade). Ova ideja dolazi iz ovog izveštaja.
Sažetak komunikacije
Ekstenzija <--> WebApp
Za komunikaciju između sadržajnog skripta i veb stranice obično se koriste post poruke. Stoga, u veb aplikaciji obično ćete pronaći pozive funkciji window.postMessage
i u sadržajnom skriptu slušaoce poput window.addEventListener
. Imajte na umu, međutim, da ekstenzija takođe može komunicirati sa veb aplikacijom slanjem Post Poruke (i stoga bi veb trebao to očekivati) ili jednostavno učiniti da veb učita novi skript.
Unutar ekstenzije
Obično se funkcija chrome.runtime.sendMessage
koristi za slanje poruke unutar ekstenzije (obično obrađuje background
skript) i da bi je primila i obradila, deklarisan je slušalac koji poziva chrome.runtime.onMessage.addListener
.
Takođe je moguće koristiti chrome.runtime.connect()
da se uspostavi postojana veza umesto slanja pojedinačnih poruka, moguće je koristiti je za slanje i prijem poruka kao u sledećem primeru:
Last updated