Browser Extension Pentesting Methodology
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Podstawowe Informacje
Rozszerzenia przeglądarki są napisane w JavaScript i ładowane przez przeglądarkę w tle. Mają swój DOM, ale mogą wchodzić w interakcje z DOM-ami innych stron. Oznacza to, że mogą naruszać poufność, integralność i dostępność (CIA) innych stron.
Główne Komponenty
Układy rozszerzeń wyglądają najlepiej, gdy są wizualizowane i składają się z trzech komponentów. Przyjrzyjmy się każdemu komponentowi dokładniej.
Skrypty Treści
Każdy skrypt treści ma bezpośredni dostęp do DOM jednej strony internetowej i jest tym samym narażony na potencjalnie złośliwe dane wejściowe. Jednak skrypt treści nie zawiera żadnych uprawnień poza możliwością wysyłania wiadomości do rdzenia rozszerzenia.
Rdzeń Rozszerzenia
Rdzeń rozszerzenia zawiera większość uprawnień/dostępu rozszerzenia, ale rdzeń rozszerzenia może wchodzić w interakcje z treścią internetową tylko za pośrednictwem XMLHttpRequest i skryptów treści. Ponadto rdzeń rozszerzenia nie ma bezpośredniego dostępu do maszyny gospodarza.
Natychmiastowy Plik Binarny
Rozszerzenie pozwala na natychmiastowy plik binarny, który może uzyskać dostęp do maszyny gospodarza z pełnymi uprawnieniami użytkownika. Natychmiastowy plik binarny wchodzi w interakcje z rdzeniem rozszerzenia za pośrednictwem standardowego interfejsu programowania aplikacji Netscape Plugin (NPAPI), używanego przez Flash i inne wtyczki przeglądarki.
Granice
Aby uzyskać pełne uprawnienia użytkownika, atakujący musi przekonać rozszerzenie do przekazania złośliwych danych wejściowych ze skryptu treści do rdzenia rozszerzenia, a następnie z rdzenia rozszerzenia do natychmiastowego pliku binarnego.
Każdy komponent rozszerzenia jest oddzielony od siebie przez silne granice ochronne. Każdy komponent działa w osobnym procesie systemu operacyjnego. Skrypty treści i rdzenie rozszerzeń działają w procesach piaskownicy, niedostępnych dla większości usług systemu operacyjnego.
Co więcej, skrypty treści są oddzielone od swoich powiązanych stron internetowych przez działanie w osobnym stosie JavaScript. Skrypt treści i strona internetowa mają dostęp do tego samego podstawowego DOM, ale obie nigdy nie wymieniają wskaźników JavaScript, co zapobiega wyciekowi funkcjonalności JavaScript.
manifest.json
manifest.json
Rozszerzenie Chrome to po prostu folder ZIP z rozszerzeniem .crx. Rdzeń rozszerzenia to plik manifest.json
w katalogu głównym folderu, który określa układ, uprawnienia i inne opcje konfiguracyjne.
Przykład:
content_scripts
content_scripts
Skrypty zawartości są ładowane za każdym razem, gdy użytkownik nawiguje do pasującej strony, w naszym przypadku każda strona pasująca do wyrażenia https://example.com/*
i niepasująca do wyrażenia regex *://*/*/business*
. Wykonują się jak własne skrypty strony i mają dowolny dostęp do Modelu Obiektu Dokumentu (DOM) strony.
Aby dodać lub wykluczyć więcej adresów URL, można również użyć include_globs
i exclude_globs
.
To jest przykład skryptu zawartości, który doda przycisk wyjaśnienia do strony, gdy API storage zostanie użyte do pobrania wartości message
z pamięci rozszerzenia.
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F600722126-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FJtticLwENZ4i7WwgHiQe%252Fuploads%252Fgit-blob-f963370a18f80faa11a2ae0ddac24ce6e6393190%252Fimage%2520%2823%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=e1dcbe83&sv=1)
Wiadomość jest wysyłana do stron rozszerzenia przez skrypt treści, gdy ten przycisk jest klikany, poprzez wykorzystanie runtime.sendMessage() API. Wynika to z ograniczenia skryptu treści w bezpośrednim dostępie do API, przy czym storage
jest jednym z nielicznych wyjątków. Dla funkcjonalności wykraczających poza te wyjątki, wiadomości są wysyłane do stron rozszerzenia, z którymi skrypty treści mogą komunikować się.
W zależności od przeglądarki, możliwości skryptu treści mogą się nieco różnić. Dla przeglądarek opartych na Chromium, lista możliwości jest dostępna w dokumentacji Chrome Developers, a dla Firefox, MDN służy jako główne źródło. Warto również zauważyć, że skrypty treści mają możliwość komunikacji z skryptami w tle, co umożliwia im wykonywanie działań i przekazywanie odpowiedzi z powrotem.
Aby wyświetlić i debugować skrypty treści w Chrome, menu narzędzi dewelopera można otworzyć z Opcje > Więcej narzędzi > Narzędzia dewelopera LUB naciskając Ctrl + Shift + I.
Po wyświetleniu narzędzi dewelopera, należy kliknąć na zakładkę Źródło, a następnie na zakładkę Skrypty treści. Umożliwia to obserwację działających skryptów treści z różnych rozszerzeń oraz ustawienie punktów przerwania w celu śledzenia przepływu wykonania.
Wstrzyknięte skrypty treści
Zauważ, że Skrypty Treści nie są obowiązkowe, ponieważ możliwe jest również dynamiczne wstrzykiwanie skryptów oraz programowe wstrzykiwanie ich na stronach internetowych za pomocą tabs.executeScript
. To w rzeczywistości zapewnia bardziej szczegółową kontrolę.
Aby programowo wstrzyknąć skrypt treści, rozszerzenie musi mieć uprawnienia hosta dla strony, do której skrypty mają być wstrzyknięte. Uprawnienia te mogą być zabezpieczone albo przez zażądanie ich w manifeście rozszerzenia, albo tymczasowo poprzez activeTab.
Przykład rozszerzenia opartego na activeTab
Wstrzyknij plik JS po kliknięciu:
Wstrzyknij funkcję po kliknięciu:
Przykład z uprawnieniami skryptów
Aby dodać lub wykluczyć więcej adresów URL, można również użyć include_globs
i exclude_globs
.
Skrypty zawartości run_at
run_at
Pole run_at
kontroluje kiedy pliki JavaScript są wstrzykiwane do strony internetowej. Preferowana i domyślna wartość to "document_idle"
.
Możliwe wartości to:
document_idle
: Kiedy tylko to możliwedocument_start
: Po załadowaniu jakichkolwiek plików zcss
, ale przed skonstruowaniem jakiegokolwiek innego DOM lub uruchomieniem jakiegokolwiek innego skryptu.document_end
: Natychmiast po zakończeniu DOM, ale przed załadowaniem subzasobów, takich jak obrazy i ramki.
Poprzez manifest.json
manifest.json
Via service-worker.js
background
background
Wiadomości wysyłane przez skrypty treści są odbierane przez stronę tła, która odgrywa centralną rolę w koordynowaniu komponentów rozszerzenia. Co ważne, strona tła utrzymuje się przez cały czas trwania rozszerzenia, działając dyskretnie bez bezpośredniej interakcji użytkownika. Posiada własny Model Obiektów Dokumentu (DOM), co umożliwia złożone interakcje i zarządzanie stanem.
Kluczowe punkty:
Rola Strony Tła: Działa jako centrum nerwowe dla rozszerzenia, zapewniając komunikację i koordynację między różnymi częściami rozszerzenia.
Trwałość: To zawsze obecny byt, niewidoczny dla użytkownika, ale integralny dla funkcjonalności rozszerzenia.
Automatyczne Generowanie: Jeśli nie jest wyraźnie zdefiniowane, przeglądarka automatycznie utworzy stronę tła. Ta automatycznie generowana strona będzie zawierać wszystkie skrypty tła określone w manifeście rozszerzenia, zapewniając płynne działanie zadań tła rozszerzenia.
Wygoda zapewniana przez przeglądarkę w automatycznym generowaniu strony tła (gdy nie jest wyraźnie zadeklarowana) zapewnia, że wszystkie niezbędne skrypty tła są zintegrowane i działają, upraszczając proces konfiguracji rozszerzenia.
Przykład skryptu tła:
Używa runtime.onMessage API do nasłuchiwania wiadomości. Gdy otrzymana zostanie wiadomość "explain"
, używa tabs API do otwarcia strony w nowej karcie.
Aby debugować skrypt w tle, możesz przejść do szczegółów rozszerzenia i sprawdzić serwis worker, co otworzy narzędzia deweloperskie z skryptem w tle:
Strony opcji i inne
Rozszerzenia przeglądarki mogą zawierać różne rodzaje stron:
Strony akcji są wyświetlane w rozwijanym menu po kliknięciu na ikonę rozszerzenia.
Strony, które rozszerzenie załaduje w nowej karcie.
Strony opcji: Ta strona wyświetla się na górze rozszerzenia po kliknięciu. W poprzednim manifeście w moim przypadku mogłem uzyskać dostęp do tej strony w
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
lub klikając:
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F600722126-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FJtticLwENZ4i7WwgHiQe%252Fuploads%252Fgit-blob-9674c12c62b3f1bd2ef1f2bc724900e3e14689c8%252Fimage%2520%2824%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=f3c5dd4d&sv=1)
Zauważ, że te strony nie są trwałe jak strony w tle, ponieważ ładują dynamicznie treści w zależności od potrzeb. Mimo to, dzielą pewne możliwości z stroną w tle:
Komunikacja z skryptami treści: Podobnie jak strona w tle, te strony mogą odbierać wiadomości od skryptów treści, ułatwiając interakcję w ramach rozszerzenia.
Dostęp do specyficznych API rozszerzenia: Te strony mają pełny dostęp do specyficznych API rozszerzenia, zgodnie z uprawnieniami zdefiniowanymi dla rozszerzenia.
permissions
& host_permissions
permissions
& host_permissions
permissions
i host_permissions
to wpisy z manifest.json
, które wskażą jakie uprawnienia ma rozszerzenie przeglądarki (przechowywanie, lokalizacja...) oraz na jakich stronach internetowych.
Ponieważ rozszerzenia przeglądarki mogą być tak uprzywilejowane, złośliwe lub skompromitowane mogłyby umożliwić atakującemu różne sposoby kradzieży wrażliwych informacji i szpiegowania użytkownika.
Sprawdź, jak te ustawienia działają i jak mogą być nadużywane w:
BrowExt - permissions & host_permissionscontent_security_policy
content_security_policy
Polityka bezpieczeństwa treści może być również zadeklarowana wewnątrz manifest.json
. Jeśli jest zdefiniowana, może być wrażliwa.
Domyślne ustawienie dla stron rozszerzeń przeglądarki jest dość restrykcyjne:
Aby strona internetowa mogła uzyskać dostęp do strony rozszerzenia przeglądarki, na przykład strony .html
, ta strona musi być wymieniona w polu web_accessible_resources
pliku manifest.json
.
Na przykład:
Te strony są dostępne pod adresem URL takim jak:
W publicznych rozszerzeniach identyfikator rozszerzenia jest dostępny:
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F600722126-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FJtticLwENZ4i7WwgHiQe%252Fuploads%252Fgit-blob-55da1d3803492ee4681e3e82b9eb1da17f8b25f6%252Fimage%2520%281194%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=94d7206e&sv=1)
Jednakże, jeśli parametr manifest.json
use_dynamic_url
jest używany, ten identyfikator może być dynamiczny.
Zauważ, że nawet jeśli strona jest tutaj wymieniona, może być chroniona przed ClickJacking dzięki Polityce Bezpieczeństwa Treści. Dlatego musisz również to sprawdzić (sekcja frame-ancestors) przed potwierdzeniem, że atak ClickJacking jest możliwy.
Dopuszczenie dostępu do tych stron sprawia, że są one potencjalnie podatne na ClickJacking:
BrowExt - ClickJackingZezwolenie na ładowanie tych stron tylko przez rozszerzenie, a nie przez losowe adresy URL, może zapobiec atakom ClickJacking.
Zauważ, że strony z web_accessible_resources
oraz inne strony rozszerzenia są również zdolne do kontaktowania się z skryptami w tle. Jeśli jedna z tych stron jest podatna na XSS, może to otworzyć większą lukę.
Ponadto, zauważ, że możesz otworzyć tylko strony wskazane w web_accessible_resources
wewnątrz iframe, ale z nowej karty możliwe jest uzyskanie dostępu do dowolnej strony w rozszerzeniu, znając identyfikator rozszerzenia. Dlatego, jeśli znajdziesz XSS wykorzystujące te same parametry, może to być nadużywane, nawet jeśli strona nie jest skonfigurowana w web_accessible_resources
.
externally_connectable
externally_connectable
Zgodnie z dokumentacją, właściwość manifestu "externally_connectable"
deklaruje które rozszerzenia i strony internetowe mogą łączyć się z Twoim rozszerzeniem za pomocą runtime.connect i runtime.sendMessage.
Jeśli klucz
externally_connectable
nie jest zadeklarowany w manifeście Twojego rozszerzenia lub jest zadeklarowany jako"ids": ["*"]
, wszystkie rozszerzenia mogą się łączyć, ale żadne strony internetowe nie mogą się łączyć.Jeśli określone identyfikatory są podane, jak w
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, tylko te aplikacje mogą się łączyć.Jeśli określone wzory są podane, te aplikacje internetowe będą mogły się łączyć:
Jeśli jest określone jako puste:
"externally_connectable": {}
, żadna aplikacja ani strona internetowa nie będą mogły się połączyć.
Im mniej rozszerzeń i adresów URL wskazanych tutaj, tym mniejsza powierzchnia ataku.
Jeśli strona internetowa wrażliwa na XSS lub przejęcie jest wskazana w externally_connectable
, atakujący będzie mógł wysyłać wiadomości bezpośrednio do skryptu w tle, całkowicie omijając skrypt treści i jego CSP.
Dlatego jest to bardzo potężne obejście.
Co więcej, jeśli klient zainstaluje złośliwe rozszerzenie, nawet jeśli nie jest dozwolone do komunikacji z wrażliwym rozszerzeniem, może wstrzyknąć dane XSS w dozwolonej stronie internetowej lub nadużyć WebRequest
lub DeclarativeNetRequest
API, aby manipulować żądaniami na docelowej domenie, zmieniając żądanie strony dla pliku JavaScript. (Zauważ, że CSP na docelowej stronie może zapobiec tym atakom). Ten pomysł pochodzi z tego opisu.
Podsumowanie komunikacji
Rozszerzenie <--> WebApp
Aby komunikować się między skryptem treści a stroną internetową, zazwyczaj używane są wiadomości post. Dlatego w aplikacji internetowej zazwyczaj znajdziesz wywołania funkcji window.postMessage
oraz w skrypcie treści nasłuchiwacze, takie jak window.addEventListener
. Należy jednak zauważyć, że rozszerzenie może również komunikować się z aplikacją internetową, wysyłając wiadomość Post (a zatem strona internetowa powinna się tego spodziewać) lub po prostu sprawić, że strona załaduje nowy skrypt.
Wewnątrz rozszerzenia
Zazwyczaj funkcja chrome.runtime.sendMessage
jest używana do wysyłania wiadomości wewnątrz rozszerzenia (zazwyczaj obsługiwana przez skrypt background
), a aby ją odebrać i obsłużyć, deklarowany jest nasłuchiwacz wywołujący chrome.runtime.onMessage.addListener
.
Możliwe jest również użycie chrome.runtime.connect()
, aby mieć stałe połączenie zamiast wysyłania pojedynczych wiadomości, można go użyć do wysyłania i odbierania wiadomości, jak w poniższym przykładzie:
Last updated