hacktricks/pentesting-web/browser-extension-pentesting-methodology/README.md

40 KiB

Metodologia de Pentesting de Extensões do Navegador

Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Informações Básicas

As extensões do navegador são escritas em JavaScript e carregadas pelo navegador em segundo plano. Elas têm seu DOM mas podem interagir com o DOM de outros sites. Isso significa que elas podem comprometer a confidencialidade, integridade e disponibilidade de outros sites (CIA).

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 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) 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 de 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, evitando o vazamento de funcionalidades JavaScript.

manifest.json

Uma extensão do Chrome é apenas uma pasta ZIP com uma extensão de arquivo .crx. 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:

{
"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) da página.

"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 for usada para recuperar o valor message do armazenamento da extensão.

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);
});

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(). Isso ocorre devido à limitação do script de conteúdo no acesso direto às APIs, sendo 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, e para o Firefox, o MDN 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 Origem deve ser clicada, seguida pela aba Scripts de Conteúdo. 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 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 temporariamente através de activeTab.

Exemplo de extensão baseada em activeTab

{% code title="manifest.json" %}

{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}

{% endcode %}

  • Injetar um arquivo JS ao clicar:
// 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:
//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

// 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

{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}

Através de service-worker.js

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:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
{
if (request == "explain")
{
chrome.tabs.create({ url: "https://example.net/explanation" });
}
})

Utiliza a API runtime.onMessage para ouvir mensagens. Quando recebe uma mensagem "explain", utiliza a API tabs para abrir uma página em uma nova aba.

Para depurar o script de segundo plano, você pode ir para os detalhes da extensão e inspecionar o service worker, isso abrirá as ferramentas de desenvolvedor com o script de segundo plano:

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 segundo plano, pois carregam conteúdo dinamicamente quando necessário. Apesar disso, elas compartilham certas capacidades com a página de segundo plano:

  • Comunicação com Scripts de Conteúdo: Semelhante à página de segundo plano, 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.

Veja como essas configurações funcionam e como podem ser abusadas em:

