.. | ||
browext-clickjacking.md | ||
browext-permissions-and-host_permissions.md | ||
browext-xss-example.md | ||
README.md |
Metodologia testowania penetracyjnego rozszerzeń przeglądarki
Zacznij od zera i stań się ekspertem od hakowania AWS dzięki htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź PLANY SUBSKRYPCYJNE!
- Kup oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud na GitHubie.
Podstawowe informacje
Rozszerzenia przeglądarki są napisane w JavaScript i są ładowane przez przeglądarkę w tle. Posiadają swoje DOM, ale mogą współdziałać z DOM-ami innych stron. Oznacza to, że mogą naruszać poufność, integralność i dostępność innych stron (CIA).
Główne składniki
Układy rozszerzeń prezentują się najlepiej wizualizowane i składają się z trzech składników. Przyjrzyjmy się każdemu z nich dokładniej.
Skrypty zawartości
Każdy skrypt zawartoś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 zawartości nie posiada uprawnień poza możliwością wysyłania wiadomości do rdzenia rozszerzenia.
Rdzeń rozszerzenia
Rdzeń rozszerzenia zawiera większość uprawnień/dostępów rozszerzenia, ale rdzeń rozszerzenia może współdziałać z zawartością internetową tylko za pomocą XMLHttpRequest i skryptów zawartości. Ponadto rdzeń rozszerzenia nie ma bezpośredniego dostępu do maszyny docelowej.
Binarny natywny
Rozszerzenie pozwala na binarny natywny, który może uzyskać dostęp do maszyny docelowej z pełnymi uprawnieniami użytkownika. Binarny natywny współdziała z rdzeniem rozszerzenia za pomocą standardowego interfejsu programistycznego aplikacji wtyczki Netscape (NPAPI) używanego przez Flash i inne wtyczki przeglądarkowe.
Granice
{% hint style="danger" %} Aby uzyskać pełne uprawnienia użytkownika, atakujący musi przekonać rozszerzenie do przekazania złośliwych danych wejściowych ze skryptu zawartości do rdzenia rozszerzenia oraz z rdzenia rozszerzenia do binarnego natywnego. {% endhint %}
Każdy składnik rozszerzenia jest odseparowany od siebie przez silne granice ochronne. Każdy składnik działa w oddzielnym procesie systemu operacyjnego. Skrypty zawartości i rdzenie rozszerzeń działają w procesach piaskownicy niedostępnych dla większości usług systemu operacyjnego.
Co więcej, skrypty zawartości oddzielone są od powiązanych stron internetowych poprzez działanie w oddzielnej stercie JavaScript. Skrypt zawartości i strona internetowa mają dostęp do tego samego DOM, ale nigdy nie wymieniają wskaźników JavaScript, co zapobiega wyciekowi funkcjonalności JavaScript.
manifest.json
Rozszerzenie Chrome to po prostu folder ZIP z rozszerzeniem .crx. Rdzeniem rozszerzenia jest plik manifest.json
znajdujący się w głównym katalogu, który określa układ, uprawnienia i inne opcje konfiguracji.
Przykład:
{
"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
Skrypty zawartości są ładowane za każdym razem, gdy użytkownik przechodzi do pasującej strony, w naszym przypadku do dowolnej strony pasującej do wyrażenia https://example.com/*
i nie pasującej do regexu *://*/*/business*
. Wykonują się jak własne skrypty strony i mają arbitralny dostęp do Modelu Obiektowego Dokumentu (DOM) strony.
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
Aby uwzględnić lub wykluczyć więcej adresów URL, można również użyć include_globs
i exclude_globs
.
To przykładowy skrypt zawartości, który doda przycisk wyjaśnienia na stronie, gdy interfejs API przechowywania do pobrania wartości message
z pamięci rozszerzenia.
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);
});
Wiadomość jest wysyłana do stron rozszerzenia przez skrypt treści po kliknięciu tego przycisku, poprzez wykorzystanie API runtime.sendMessage(). Wynika to z ograniczenia skryptu treści w bezpośrednim dostępie do interfejsów API, przy czym storage
należy do nielicznych wyjątków. Dla funkcji poza tymi wyjątkami, wiadomości są wysyłane do stron rozszerzenia, z którymi skrypty treści mogą komunikować się.
{% hint style="warning" %}
W zależności od przeglądarki, możliwości skryptu treści mogą nieznacznie się różnić. Dla przeglądarek opartych na Chromium, lista możliwości jest dostępna w dokumentacji deweloperów Chrome'a, a dla Firefoksa, MDN służy jako główne źródło informacji.
Warto również zauważyć, że skrypty treści mają zdolność komunikowania się z skryptami tła, umożliwiając im wykonywanie działań i przekazywanie odpowiedzi.
{% endhint %}
Aby wyświetlić i debugować skrypty treści w Chrome, menu narzędzi deweloperskich Chrome'a można uzyskać z pozycji Opcje > Więcej narzędzi > Narzędzia deweloperskie LUB poprzez naciśnięcie Ctrl + Shift + I.
Po wyświetleniu narzędzi deweloperskich, należy kliknąć zakładkę Źródło, a następnie zakładkę Skrypty treści. Pozwala to na obserwację działających skryptów treści z różnych rozszerzeń oraz ustawianie punktów przerwania w celu śledzenia przepływu wykonania.
Wstrzyknięte skrypty treści
{% hint style="success" %}
Zauważ, że Skrypty treści nie są obowiązkowe, ponieważ istnieje również możliwość dynamicznego wstrzykiwania skryptów i programowego wstrzykiwania ich na strony internetowe za pomocą tabs.executeScript
. Zapewnia to faktycznie większą kontrolę granularną.
{% endhint %}
Dla programowego wstrzykiwania skryptu treści, rozszerzenie musi mieć uprawnienia hosta dla strony, na którą mają być wstrzykiwane skrypty. Uprawnienia te można zabezpieczyć poprzez żądanie ich w manifeście rozszerzenia lub tymczasowo poprzez activeTab.
Przykładowe rozszerzenie oparte na activeTab
{% code title="manifest.json" %}
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
{% endcode %}
- Wstrzyknięcie pliku JS po kliknięciu:
// 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"]
});
});
- Wstrzyknij funkcję po kliknięciu:
//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,
});
});
Przykład z uprawnieniami skryptów
// 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" });
Aby uwzględnić lub wykluczyć więcej adresów URL, można również użyć include_globs
i exclude_globs
.
Skrypty zawartości 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
: Kiedykolwiek to możliwedocument_start
: Po plikach zcss
, ale przed zbudowaniem jakiegokolwiek innego DOM lub uruchomieniem jakiegokolwiek innego skryptu.document_end
: Bezpośrednio po zakończeniu budowy DOM, ale przed załadowaniem zasobów podrzędnych, takich jak obrazy i ramki.
Za pomocą manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
Poprzez service-worker.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.example.com/*" ],
runAt : "document_idle",
js : [ "contentScript.js" ],
}]);
tło
Wiadomości wysłane przez skrypty zawartości są odbierane przez stronę tła, która pełni centralną rolę w koordynowaniu komponentów rozszerzenia. Warto zauważyć, że strona tła pozostaje aktywna przez cały czas trwania rozszerzenia, działając dyskretnie bez bezpośredniej interakcji użytkownika. Posiada własny Model Obiektowy Dokumentu (DOM), umożliwiający kompleksowe interakcje i zarządzanie stanem.
Kluczowe punkty:
- Rola Strony Tła: Działa jako centrum nerwowe rozszerzenia, zapewniając komunikację i koordynację między różnymi częściami rozszerzenia.
- Trwałość: Jest to obecna zawsze jednostka, niewidoczna dla użytkownika, ale integralna dla funkcjonalności rozszerzenia.
- Automatyczne Generowanie: Jeśli nie jest jawnie zdefiniowana, przeglądarka automatycznie utworzy stronę tła. Ta automatycznie wygenerowana strona będzie zawierać wszystkie skrypty tła określone w manifeście rozszerzenia, zapewniając bezproblemową operację zadań tła rozszerzenia.
{% hint style="success" %} Wygodę zapewnianą przez przeglądarkę poprzez automatyczne generowanie strony tła (gdy nie jest jawnie zadeklarowana) zapewnia, że wszystkie niezbędne skrypty tła są zintegrowane i działające, usprawniając proces konfiguracji rozszerzenia. {% endhint %}
Przykładowy skrypt tła:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
{
if (request == "explain")
{
chrome.tabs.create({ url: "https://example.net/explanation" });
}
})
Wykorzystuje API runtime.onMessage do nasłuchiwania wiadomości. Gdy otrzyma wiadomość "explain"
, używa API tabs do otwarcia strony w nowej karcie.
Aby debugować skrypt tła, możesz przejść do szczegółów rozszerzenia i sprawdzić serwis workera, co otworzy narzędzia deweloperskie z skryptem tła:
Strony opcji i inne
Rozszerzenia przeglądarki mogą zawierać różne rodzaje stron:
- Strony akcji są wyświetlane w rozwijanym menu po kliknięciu ikony rozszerzenia.
- Strony, które rozszerzenie załaduje w nowej karcie.
- Strony opcji: Ta strona wyświetla się na wierzchu rozszerzenia po kliknięciu. W poprzednim manifeście w moim przypadku mogłem uzyskać dostęp do tej strony pod adresem
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
lub klikając:
Zauważ, że te strony nie są trwałe jak strony tła, ponieważ dynamicznie ładowane są treści w razie potrzeby. Mimo to, dzielą pewne możliwości z stroną tła:
- Komunikacja z skryptami zawartości: Podobnie jak strona tła, te strony mogą otrzymywać wiadomości od skryptów zawartości, ułatwiając interakcję wewnątrz rozszerzenia.
- Dostęp do API specyficznych dla rozszerzenia: Te strony mają pełny dostęp do API specyficznych dla rozszerzenia, zgodnie z uprawnieniami zdefiniowanymi dla rozszerzenia.
permissions
i host_permissions
permissions
i host_permissions
to wpisy z pliku manifest.json
, które wskazują, jakie uprawnienia ma rozszerzenie przeglądarki (np. przechowywanie, lokalizacja...) i na których stronach internetowych.
Ponieważ rozszerzenia przeglądarki mogą być tak uprzywilejowane, złośliwe lub skompromitowane mogą umożliwić atakującemu różne sposoby kradzieży wrażliwych informacji i szpiegowania użytkownika.
Sprawdź, jak działają te ustawienia i jak mogą być wykorzystane w:
{% content-ref url="browext-permissions-and-host_permissions.md" %} browext-permissions-and-host_permissions.md {% endcontent-ref %}
content_security_policy
Polityka bezpieczeństwa treści może być zadeklarowana również w pliku manifest.json
. Jeśli jest zdefiniowana, może być podatna.
Domyślne ustawienie dla stron rozszerzenia przeglądarki jest raczej restrykcyjne:
script-src 'self'; object-src 'self';
Aby uzyskać więcej informacji na temat CSP i potencjalnych obejść, sprawdź:
{% content-ref url="../content-security-policy-csp-bypass/" %} content-security-policy-csp-bypass {% endcontent-ref %}
web_accessible_resources
Aby strona internetowa mogła uzyskać dostęp do strony Rozszerzenia Przeglądarki, na przykład pliku .html
, ta strona musi być wymieniona w polu web_accessible_resources
pliku manifest.json
.
Na przykład:
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
Te strony są dostępne pod adresem URL takim jak:
chrome-extension://<extension-id>/message.html
W publicznych rozszerzeniach identyfikator rozszerzenia jest dostępny:
Jednakże, jeśli parametr manifest.json
use_dynamic_url
jest używany, to ten identyfikator może być dynamiczny.
{% hint style="success" %} Zauważ, że nawet jeśli strona jest tutaj wymieniona, może być chroniona przed ClickJacking dzięki Polityce Bezpieczeństwa Zawartości. Dlatego też należy to sprawdzić (sekcja frame-ancestors) zanim potwierdzisz, że atak ClickJacking jest możliwy. {% endhint %}
Zezwolenie na dostęp do tych stron sprawia, że te strony są potencjalnie podatne na ClickJacking:
{% content-ref url="browext-clickjacking.md" %} browext-clickjacking.md {% endcontent-ref %}
{% hint style="success" %} Zezwolenie na ładowanie tych stron tylko przez rozszerzenie, a nie przez losowe adresy URL, może zapobiec atakom ClickJacking. {% endhint %}
{% hint style="danger" %}
Zauważ, że strony z web_accessible_resources
oraz inne strony rozszerzenia są również zdolne do kontaktu z skryptami w tle. Dlatego jeśli jedna z tych stron jest podatna na XSS, może to otworzyć większą lukę w zabezpieczeniach.
Ponadto, zauważ, że można otworzyć tylko strony wskazane w web_accessible_resources
w ramkach, ale z nowej karty można uzyskać dostęp do dowolnej strony w rozszerzeniu, znając identyfikator rozszerzenia. Dlatego jeśli zostanie znalezione XSS nadużywające tych samych parametrów, może to być wykorzystane nawet jeśli strona nie jest skonfigurowana w web_accessible_resources
.
{% endhint %}
externally_connectable
Zgodnie z dokumentacją, Właściwość manifestu "externally_connectable"
deklaruje, które rozszerzenia i strony internetowe mogą się połączyć 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ę połączyć, ale żadna strona internetowa nie może. - Jeśli są określone konkretne identyfikatory, jak w
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, tylko te aplikacje mogą się połączyć. - Jeśli są określone dopasowania, te aplikacje internetowe będą mogły się połączyć:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
- Jeśli jest określone jako puste:
"externally_connectable": {}
, żadna aplikacja ani strona internetowa nie będzie mogła się połączyć.
Im mniej rozszerzeń i adresów URL tutaj wskazanych, tym mniejsza powierzchnia ataku.
{% hint style="danger" %}
Jeśli strona internetowa podatna na XSS lub przejęcie jest wskazana w externally_connectable
, atakujący będzie mógł wysyłać wiadomości bezpośrednio do skryptu tła, całkowicie omijając Skrypt Zawartoś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 ono upoważnione do komunikacji z podatnym rozszerzeniem, może wstrzyknąć dane XSS na dozwolonej stronie internetowej lub nadużyć interfejsów API WebRequest
lub DeclarativeNetRequest
do manipulowania żądaniami na docelowej domenie zmieniając żądanie strony dla pliku JavaScript. (Należy zauważyć, że CSP na docelowej stronie może zapobiec tym atakom). Ten pomysł pochodzi z tego opisu.
{% endhint %}
Podsumowanie komunikacji
Rozszerzenie <--> Aplikacja internetowa
Do komunikacji między skryptem zawartości a stroną internetową zazwyczaj używane są wiadomości post. Dlatego w aplikacji internetowej zazwyczaj znajdziesz wywołania funkcji window.postMessage
, a w skrypcie zawartości słuchacze 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 (dlatego strona internetowa powinna się tego spodziewać) lub po prostu sprawić, aby strona internetowa załadowała nowy skrypt.
Wewnątrz rozszerzenia
Zazwyczaj funkcja chrome.runtime.sendMessage
jest używana do wysyłania wiadomości wewnątrz rozszerzenia (zazwyczaj obsługiwane przez skrypt background
) i w celu odbioru i obsługi jest deklarowany słuchacz wywołujący chrome.runtime.onMessage.addListener
.
Możliwe jest również użycie chrome.runtime.connect()
do utrzymania trwałego połączenia zamiast wysyłania pojedynczych wiadomości, można go użyć do wysyłania i odbierania wiadomości jak w poniższym przykładzie:
Przykład chrome.runtime.connect()
```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>
Jest również możliwe wysyłanie wiadomości z tła skryptu do skryptu zawartości znajdującego się w określonej karcie, wywołując **`chrome.tabs.sendMessage`**, gdzie będziesz musiał podać **ID karty**, do której ma zostać wysłana wiadomość.
### Z dozwolonych `externally_connectable` do rozszerzenia
**Aplikacje internetowe i zewnętrzne rozszerzenia przeglądarki dozwolone** w konfiguracji `externally_connectable` mogą wysyłać żądania za pomocą:
```javascript
chrome.runtime.sendMessage(extensionId, ...
Gdzie jest wymagane wspomnienie ID rozszerzenia.
Komunikacja między skryptem zawartości a stroną internetową
Środowiska, w których działają skrypty zawartości i gdzie istnieją strony hosta, są od siebie oddzielone, zapewniając izolację. Pomimo tej izolacji obie strony mają możliwość interakcji z Modelem Obiektowym Dokumentu (DOM) strony, wspólnym zasobem. Aby strona hosta mogła komunikować się ze skryptem zawartości, lub pośrednio z rozszerzeniem poprzez skrypt zawartości, konieczne jest wykorzystanie DOM, do którego mają dostęp obie strony jako kanału komunikacji.
Wiadomości post
{% code title="skrypt-zawartości.js" %}
// 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);
{% endcode %}
{% code title="example.js" %}
document.getElementById("theButton").addEventListener("click", () => {
window.postMessage(
{type : "FROM_PAGE", text : "Hello from the webpage!"}, "*");
}, false);
{% endcode %}
Bezpieczna komunikacja Post Message powinna sprawdzać autentyczność otrzymanej wiadomości, można to zrobić sprawdzając:
event.isTrusted
: Jest to prawdziwe tylko wtedy, gdy zdarzenie zostało wywołane przez akcję użytkownika.- Skrypt zawartości może oczekiwać wiadomości tylko wtedy, gdy użytkownik wykonuje jakąś akcję.
- Domena pochodzenia: może oczekiwać wiadomości tylko z listy zaufanych domen.
- Jeśli używany jest regex, należy być bardzo ostrożnym.
- Źródło:
received_message.source !== window
można użyć do sprawdzenia, czy wiadomość pochodzi z tego samego okna, w którym nasłuchuje Skrypt Zawartości.
Poprzednie sprawdzenia, nawet jeśli wykonane, mogą być podatne, dlatego sprawdź na następnej stronie potencjalne sposoby obchodzenia Post Message:
{% content-ref url="../postmessage-vulnerabilities/" %} postmessage-vulnerabilities {% endcontent-ref %}
Iframe
Inną możliwą metodą komunikacji może być poprzez adresy URL Iframe, przykład można znaleźć w:
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
DOM
To nie jest "dokładnie" sposób komunikacji, ale strona internetowa i skrypt zawartości będą miały dostęp do DOM. Dlatego jeśli skrypt zawartości odczytuje pewne informacje z niego, ufając DOM-owi strony, strona internetowa może zmodyfikować te dane (ponieważ strona internetowa nie powinna być ufała, lub ponieważ strona internetowa jest podatna na XSS) i naruszyć Skrypt Zawartości.
Można także znaleźć przykład DOM based XSS do naruszenia rozszerzenia przeglądarki w:
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
Skrypt Zawartości ↔︎ Skrypt Tła Komunikacja
Skrypt Zawartości może użyć funkcji runtime.sendMessage() lub tabs.sendMessage() do wysłania jednorazowej wiadomości serializowalnej w formacie JSON.
Aby obsłużyć odpowiedź, użyj zwróconego Promise. Mimo to, dla zachowania kompatybilności wstecznej, nadal można przekazać funkcję zwrotną jako ostatni argument.
Wysłanie żądania ze skryptu zawartości wygląda następująco:
(async () => {
const response = await chrome.runtime.sendMessage({greeting: "hello"});
// do something with response here, not outside the function
console.log(response);
})();
Wysyłanie żądania z rozszerzenia (zwykle z skryptu tła). Przykład, jak wysłać wiadomość do skryptu zawartości w wybranej karcie:
// 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);
})();
Na końcu odbiorczym, musisz skonfigurować nasłuchiwanie zdarzenia runtime.onMessage, aby obsłużyć wiadomość. Wygląda to tak samo zarówno z treścią skryptu, jak i stroną rozszerzenia.
// 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"});
}
);
W podświetlonym przykładzie sendResponse()
zostało wykonane w sposób synchroniczny. Aby zmodyfikować obsługę zdarzenia onMessage
w celu asynchronicznego wykonania sendResponse()
, konieczne jest uwzględnienie return true;
.
Ważnym aspektem jest, że w scenariuszach, gdzie wiele stron jest ustawionych do otrzymywania zdarzeń onMessage
, pierwsza strona wykonująca sendResponse()
dla określonego zdarzenia będzie jedyną zdolną skutecznie dostarczyć odpowiedź. Wszelkie kolejne odpowiedzi na to samo zdarzenie nie będą brane pod uwagę.
Tworząc nowe rozszerzenia, należy preferować obietnice (promises) w przeciwieństwie do wywołań zwrotnych (callbacks). W odniesieniu do użycia wywołań zwrotnych, funkcja sendResponse()
jest uważana za ważną tylko wtedy, gdy jest wykonywana bezpośrednio w kontekście synchronicznym, lub jeśli obsługa zdarzenia wskazuje na operację asynchroniczną poprzez zwrócenie true
. Jeśli żaden z obsługujących nie zwróci true
lub jeśli funkcja sendResponse()
zostanie usunięta z pamięci (zebrana przez garbage collector), zwrotny wywołanie związane z funkcją sendMessage()
zostanie domyślnie uruchomione.
Wrażliwe informacje w pamięci/kodzie/schowku
Jeśli Rozszerzenie Przeglądarki przechowuje wrażliwe informacje w swojej pamięci, mogą one zostać wydobyte (szczególnie w systemach Windows) i przeszukane w poszukiwaniu tych informacji.
Dlatego pamięć Rozszerzenia Przeglądarki nie powinna być uważana za bezpieczną i wrażliwe informacje takie jak dane uwierzytelniające czy frazy mnemoniczne nie powinny być przechowywane.
Oczywiście, nie umieszczaj wrażliwych informacji w kodzie, ponieważ będą one publiczne.
Aby wydobyć pamięć z przeglądarki, można wydobyć pamięć procesu lub przejść do ustawień rozszerzenia przeglądarki i kliknąć Inspect pop-up
-> W sekcji Memory
-> Zrób zrzut
i użyć CTRL+F
do wyszukiwania w zrzucie wrażliwych informacji.
Co więcej, bardzo wrażliwe informacje, takie jak klucze mnemoniczne czy hasła, nie powinny być zezwolone na kopiowanie do schowka (lub przynajmniej usuń je ze schowka po kilku sekundach), ponieważ procesy monitorujące schowek będą w stanie je uzyskać.
Ładowanie Rozszerzenia w Przeglądarce
- Pobierz Rozszerzenie Przeglądarki i rozpakuj
- Przejdź do
chrome://extensions/
i włączTryb Dewelopera
- Kliknij przycisk
Załaduj rozpakowane
W Firefoxie przejdź do about:debugging#/runtime/this-firefox
i kliknij przycisk Załaduj tymczasowe rozszerzenie
.
Pobieranie kodu źródłowego z sklepu
Kod źródłowy rozszerzenia Chrome można uzyskać za pomocą różnych metod. Poniżej znajdują się szczegółowe wyjaśnienia i instrukcje dla każdej opcji.
Pobierz Rozszerzenie jako ZIP za pomocą Wiersza Poleceń
Kod źródłowy rozszerzenia Chrome można pobrać jako plik ZIP za pomocą wiersza poleceń. Wymaga to użycia curl
do pobrania pliku ZIP z określonego adresu URL, a następnie wypakowania zawartości pliku ZIP do katalogu. Oto kroki:
- Zastąp
"extension_id"
rzeczywistym identyfikatorem rozszerzenia. - Wykonaj następujące polecenia:
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"
Użyj strony CRX Viewer
Użyj rozszerzenia CRX Viewer
Inną wygodną metodą jest użycie przeglądarki Chrome Extension Source Viewer, który jest projektem open-source. Można go zainstalować ze sklepu Chrome Web Store. Kod źródłowy przeglądarki jest dostępny w repozytorium GitHub.
Wyświetl źródło lokalnie zainstalowanego rozszerzenia
Lokalnie zainstalowane rozszerzenia Chrome można również sprawdzić. Oto jak:
- Otwórz katalog profilu lokalnego Chrome, odwiedzając
chrome://version/
i zlokalizuj pole "Profile Path". - Przejdź do podfolderu
Extensions/
w katalogu profilu. - Ten folder zawiera wszystkie zainstalowane rozszerzenia, zazwyczaj z kodem źródłowym w czytelnej formie.
Aby zidentyfikować rozszerzenia, można przyporządkować ich identyfikatory do nazw:
- Włącz tryb dewelopera na stronie
about:extensions
, aby zobaczyć identyfikatory każdego rozszerzenia. - Wewnątrz folderu każdego rozszerzenia plik
manifest.json
zawiera czytelną sekcjęname
, pomagającą zidentyfikować rozszerzenie.
Użyj Archiwizatora plików lub Odpakowywacza
Przejdź do Chrome Web Store i pobierz rozszerzenie. Plik będzie miał rozszerzenie .crx
. Zmień rozszerzenie pliku z .crx
na .zip
. Użyj dowolnego archiwizatora plików (np. WinRAR, 7-Zip itp.), aby wypakować zawartość pliku ZIP.
Użyj trybu dewelopera w Chrome
Otwórz Chrome i przejdź do chrome://extensions/
. Włącz "Tryb dewelopera" w prawym górnym rogu. Kliknij "Załaduj rozszerzenie bez pakowania...". Przejdź do katalogu swojego rozszerzenia. To nie pobiera kodu źródłowego, ale jest przydatne do przeglądania i modyfikowania kodu już pobranego lub opracowanego rozszerzenia.
Lista kontrolna audytu bezpieczeństwa
Mimo że rozszerzenia przeglądarki mają ograniczoną powierzchnię ataku, niektóre z nich mogą zawierać podatności lub potencjalne ulepszenia zabezpieczeń. Oto najczęstsze z nich:
- Ograniczaj jak najbardziej żądane
uprawnienia
- Ograniczaj jak najbardziej
host_permissions
- Użyj silnej
content_security_policy
- Ograniczaj jak najbardziej
externally_connectable
, jeśli nie jest to potrzebne i możliwe, nie pozostawiaj go domyślnie, określ{}
- Jeśli tutaj wymieniono URL podatny na XSS lub przejęcie, atakujący będzie mógł wysyłać wiadomości bezpośrednio do skryptów tła. Bardzo potężne obejście.
- Ograniczaj jak najbardziej
web_accessible_resources
, nawet jeśli jest puste, jeśli to możliwe. - Jeśli
web_accessible_resources
nie jest puste, sprawdź ClickJacking - Jeśli występuje jakakolwiek komunikacja z rozszerzenia do strony internetowej, sprawdź podatności na XSS spowodowane w komunikacji.
- Jeśli są używane Post Messages, sprawdź podatności na Post Message.
- Jeśli Skrypt zawartości uzyskuje dostęp do szczegółów DOM, sprawdź, czy nie wprowadzają one XSS, jeśli zostaną zmodyfikowane przez stronę internetową
- Zwróć szczególną uwagę, jeśli ta komunikacja jest również zaangażowana w komunikację Skryptu zawartości -> Skrypt tła
- Informacje poufne nie powinny być przechowywane w kodzie rozszerzenia przeglądarki
- Informacje poufne nie powinny być przechowywane w pamięci rozszerzenia przeglądarki
Narzędzia
Tarnish
- Pobiera dowolne rozszerzenie Chrome z podanego linku sklepu Chrome.
- Przeglądarka manifest.json: po prostu wyświetla sformatowaną wersję manifestu rozszerzenia.
- Analiza odcisków palców: Wykrywanie web_accessible_resources i automatyczna generacja JavaScriptu odcisków palców rozszerzenia Chrome.
- Analiza potencjalnego Clickjackingu: Wykrywanie stron HTML rozszerzenia z dyrektywą web_accessible_resources. Są one potencjalnie podatne na clickjacking w zależności od celu stron.
- Przeglądarka ostrzeżeń o uprawnieniach: pokazuje listę wszystkich ostrzeżeń dotyczących uprawnień Chrome, które zostaną wyświetlone podczas próby instalacji rozszerzenia przez użytkownika.
- Funkcje niebezpieczne: pokazuje lokalizację funkcji niebezpiecznych, które potencjalnie mogą być wykorzystane przez atakującego (np. funkcje takie jak innerHTML, chrome.tabs.executeScript).
- Punkty wejścia: pokazuje, gdzie rozszerzenie pobiera dane od użytkownika/zewnętrzne dane. Jest to przydatne do zrozumienia obszaru powierzchni rozszerzenia i poszukiwania potencjalnych punktów do przesyłania złośliwie spreparowanych danych do rozszerzenia.
- Zarówno skanery Funkcji niebezpiecznych, jak i Punkty wejścia mają następujące elementy dla generowanych alertów:
- Istotny fragment kodu i linia, która spowodowała alert.
- Opis problemu.
- Przycisk „Wyświetl plik”, aby zobaczyć pełny plik źródłowy zawierający kod.
- Ścieżka pliku ostrzeżonego.
- Pełny URI rozszerzenia Chrome ostrzeżonego pliku.
- Typ pliku, taki jak skrypt strony tła, skrypt zawartości, akcja przeglądarki, itp.
- Jeśli podatna linia znajduje się w pliku JavaScript, ścieżki wszystkich stron, gdzie jest ona zawarta, a także status web_accessible_resource tych stron.
- Analizator zasad bezpieczeństwa zawartości (CSP) i sprawdzarka bypass: Wskaże słabe punkty w zasadach CSP Twojego rozszerzenia oraz oświetli ewentualne sposoby na ich obejście z powodu zatwierdzonych na białej liście CDN itp.
- Znane biblioteki podatne: Wykorzystuje Retire.js do sprawdzenia użycia znanych podatnych bibliotek JavaScript.
- Pobierz rozszerzenie i sformatowane wersje.
- Pobierz oryginalne rozszerzenie.
- Pobierz sformatowaną wersję rozszerzenia (automatycznie sformatowany HTML i JavaScript).
- Automatyczne buforowanie wyników skanowania, uruchomienie skanowania rozszerzenia zajmie sporo czasu za pierwszym razem. Jednak drugi raz, zakładając, że rozszerzenie nie zostało zaktualizowane, będzie prawie natychmiastowe ze względu na buforowanie wyników.
- Linkowalne adresy URL raportów, łatwe przekazanie komuś innemu raportu o rozszerzeniu wygenerowanego przez tarnish.
Neto
Projekt Neto to pakiet Python 3 stworzony do analizy i odkrywania ukrytych funkcji wtyczek i rozszerzeń przeglądarek takich jak Firefox i Chrome. Automatyzuje proces rozpakowywania spakowanych plików w celu wydobycia tych funkcji z odpowiednich zasobów w rozszerzeniu, takich jak manifest.json
, foldery lokalizacyjne czy pliki źródłowe Javascript i HTML.
Odnośniki
- Dzięki dla @naivenom za pomoc przy tej metodologii
- 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
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź PLANY SUBSKRYPCYJNE!
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.