# Metodologia de Pentesting de Extensões de Navegador
Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)! Outras formas de apoiar o HackTricks: * Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)! * Adquira [**produtos oficiais PEASS & HackTricks**](https://peass.creator-spring.com) * Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
## Informações Básicas As extensões de navegador são escritas em JavaScript e carregadas pelo navegador em segundo plano. Elas possuem seu [DOM](https://www.w3schools.com/js/js\_htmldom.asp) mas podem interagir com o DOM de outros sites. Isso significa que elas podem comprometer a confidencialidade, integridade e disponibilidade de outros sites. ## Componentes Principais Os layouts das extensões ficam melhores quando visualizados e consistem em três componentes. Vamos analisar cada componente em detalhes.

http://webblaze.cs.berkeley.edu/papers/Extensions.pdf

### **Scripts de Conteúdo** Cada script de conteúdo tem acesso direto ao DOM de uma **única página da web** e, portanto, está exposto a **entradas potencialmente maliciosas**. No entanto, o script de conteúdo não possui permissões além da capacidade de enviar mensagens para o núcleo da extensão. ### **Núcleo da Extensão** O núcleo da extensão contém a maioria dos privilégios/acessos da extensão, mas o núcleo da extensão só pode interagir com o conteúdo da web via [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) e scripts de conteúdo. Além disso, o núcleo da extensão não tem acesso direto à máquina hospedeira. ### **Binário Nativo** A extensão permite um binário nativo que pode **acessar a máquina hospedeira com os privilégios completos do usuário**. O binário nativo interage com o núcleo da extensão por meio da Interface de Programação de Aplicativos de Plug-in Netscape padrão ([NPAPI](https://en.wikipedia.org/wiki/NPAPI)) usada pelo Flash e outros plug-ins de navegador. ### Limites {% hint style="danger" %} Para obter os privilégios completos do usuário, um atacante deve convencer a extensão a passar uma entrada maliciosa do script de conteúdo para o núcleo da extensão e do núcleo da extensão para o binário nativo. {% endhint %} Cada componente da extensão é separado uns dos outros por **fortes limites de proteção**. Cada componente é executado em um **processo de sistema operacional separado**. Os scripts de conteúdo e os núcleos da extensão são executados em **processos de sandbox** indisponíveis para a maioria dos serviços do sistema operacional. Além disso, os scripts de conteúdo são separados de suas páginas da web associadas por **serem executados em um heap JavaScript separado**. O script de conteúdo e a página da web têm **acesso ao mesmo DOM subjacente**, mas os dois **nunca trocam ponteiros JavaScript**, impedindo o vazamento de funcionalidades JavaScript. ## **`manifest.json`** Uma extensão do Chrome é apenas uma pasta ZIP com uma extensão de arquivo [.crx](https://www.lifewire.com/crx-file-2620391). O núcleo da extensão é o arquivo **`manifest.json`** na raiz da pasta, que especifica o layout, permissões e outras opções de configuração. Exemplo: ```json { "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` Os scripts de conteúdo são **carregados** sempre que o usuário **navega para uma página correspondente**, no nosso caso qualquer página correspondente à expressão **`https://example.com/*`** e que não corresponda ao regex **`*://*/*/business*`**. Eles são executados **como os próprios scripts da página** e têm acesso arbitrário ao [Modelo de Objeto de Documento (DOM)](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) da página. ```json "content_scripts": [ { "js": [ "script.js" ], "matches": [ "https://example.com/*", "https://www.example.com/*" ], "exclude_matches": ["*://*/*business*"], } ], ``` Para incluir ou excluir mais URLs, também é possível usar **`include_globs`** e **`exclude_globs`**. Este é um exemplo de script de conteúdo que adicionará um botão de explicação à página quando [a API de armazenamento](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage) for usada para recuperar o valor `message` do armazenamento da extensão. ```js chrome.storage.local.get("message", result => { let div = document.createElement("div"); div.innerHTML = result.message + " "; div.querySelector("button").addEventListener("click", () => { chrome.runtime.sendMessage("explain"); }); document.body.appendChild(div); }); ```
Uma mensagem é enviada para as páginas da extensão pelo script de conteúdo quando este botão é clicado, através da utilização da [**API runtime.sendMessage()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage). Isso ocorre devido à limitação do script de conteúdo no acesso direto às APIs, sendo o `storage` uma das poucas exceções. Para funcionalidades além dessas exceções, mensagens são enviadas para as páginas da extensão com as quais os scripts de conteúdo podem se comunicar. {% hint style="warning" %} Dependendo do navegador, as capacidades do script de conteúdo podem variar ligeiramente. Para navegadores baseados em Chromium, a lista de capacidades está disponível na [documentação dos desenvolvedores do Chrome](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities), e para o Firefox, o [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis) serve como fonte primária.\ Também é importante notar que os scripts de conteúdo têm a capacidade de se comunicar com scripts de plano de fundo, permitindo que realizem ações e transmitam respostas de volta. {% endhint %} Para visualizar e depurar scripts de conteúdo no Chrome, o menu de ferramentas para desenvolvedores do Chrome pode ser acessado em Opções > Mais ferramentas > Ferramentas do desenvolvedor OU pressionando Ctrl + Shift + I. Ao exibir as ferramentas para desenvolvedores, a **aba Source** deve ser clicada, seguida pela aba **Content Scripts**. Isso permite a observação dos scripts de conteúdo em execução de várias extensões e a definição de pontos de interrupção para rastrear o fluxo de execução. ### Scripts de conteúdo injetados {% hint style="success" %} Observe que **Scripts de Conteúdo não são obrigatórios** pois também é possível **injetar scripts dinamicamente** e **injetá-los programaticamente** em páginas da web via **`tabs.executeScript`**. Isso, na verdade, fornece mais **controles granulares**. {% endhint %} Para a injeção programática de um script de conteúdo, a extensão deve ter [permissões de host](https://developer.chrome.com/docs/extensions/reference/permissions) para a página na qual os scripts serão injetados. Essas permissões podem ser garantidas tanto **solicitando-as** dentro do manifesto da extensão quanto de forma temporária através de [**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab). #### Exemplo de extensão baseada em activeTab {% code title="manifest.json" %} ```json { "name": "My extension", ... "permissions": [ "activeTab", "scripting" ], "background": { "service_worker": "background.js" }, "action": { "default_title": "Action Button" } } ``` {% endcode %} * **Injetar um arquivo JS ao clicar:** ```javascript // 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"] }); }); ``` * **Injetar uma função** ao clicar: ```javascript //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, }); }); ``` #### Exemplo com permissões de script ```javascript // 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" }); ``` Para incluir ou excluir mais URLs, também é possível usar **`include_globs`** e **`exclude_globs`**. ### Scripts de Conteúdo `run_at` O campo `run_at` controla **quando os arquivos JavaScript são injetados na página da web**. O valor preferido e padrão é `"document_idle"`. Os valores possíveis são: * **`document_idle`**: Sempre que possível * **`document_start`**: Após quaisquer arquivos `css`, mas antes de qualquer outro DOM ser construído ou qualquer outro script ser executado. * **`document_end`**: Imediatamente após o DOM estar completo, mas antes de subrecursos como imagens e frames serem carregados. #### Via `manifest.json` ```json { "name": "My extension", ... "content_scripts": [ { "matches": ["https://*.example.com/*"], "run_at": "document_idle", "js": ["contentScript.js"] } ], ... } ``` Através de **`service-worker.js`** ```javascript chrome.scripting.registerContentScripts([{ id : "test", matches : [ "https://*.example.com/*" ], runAt : "document_idle", js : [ "contentScript.js" ], }]); ``` ### `background` As mensagens enviadas pelos scripts de conteúdo são recebidas pela **página de fundo**, que desempenha um papel central na coordenação dos componentes da extensão. Notavelmente, a página de fundo persiste ao longo da vida da extensão, operando discretamente sem interação direta do usuário. Possui seu próprio Document Object Model (DOM), permitindo interações complexas e gerenciamento de estado. **Pontos Chave**: - **Papel da Página de Fundo:** Age como o centro nervoso da extensão, garantindo a comunicação e coordenação entre várias partes da extensão. - **Persistência:** É uma entidade sempre presente, invisível para o usuário, mas fundamental para a funcionalidade da extensão. - **Geração Automática:** Se não for explicitamente definida, o navegador criará automaticamente uma página de fundo. Esta página gerada automaticamente incluirá todos os scripts de fundo especificados no manifesto da extensão, garantindo a operação contínua das tarefas de fundo da extensão. {% hint style="success" %} A conveniência fornecida pelo navegador ao gerar automaticamente uma página de fundo (quando não declarada explicitamente) garante que todos os scripts de fundo necessários sejam integrados e operacionais, simplificando o processo de configuração da extensão. {% endhint %} Exemplo de script de fundo: ```js chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request == "explain") { chrome.tabs.create({ url: "https://example.net/explanation" }); } }) ``` Ele usa a [API runtime.onMessage](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage) para ouvir mensagens. Quando uma mensagem `"explain"` é recebida, ele usa a [API tabs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) para abrir uma página em uma nova aba. Para depurar o script de fundo, você pode ir para os **detalhes da extensão e inspecionar o service worker**, isso abrirá as ferramentas de desenvolvedor com o script de fundo:
### Páginas de opções e outras As extensões do navegador podem conter vários tipos de páginas: * **Páginas de ação** são exibidas em um **menu suspenso quando o ícone da extensão é clicado**. * Páginas que a extensão irá **carregar em uma nova aba**. * **Páginas de opções**: Esta página é exibida sobre a extensão quando clicada. No manifesto anterior, no meu caso, consegui acessar esta página em `chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca` ou clicando em:
Observe que essas páginas não são persistentes como as páginas de fundo, pois carregam conteúdo dinamicamente quando necessário. Apesar disso, elas compartilham certas capacidades com a página de fundo: - **Comunicação com Scripts de Conteúdo:** Semelhante à página de fundo, essas páginas podem receber mensagens de scripts de conteúdo, facilitando a interação dentro da extensão. - **Acesso a APIs Específicas da Extensão:** Essas páginas têm amplo acesso a APIs específicas da extensão, sujeitas às permissões definidas para a extensão. ### `permissions` e `host_permissions` **`permissions`** e **`host_permissions`** são entradas do `manifest.json` que indicarão **quais permissões** a extensão do navegador possui (armazenamento, localização...) e em **quais páginas da web**. Como as extensões do navegador podem ser tão **privilegiadas**, uma maliciosa ou comprometida poderia permitir ao atacante **diferentes meios de roubar informações sensíveis e espionar o usuário**. Verifique como essas configurações funcionam e como elas podem ser abusadas em: {% content-ref url="browext-permissions-and-host_permissions.md" %} [browext-permissions-and-host\_permissions.md](browext-permissions-and-host\_permissions.md) {% endcontent-ref %} ### `content_security_policy` Uma **política de segurança de conteúdo** também pode ser declarada dentro do `manifest.json`. Se houver uma definida, ela poderia ser **vulnerável**. A configuração padrão para páginas de extensão do navegador é bastante restritiva: ```bash script-src 'self'; object-src 'self'; ``` Para obter mais informações sobre CSP e possíveis formas de contorná-lo, verifique: {% content-ref url="../content-security-policy-csp-bypass/" %} [content-security-policy-csp-bypass](../content-security-policy-csp-bypass/) {% endcontent-ref %} ### `web_accessible_resources` para que uma página da web acesse uma página de uma Extensão do Navegador, uma página `.html`, por exemplo, essa página precisa ser mencionada no campo **`web_accessible_resources`** do `manifest.json`.\ Por exemplo: ```javascript { ... "web_accessible_resources": [ { "resources": [ "images/*.png" ], "matches": [ "https://example.com/*" ] }, { "resources": [ "fonts/*.woff" ], "matches": [ "https://example.com/*" ] } ], ... } ``` Estas páginas são acessíveis em URLs como: ``` chrome-extension:///message.html ``` Em extensões públicas, o **ID da extensão é acessível**:
No entanto, se o parâmetro `manifest.json` **`use_dynamic_url`** for usado, esse **ID pode ser dinâmico**. Permitir o acesso a essas páginas torna essas páginas **potencialmente vulneráveis ao ClickJacking**: {% content-ref url="browext-clickjacking.md" %} [browext-clickjacking.md](browext-clickjacking.md) {% endcontent-ref %} {% hint style="success" %} Permitir que essas páginas sejam carregadas apenas pela extensão e não por URLs aleatórios poderia prevenir ataques de CLickJacking. {% endhint %} ### `externally_connectable` Conforme a [**documentação**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable), a propriedade do manifesto `"externally_connectable"` declara **quais extensões e páginas da web podem se conectar** à sua extensão via [runtime.connect](https://developer.chrome.com/docs/extensions/reference/runtime#method-connect) e [runtime.sendMessage](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage). * Se a chave **`externally_connectable`** não for declarada no manifesto da sua extensão ou for declarada como **`"ids": ["*"]`**, **todas as extensões podem se conectar, mas nenhuma página da web pode se conectar**. * Se **IDs específicos forem especificados**, como em `"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]`, **apenas essas aplicações** podem se conectar. * Se **correspondências** forem especificadas, esses aplicativos da web poderão se conectar: ```json "matches": [ "https://*.google.com/*", "*://*.chromium.org/*", ``` * Se for especificado como vazio: **`"externally_connectable": {}`**, nenhum aplicativo ou site poderá se conectar. Quanto **menos extensões e URLs** forem indicados aqui, **menor será a superfície de ataque**. {% hint style="danger" %} Se uma página da web **vulnerável a XSS ou takeover** for indicada em **`externally_connectable`**, um atacante poderá **enviar mensagens diretamente para o script de plano de fundo**, contornando completamente o Content Script e sua CSP. Portanto, este é um **bypass muito poderoso**. {% endhint %} ## Comunicação Web **↔︎** Content Script Os ambientes onde os **scripts de conteúdo** operam e onde as páginas hospedeiras existem estão **separados** um do outro, garantindo **isolamento**. Apesar desse isolamento, ambos têm a capacidade de interagir com o **Modelo de Objeto de Documento (DOM)** da página, um recurso compartilhado. Para que a página hospedeira se comunique com o **content script**, ou indiretamente com a extensão por meio do content script, é necessário utilizar o **DOM** que é acessível por ambas as partes como canal de comunicação. ### Mensagens de Postagem {% code title="content-script.js" %} ```javascript 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); port.postMessage(event.data.text); } }, false); ``` {% endcode %} {% code title="example.js" %} ```javascript document.getElementById("theButton").addEventListener("click", () => { window.postMessage( {type : "FROM_PAGE", text : "Hello from the webpage!"}, "*"); }, false); ``` {% endcode %} Uma comunicação segura de Post Message deve verificar a autenticidade da mensagem recebida, isso pode ser feito verificando: - **`event.isTrusted`**: Isso é True apenas se o evento foi acionado por uma ação do usuário - O script de conteúdo pode esperar uma mensagem apenas se o usuário realizar alguma ação - **domínio de origem**: pode esperar uma mensagem apenas de uma lista de domínios permitidos. - Se uma regex for usada, tenha muito cuidado - **Fonte**: `received_message.source !== window` pode ser usado para verificar se a mensagem foi **da mesma janela** onde o Content Script está ouvindo. As verificações anteriores, mesmo se realizadas, podem ser vulneráveis, então verifique na seguinte página **possíveis bypasses de Post Message**: {% content-ref url="../postmessage-vulnerabilities/" %} [postmessage-vulnerabilities](../postmessage-vulnerabilities/) {% endcontent-ref %} ### Iframe Outra possível forma de comunicação pode ser através de **URLs de Iframe**, você pode encontrar um exemplo em: {% content-ref url="browext-xss-example.md" %} [browext-xss-example.md](browext-xss-example.md) {% endcontent-ref %} ### DOM Isso não é "exatamente" uma forma de comunicação, mas a **web e o script de conteúdo terão acesso ao DOM da web**. Portanto, se o **script de conteúdo** estiver lendo algumas informações dele, **confiando no DOM da web**, a web poderia **modificar esses dados** (porque a web não deve ser confiável, ou porque a web é vulnerável a XSS) e **comprometer o Content Script**. Você também pode encontrar um exemplo de **XSS baseado em DOM para comprometer uma extensão do navegador** em: {% content-ref url="browext-xss-example.md" %} [browext-xss-example.md](browext-xss-example.md) {% endcontent-ref %} ## Informações Sensíveis na Memória/Código Se uma Extensão do Navegador armazena **informações sensíveis em sua memória**, isso poderia ser **dumped** (especialmente em máquinas Windows) e **procurado** por essas informações. Portanto, a memória da Extensão do Navegador **não deve ser considerada segura** e **informações sensíveis** como credenciais ou frases mnemônicas **não devem ser armazenadas**. Claro, **não coloque informações sensíveis no código**, pois será **público**. ## Comunicação entre Content Script **↔︎** Background Script Um Content Script pode usar as funções [**runtime.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage) **ou** [**tabs.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/tabs#method-sendMessage) para enviar uma mensagem **serializável em JSON** de uma vez. Para lidar com a **resposta**, use a **Promise** retornada. No entanto, para compatibilidade com versões anteriores, ainda é possível passar um **callback** como último argumento. Enviar uma solicitação de um **script de conteúdo** parece com isso: ```javascript (async () => { const response = await chrome.runtime.sendMessage({greeting: "hello"}); // do something with response here, not outside the function console.log(response); })(); ``` Enviar uma solicitação da **extensão** (geralmente um **script de plano de fundo**) Um Script de Conteúdo pode usar as funções, exceto que você precisa especificar para qual aba enviá-lo. Exemplo de como enviar uma mensagem para o script de conteúdo na aba selecionada: ```javascript // 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); })(); ``` No **lado receptor**, você precisa configurar um [**runtime.onMessage**](https://developer.chrome.com/docs/extensions/reference/runtime#event-onMessage) **ouvinte de evento** para lidar com a mensagem. Isso parece o mesmo em um script de conteúdo ou página de extensão. ```javascript // 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"}); } ); ``` No exemplo destacado, **`sendResponse()`** foi executado de forma síncrona. Para modificar o manipulador de eventos `onMessage` para execução assíncrona de `sendResponse()`, é imperativo incorporar `return true;`. Uma consideração importante é que em cenários onde várias páginas estão configuradas para receber eventos `onMessage`, **a primeira página a executar `sendResponse()`** para um evento específico será a única capaz de entregar a resposta de forma eficaz. Quaisquer respostas subsequentes ao mesmo evento não serão consideradas. Ao criar novas extensões, a preferência deve ser para promessas em vez de callbacks. Em relação ao uso de callbacks, a função `sendResponse()` é considerada válida apenas se for executada diretamente no contexto síncrono, ou se o manipulador de eventos indicar uma operação assíncrona retornando `true`. Caso nenhum dos manipuladores retorne `true` ou se a função `sendResponse()` for removida da memória (coletada pelo garbage collector), o callback associado à função `sendMessage()` será acionado por padrão. ## Carregando uma Extensão no Navegador 1. **Baixe** a Extensão do Navegador e descompacte 2. Acesse **`chrome://extensions/`** e **habilite** o `Modo de Desenvolvedor` 3. Clique no botão **`Carregar sem compactação`** No **Firefox**, acesse **`about:debugging#/runtime/this-firefox`** e clique no botão **`Carregar Complemento Temporário`**. ## Obtendo o código-fonte da loja O código-fonte de uma extensão do Chrome pode ser obtido por meio de vários métodos. Abaixo estão explicações detalhadas e instruções para cada opção. ### Baixar Extensão como ZIP via Linha de Comando O código-fonte de uma extensão do Chrome pode ser baixado como um arquivo ZIP usando a linha de comando. Isso envolve usar `curl` para buscar o arquivo ZIP de uma URL específica e depois extrair o conteúdo do arquivo ZIP para um diretório. Aqui estão os passos: 1. Substitua `"extension_id"` pelo ID real da extensão. 2. Execute os seguintes comandos: ```bash 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" ``` ### Usar o site CRX Viewer [https://robwu.nl/crxviewer/](https://robwu.nl/crxviewer/) ### Usar a extensão CRX Viewer Outro método conveniente é usar o Chrome Extension Source Viewer, que é um projeto de código aberto. Pode ser instalado na [Chrome Web Store](https://chrome.google.com/webstore/detail/chrome-extension-source-v/jifpbeccnghkjeaalbbjmodiffmgedin?hl=en). O código-fonte do visualizador está disponível em seu [repositório GitHub](https://github.com/Rob--W/crxviewer). ### Visualizar o código-fonte de uma extensão instalada localmente As extensões do Chrome instaladas localmente também podem ser inspecionadas. Veja como: 1. Acesse o diretório do perfil local do Chrome visitando `chrome://version/` e localizando o campo "Profile Path". 2. Navegue até a subpasta `Extensions/` dentro do diretório do perfil. 3. Esta pasta contém todas as extensões instaladas, geralmente com seu código-fonte em um formato legível. Para identificar as extensões, você pode mapear seus IDs para nomes: - Ative o Modo de Desenvolvedor na página `about:extensions` para ver os IDs de cada extensão. - Dentro da pasta de cada extensão, o arquivo `manifest.json` contém um campo `name` legível, ajudando a identificar a extensão. ### Usar um Arquivador ou Descompactador de Arquivos Vá para a Chrome Web Store e baixe a extensão. O arquivo terá a extensão `.crx`. Altere a extensão do arquivo de `.crx` para `.zip`. Use qualquer arquivador de arquivos (como WinRAR, 7-Zip, etc.) para extrair o conteúdo do arquivo ZIP. ### Usar o Modo Desenvolvedor no Chrome Abra o Chrome e vá para `chrome://extensions/`. Ative o "Modo Desenvolvedor" no canto superior direito. Clique em "Carregar extensão sem compactação...". Navegue até o diretório da sua extensão. Isso não baixa o código-fonte, mas é útil para visualizar e modificar o código de uma extensão já baixada ou desenvolvida. ## Lista de Verificação de Auditoria de Segurança Embora as Extensões do Navegador tenham uma **superfície de ataque limitada**, algumas delas podem conter **vulnerabilidades** ou **melhorias potenciais de fortalecimento**. As mais comuns são: * [ ] **Limitar** o máximo possível as **`permissões`** solicitadas * [ ] **Limitar** o máximo possível as **`host_permissions`** * [ ] Usar uma **`content_security_policy`** **forte** * [ ] **Limitar** o máximo possível o **`externally_connectable`**, se nenhum for necessário e possível, não deixe por padrão, especifique **`{}`** * [ ] Se uma **URL vulnerável a XSS ou a takeover** for mencionada aqui, um atacante poderá **enviar mensagens diretamente aos scripts de segundo plano**. Um bypass muito poderoso. * [ ] **Limitar** o máximo possível os **`web_accessible_resources`**, mesmo vazio, se possível. * [ ] Se **`web_accessible_resources`** não for nenhum, verifique o [**ClickJacking**](browext-clickjacking.md) * [ ] Se houver alguma **comunicação** da **extensão** para a **página da web**, [**verifique XSS**](browext-xss-example.md) **vulnerabilidades** causadas na comunicação. * [ ] Se Post Messages forem usados, verifique [**vulnerabilidades de Post Message**](../postmessage-vulnerabilities/)**.** * [ ] Se o **Script de Conteúdo acessar detalhes do DOM**, verifique se eles **não estão introduzindo um XSS** se forem **modificados** pela web * [ ] Faça um destaque especial se essa comunicação também estiver envolvida na **comunicação do Script de Conteúdo -> Script de Segundo Plano** * **Informações sensíveis não devem ser armazenadas** dentro do código da Extensão do Navegador * **Informações sensíveis não devem ser armazenadas** na memória da Extensão do Navegador ## Ferramentas ### [**Tarnish**](https://thehackerblog.com/tarnish/) * Extrai qualquer extensão do Chrome a partir de um link fornecido da Chrome Web Store. * Visualizador de [**manifest.json**](https://developer.chrome.com/extensions/manifest): exibe simplesmente uma versão JSON formatada do manifesto da extensão. * Análise de Impressão Digital: Detecção de [web\_accessible\_resources](https://developer.chrome.com/extensions/manifest/web\_accessible\_resources) e geração automática de JavaScript de impressão digital de extensão do Chrome. * Análise Potencial de Clickjacking: Detecção de páginas HTML de extensão com a diretiva [web\_accessible\_resources](https://developer.chrome.com/extensions/manifest/web\_accessible\_resources) definida. Estas são potencialmente vulneráveis ao clickjacking, dependendo do propósito das páginas. * Visualizador de Aviso(s) de Permissão: que mostra uma lista de todos os avisos de permissão do Chrome que serão exibidos ao usuário ao tentar instalar a extensão. * Função(ões) Perigosa(s): mostra a localização de funções perigosas que poderiam ser potencialmente exploradas por um atacante (por exemplo, funções como innerHTML, chrome.tabs.executeScript). * Ponto(s) de Entrada: mostra onde a extensão recebe entrada do usuário/externa. Isso é útil para entender a área de superfície de uma extensão e procurar pontos potenciais para enviar dados maliciosamente criados para a extensão. * Tanto as Função(ões) Perigosa(s) quanto os scanners de Ponto(s) de Entrada têm o seguinte para seus alertas gerados: * Trecho de código relevante e linha que causou o alerta. * Descrição do problema. * Um botão "Visualizar Arquivo" para visualizar o arquivo de origem completo contendo o código. * O caminho do arquivo alertado. * O URI completo da extensão do Chrome do arquivo alertado. * O tipo de arquivo que é, como um script de Página de Fundo, Script de Conteúdo, Ação do Navegador, etc. * Se a linha vulnerável estiver em um arquivo JavaScript, os caminhos de todas as páginas onde ele está incluído, bem como o tipo dessas páginas e o status de [web\_accessible\_resource](https://developer.chrome.com/extensions/manifest/web\_accessible\_resources). * Analisador de Política de Segurança de Conteúdo (CSP) e verificador de bypass: Isso apontará fraquezas na CSP da sua extensão e também iluminará quaisquer maneiras potenciais de contornar sua CSP devido a CDNs na lista branca, etc. * Bibliotecas Vulneráveis Conhecidas: Isso usa [Retire.js](https://retirejs.github.io/retire.js/) para verificar qualquer uso de bibliotecas JavaScript conhecidas como vulneráveis. * Baixar extensão e versões formatadas. * Baixar a extensão original. * Baixar uma versão embelezada da extensão (HTML e JavaScript automaticamente embelezados). * Armazenamento automático de resultados de varredura, executar uma varredura de extensão levará um bom tempo na primeira vez que você a executar. No entanto, na segunda vez, assumindo que a extensão não tenha sido atualizada, será quase instantâneo devido aos resultados estarem em cache. * URLs de Relatórios Linkáveis, facilmente vincule alguém a um relatório de extensão gerado pelo tarnish. ### [Neto](https://github.com/elevenpaths/neto) O Projeto Neto é um pacote Python 3 concebido para analisar e desvendar recursos ocultos de plugins e extensões de navegador para navegadores conhecidos como Firefox e Chrome. Ele automatiza o processo de descompactar os arquivos empacotados para extrair esses recursos de recursos relevantes em uma extensão como `manifest.json`, pastas de localização ou arquivos de origem Javascript e HTML. ## Referências * **Agradecimentos a** [**@naivenom**](https://twitter.com/naivenom) **pela ajuda com esta metodologia** * [https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing](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/10/anatomy-of-a-basic-extension/) * [https://palant.info/2022/08/24/attack-surface-of-extension-pages/](https://palant.info/2022/08/24/attack-surface-of-extension-pages/) * [https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/](https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/) * [https://help.passbolt.com/assets/files/PBL-02-report.pdf](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/develop/concepts/content-scripts) * [https://developer.chrome.com/docs/extensions/mv2/background-pages](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://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/) * [https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0](https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0)
Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)! Outras formas de apoiar o HackTricks: * Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)! * Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com) * Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Compartilhe seus truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.