{% content-ref url="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 as páginas de extensão do navegador é bastante restritiva:

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 {% 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:

{
...
"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://<extension-id>/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.

{% hint style="success" %} Observe que mesmo que uma página seja mencionada aqui, ela pode estar protegida contra ClickJacking graças à Política de Segurança de Conteúdo. Portanto, você também precisa verificar (seção frame-ancestors) antes de confirmar se um ataque de ClickJacking é possível. {% endhint %}

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 {% 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 %}

{% hint style="danger" %} Observe que as páginas de web_accessible_resources e outras páginas da extensão também são capazes de contatar scripts de plano de fundo. Portanto, se uma dessas páginas for vulnerável a XSS, poderia abrir uma vulnerabilidade maior.

Além disso, observe que você só pode abrir páginas indicadas em web_accessible_resources dentro de iframes, mas de uma nova guia é possível acessar qualquer página na extensão conhecendo o ID da extensão. Portanto, se um XSS for encontrado abusando dos mesmos parâmetros, ele poderia ser abusado mesmo que a página não esteja configurada em web_accessible_resources. {% endhint %}

externally_connectable

Conforme a documentação, A propriedade de manifesto "externally_connectable" declara quais extensões e páginas da web podem se conectar à sua extensão via runtime.connect e runtime.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:
"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 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 fundo, contornando completamente o Content Script e sua CSP.

Portanto, este é um bypass muito poderoso.

Além disso, se o cliente instalar uma extensão maliciosa, mesmo que não seja permitido comunicar com a extensão vulnerável, ela poderá injetar dados de XSS em uma página da web permitida ou abusar das APIs WebRequest ou DeclarativeNetRequest para manipular solicitações em um domínio específico alterando a solicitação de uma página para um arquivo JavaScript. (Observe que a CSP na página alvo pode prevenir esses ataques). Essa ideia vem deste artigo. {% endhint %}

Resumo da comunicação

Extensão <--> Aplicativo da Web

Para se comunicar entre o script de conteúdo e a página da web, geralmente são usadas mensagens post. Portanto, no aplicativo da web, geralmente você encontrará chamadas para a função window.postMessage e no script de conteúdo ouvintes como window.addEventListener. No entanto, observe que a extensão também pode comunicar-se com o aplicativo da web enviando uma Post Message (e, portanto, o web deve esperar por isso) ou apenas fazer o web carregar um novo script.

Dentro da extensão

Normalmente, a função chrome.runtime.sendMessage é usada para enviar uma mensagem dentro da extensão (geralmente tratada pelo script background) e, para receber e lidar com ela, um ouvinte é declarado chamando chrome.runtime.onMessage.addListener.

Também é possível usar chrome.runtime.connect() para ter uma conexão persistente em vez de enviar mensagens únicas, é possível usá-lo para enviar e receber mensagens como no exemplo a seguir:

chrome.runtime.connect() exemplo ```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>

Também é possível enviar mensagens de um script de fundo para um script de conteúdo localizado em uma guia específica chamando **`chrome.tabs.sendMessage`** onde você precisará indicar o **ID da guia** para enviar a mensagem.

### De `externally_connectable` permitido para a extensão

**Aplicativos da web e extensões de navegador externas permitidas** na configuração `externally_connectable` podem enviar solicitações usando:
```javascript
chrome.runtime.sendMessage(extensionId, ...

Onde for necessário mencionar o ID da extensão.

Comunicação entre Web ↔︎ Script de Conteúdo

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 envolva na comunicação com o script de conteúdo, ou indiretamente com a extensão através do script de conteúdo, é necessário utilizar o DOM que é acessível por ambas as partes como canal de comunicação.

Mensagens de Postagem

{% code title="script-de-conteudo.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 %}

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 permitida de domínios.
  • 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 {% 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 {% 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 {% endcontent-ref %}

Comunicação do Script de Conteúdo ↔︎ Script de Fundo

Um Script de Conteúdo pode usar as funções runtime.sendMessage() ou tabs.sendMessage() para enviar uma mensagem serializável em JSON única.

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:

(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). Exemplo de como enviar uma mensagem para o script de conteúdo na aba selecionada:

// 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 ouvinte de evento para lidar com a mensagem. Isso parece o mesmo em um script de conteúdo ou página de extensão.

// 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 efetivamente. 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.

Informações Sensíveis na Memória/Código/Área de Transferência

Se uma Extensão do Navegador armazena informações sensíveis em sua memória, isso poderá 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 elas serão públicas.

Para fazer dump da memória do navegador, você pode fazer dump da memória do processo ou ir para as configurações da extensão do navegador clicando em Inspect pop-up -> Na seção Memory -> Take a snaphost e CTRL+F para pesquisar dentro do snapshot por informações sensíveis.

Além disso, informações altamente sensíveis como chaves mnemônicas ou senhas não devem ser permitidas de serem copiadas na área de transferência (ou pelo menos removê-las da área de transferência em alguns segundos) porque então processos monitorando a área de transferência poderão obtê-las.

Carregando uma Extensão no Navegador

  1. Baixe a Extensão do Navegador e descompacte
  2. Vá para chrome://extensions/ e habilite o Modo de Desenvolvedor
  3. Clique no botão Load unpacked

No Firefox, vá para about:debugging#/runtime/this-firefox e clique no botão Load Temporary Add-on.

Obtendo o código-fonte da loja

O código-fonte de uma extensão do Chrome pode ser obtido por 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:
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"

Utilize o site CRX Viewer

https://robwu.nl/crxviewer/

Utilize 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. O código-fonte do visualizador está disponível em seu repositório GitHub.

Visualize o código-fonte da 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 "Caminho do Perfil".
  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.

Utilize um Arquivador de Arquivos ou Descompactador

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.

Utilize 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 de fortalecimento potenciais. As seguintes são as mais comuns:

  • Limite o máximo possível as permissões solicitadas
  • Limite o máximo possível as host_permissions
  • Use uma content_security_policy forte
  • Limite o máximo possível o externally_connectable, se nenhum for necessário e possível, não o deixe por padrão, especifique {}
  • Se URL vulnerável a XSS ou a takeover for mencionado aqui, um atacante poderá enviar mensagens diretamente para os scripts de segundo plano. Um bypass muito poderoso.
  • Limite 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
  • Se houver comunicação da extensão para a página da web, verifique XSS vulnerabilidades causadas na comunicação.
  • Se Post Messages forem usados, verifique vulnerabilidades de Post Message.
  • 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

  • Extrai qualquer extensão do Chrome a partir de um link fornecido da Chrome Web Store.
  • Visualizador de manifest.json: exibe simplesmente uma versão JSON formatada do manifesto da extensão.
  • Análise de Impressão Digital: Detecção de 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 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 prompt 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 status de web_accessible_resource dessas páginas.
  • 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 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 serem armazenados em cache.
  • URLs de Relatórios Linkáveis, facilmente vincule alguém a um relatório de extensão gerado pelo tarnish.

Neto

O Projeto Neto é um pacote Python 3 concebido para analisar e desvendar recursos ocultos de plugins e extensões do 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

Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks: