mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-29 22:43:11 +00:00
592 lines
33 KiB
Markdown
592 lines
33 KiB
Markdown
|
# Metodologia de Pentesting em Extensões de Navegador
|
||
|
|
||
|
<details>
|
||
|
|
||
|
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
|
||
|
Outras formas de apoiar o HackTricks:
|
||
|
|
||
|
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
|
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
|
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
|
||
|
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||
|
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios do GitHub** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
|
||
|
</details>
|
||
|
|
||
|
## Informações Básicas
|
||
|
|
||
|
Extensões de navegador são escritas em JavaScript e carregadas pelo navegador em segundo plano. Possuem seu próprio [DOM](https://www.w3schools.com/js/js_htmldom.asp), mas podem interagir com o DOM de outros sites. Isso significa que podem comprometer a confidencialidade, integridade e disponibilidade (CIA) de outros sites.
|
||
|
|
||
|
## Componentes Principais
|
||
|
|
||
|
A estrutura de uma extensão é melhor visualizada e consiste em três componentes. Vamos examinar cada componente em detalhes.
|
||
|
|
||
|
<figure><img src="../../.gitbook/assets/image.png" alt=""><figcaption><p><a href="http://webblaze.cs.berkeley.edu/papers/Extensions.pdf">http://webblaze.cs.berkeley.edu/papers/Extensions.pdf</a></p></figcaption></figure>
|
||
|
|
||
|
### **Scripts de Conteúdo**
|
||
|
|
||
|
Cada script de conteúdo tem acesso direto ao DOM de uma **página web única** e, portanto, está exposto a **entradas potencialmente maliciosas**. No entanto, o script de conteúdo não contém permissões além da capacidade de enviar mensagens para o núcleo da extensão.
|
||
|
|
||
|
Para visualizar e depurar scripts de conteúdo no Chrome, você pode abrir o menu de ferramentas de desenvolvedor do Chrome em Opções > Mais ferramentas > Ferramentas do desenvolvedor OU (Pressione - Ctrl + Shift + I).
|
||
|
|
||
|
Com as ferramentas de desenvolvedor exibidas, clique na aba **Source**, depois na aba **Scripts de Conteúdo**. Aqui você pode ver os scripts de conteúdo em execução das várias extensões e definir pontos de interrupção para monitorar o fluxo de execução. No nosso caso, mostramos através da extensão do navegador Wappalyzer. 
|
||
|
|
||
|
<figure><img src="../../.gitbook/assets/image (1).png" alt=""><figcaption></figcaption></figure>
|
||
|
|
||
|
### **Núcleo da Extensão**
|
||
|
|
||
|
O núcleo da extensão contém a maioria dos privilégios/acessos da extensão, mas só pode interagir com o conteúdo da web por meio de [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 todos os privilégios do usuário.** O binário nativo interage com o núcleo da extensão através 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 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 um do outro por **fortes barreiras de proteção**. Cada componente é executado em um **processo separado do sistema operacional**. Scripts de conteúdo e núcleos de extensão são executados em **processos de sandbox** inacessíveis à maioria dos serviços do sistema operacional.  
|
||
|
|
||
|
Além disso, os scripts de conteúdo são separados das páginas web associadas por **executarem em um heap JavaScript separado**. O script de conteúdo e a página web têm **acesso ao mesmo DOM subjacente**, mas os dois **nunca trocam ponteiros JavaScript**, prevenindo 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`
|
||
|
|
||
|
Scripts de conteúdo são **carregados** sempre que o usuário **navega para uma página correspondente**, no nosso caso qualquer página que corresponda à expressão **`https://example.com/*`** e que não corresponda à regex **`*://*/*/business*`**. Eles executam **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) 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 + " <button>Explain</button>";
|
||
|
div.querySelector("button").addEventListener("click", () =>
|
||
|
{
|
||
|
chrome.runtime.sendMessage("explain");
|
||
|
});
|
||
|
document.body.appendChild(div);
|
||
|
});
|
||
|
```
|
||
|
<figure><img src="../../.gitbook/assets/image (7).png" alt=""><figcaption></figcaption></figure>
|
||
|
|
||
|
Quando este botão é clicado, o script de conteúdo **usa** a [**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage) **para enviar uma mensagem às páginas da extensão**. Isso ocorre porque um script de conteúdo só tem acesso direto a um punhado de APIs, como `storage`. Tudo o mais deve ser feito por páginas de extensão às quais os scripts de conteúdo podem enviar mensagens.
|
||
|
|
||
|
{% hint style="warning" %}
|
||
|
As **capacidades do script de conteúdo** diferem ligeiramente dependendo do navegador. Para navegadores baseados em Chromium, você pode encontrar a lista na [documentação dos Chrome Developers](https://developer.chrome.com/docs/extensions/mv3/content\_scripts/#capabilities), para o Firefox, [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content\_scripts#webextension\_apis) é a fonte definitiva.\
|
||
|
Lembre-se de que o Script de Conteúdo também pode **comunicar com os scripts de fundo** para que eles realizem ações e enviem de volta a resposta.
|
||
|
{% endhint %}
|
||
|
|
||
|
### Scripts de conteúdo injetados
|
||
|
|
||
|
{% hint style="success" %}
|
||
|
Note que **Scripts de Conteúdo não são obrigatórios**, pois também é possível **injetar** scripts **dinamicamente** e **programaticamente** em páginas web através de **`tabs.executeScript`**. Isso na verdade fornece controles mais **granulares**.
|
||
|
{% endhint %}
|
||
|
|
||
|
Para injetar um script de conteúdo programaticamente, sua extensão precisa de [permissões de host](https://developer.chrome.com/docs/extensions/reference/permissions) para a página na qual está tentando injetar scripts. As permissões de host podem ser concedidas **solicitando-as** como parte do manifesto da sua extensão ou temporariamente via [**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"
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
* **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://*.nytimes.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 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 de `css`, mas antes de qualquer outra construção do DOM ou execução de outro script.
|
||
|
* **`document_end`**: Imediatamente após a conclusão do DOM, mas antes que subrecursos como imagens e frames sejam carregados.
|
||
|
|
||
|
#### Via `manifest.json`
|
||
|
```json
|
||
|
{
|
||
|
"name": "My extension",
|
||
|
...
|
||
|
"content_scripts": [
|
||
|
{
|
||
|
"matches": ["https://*.nytimes.com/*"],
|
||
|
"run_at": "document_idle",
|
||
|
"js": ["contentScript.js"]
|
||
|
}
|
||
|
],
|
||
|
...
|
||
|
}
|
||
|
|
||
|
```
|
||
|
Via **`service-worker.js`**
|
||
|
```javascript
|
||
|
chrome.scripting.registerContentScripts([{
|
||
|
id : "test",
|
||
|
matches : [ "https://*.nytimes.com/*" ],
|
||
|
runAt : "document_idle",
|
||
|
js : [ "contentScript.js" ],
|
||
|
}]);
|
||
|
```
|
||
|
### `background`
|
||
|
|
||
|
Quando scripts de conteúdo enviam uma mensagem, o destino é a **página de background**. A página de background é uma página especial que está **sempre presente** a menos que especificado de outra forma no manifesto da extensão. Ela é invisível para o usuário, apesar de ser uma página regular com seu próprio DOM e tudo mais. Sua função é tipicamente coordenar todas as outras partes da extensão.
|
||
|
|
||
|
{% hint style="success" %}
|
||
|
Se uma página de background não for declarada explicitamente, o navegador irá gentilmente **gerar uma** automaticamente e garantir que todos os **scripts de background declarados sejam carregados** nela, como no exemplo anterior de manifest.json.
|
||
|
{% endhint %}
|
||
|
|
||
|
Exemplo de script de background:
|
||
|
```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.
|
||
|
|
||
|
### Páginas de opções e outras
|
||
|
|
||
|
Extensões de 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, eu consegui acessar esta página em `chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca` ou clicando:
|
||
|
|
||
|
<figure><img src="../../.gitbook/assets/image (8).png" alt="" width="375"><figcaption></figcaption></figure>
|
||
|
|
||
|
Ao contrário da página de fundo, essas páginas não são persistentes, mas sim carregadas quando necessário. No entanto, todas elas podem **receber mensagens de scripts de conteúdo**. E todas têm **acesso total às APIs específicas da extensão**, conforme as permissões da extensão permitem.
|
||
|
|
||
|
No total, os contextos relevantes para extensões de navegador parecem assim:
|
||
|
|
||
|
<figure><img src="../../.gitbook/assets/image (9).png" alt="" width="563"><figcaption></figcaption></figure>
|
||
|
|
||
|
### `permissions` & `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 de navegador podem ser tão **privilegiadas**, uma maliciosa ou comprometida pode 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ões de navegador é bastante restritiva:
|
||
|
```bash
|
||
|
script-src 'self'; object-src 'self';
|
||
|
```
|
||
|
Para mais informações sobre CSP e possíveis bypasses, confira:
|
||
|
|
||
|
{% 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 de Navegador, uma página `.html` por exemplo, esta 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://<extension-id>/message.html
|
||
|
```
|
||
|
Em extensões públicas, o **extension-id é acessível**:
|
||
|
|
||
|
<figure><img src="../../.gitbook/assets/image (722).png" alt="" width="375"><figcaption></figcaption></figure>
|
||
|
|
||
|
No entanto, se o parâmetro `manifest.json` **`use_dynamic_url`** for usado, esse **id pode ser dinâmico**.
|
||
|
|
||
|
Ser permitido acessar essas páginas torna essas páginas **potencialmente vulneráveis a 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órias pode prevenir ataques de ClickJacking.
|
||
|
{% endhint %}
|
||
|
|
||
|
### `externally_connectable`
|
||
|
|
||
|
Conforme a [**documentação**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable), a propriedade `"externally_connectable"` do manifesto declara **quais extensões e páginas da web podem se conectar** à sua extensão através de [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 aquelas aplicações** podem se conectar.
|
||
|
* Se **matches** forem especificados, aquelas aplicações da web poderão se conectar:
|
||
|
```json
|
||
|
"matches": [
|
||
|
"https://*.google.com/*",
|
||
|
"*://*.chromium.org/*",
|
||
|
```
|
||
|
* Se estiver especificado como vazio: **`"externally_connectable": {}`**, nenhum aplicativo ou página web poderá se conectar.
|
||
|
|
||
|
Quanto **menos extensões e URLs** indicadas aqui, **menor será a superfície de ataque**.
|
||
|
|
||
|
{% hint style="danger" %}
|
||
|
Se uma página web **vulnerável a XSS ou takeover** estiver indicada em **`externally_connectable`**, um atacante poderá **enviar mensagens diretamente para o script de background**, contornando completamente o Content Script e seu CSP.
|
||
|
|
||
|
Portanto, este é um **bypass muito poderoso**.
|
||
|
{% endhint %}
|
||
|
|
||
|
## Comunicação Web **↔︎** Content Script
|
||
|
|
||
|
Embora os ambientes de execução dos **content scripts e das páginas** que os hospedam sejam **isolados** um do outro, eles **compartilham acesso ao DOM da página**. Se a página deseja se comunicar com o content script, ou com a extensão através do content script, deve fazê-lo através do **DOM compartilhado**.
|
||
|
|
||
|
### Postar Mensagens
|
||
|
|
||
|
{% 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 é verdadeiro apenas se o evento foi acionado por uma ação do usuário
|
||
|
* O script de conteúdo pode estar esperando uma mensagem apenas se o usuário realizar alguma ação
|
||
|
* **domínio de origem**: Pode ser verificado contra uma lista de permissões de domínios.
|
||
|
* Se um regex é usado, tenha muito cuidado
|
||
|
* **Fonte**: `received_message.source !== window` pode ser usado para verificar se a mensagem foi **da mesma janela** onde o Script de Conteúdo está ouvindo.
|
||
|
|
||
|
Os controles anteriores, mesmo que realizados, podem ser vulneráveis, então verifique na seguinte página **potenciais 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**. Então, se o **script de conteúdo** está lendo alguma informação 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 Script de Conteúdo**.
|
||
|
|
||
|
Você também pode encontrar um exemplo de um **XSS baseado em DOM para comprometer uma extensão de 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 de Navegador armazena **informações sensíveis dentro de sua memória**, isso poderia ser **despejado** (especialmente em máquinas Windows) e **procurado** por essas informações.
|
||
|
|
||
|
Portanto, a memória da Extensão de 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**.
|
||
|
|
||
|
## Comunicação Script de Conteúdo **↔︎** Script de Fundo
|
||
|
|
||
|
Um Script de Conteúdo 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 uso único**.
|
||
|
|
||
|
Para lidar com a **resposta**, use a **Promise** retornada. No entanto, para compatibilidade com versões anteriores, você ainda pode passar um **callback** como o último argumento.
|
||
|
|
||
|
Enviar uma solicitação de um **script de conteúdo** se 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);
|
||
|
})();
|
||
|
```
|
||
|
Enviando uma solicitação da **extensão** (geralmente um **script de background**) para um script de conteúdo é semelhante, exceto que você precisa especificar para qual aba enviá-la. Este exemplo demonstra o envio de uma mensagem para o script de conteúdo na aba selecionada.
|
||
|
```javascript
|
||
|
(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 de um script de conteúdo ou página de extensão.
|
||
|
```javascript
|
||
|
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 acima, **`sendResponse()`** foi chamado de forma síncrona. Se você quiser usar `sendResponse()` de forma **assíncrona**, adicione `return true;` ao manipulador de eventos `onMessage`.
|
||
|
|
||
|
> Se múltiplas páginas estiverem ouvindo eventos `onMessage`, **apenas a primeira a chamar `sendResponse()`** para um evento específico terá sucesso em enviar a resposta. Todas as outras respostas para esse evento serão ignoradas.
|
||
|
|
||
|
Para novas extensões, você deve preferir promessas em vez de callbacks. Se você estiver usando callbacks, o callback `sendResponse()` só é válido se usado de forma síncrona, ou se o manipulador de eventos retornar `true` para indicar que responderá de forma assíncrona. O callback da função `sendMessage()` será invocado automaticamente se nenhum manipulador retornar true ou se o callback `sendResponse()` for coletado como lixo.
|
||
|
|
||
|
## Carregando uma Extensão no Navegador
|
||
|
|
||
|
1. **Baixe** a Extensão do Navegador e descompacte
|
||
|
2. Vá para **`chrome://extensions/`** e **ative** o `Modo de Desenvolvedor`
|
||
|
3. Clique no botão **`Carregar descompactado`**
|
||
|
|
||
|
No **Firefox**, vá para **`about:debugging#/runtime/this-firefox`** e clique no botão **`Carregar Complemento Temporário`**.
|
||
|
|
||
|
## Obtendo o código-fonte da loja
|
||
|
|
||
|
A partir [**daqui**](https://gist.github.com/paulirish/78d6c1406c901be02c2d):
|
||
|
|
||
|
### Opção 1: Download da extensão via linha de comando como zip e extração
|
||
|
|
||
|
{% code overflow="wrap" %}
|
||
|
```bash
|
||
|
extension_id=jifpbeccnghkjeaalbbjmodiffmgedin # change this 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"
|
||
|
```
|
||
|
{% endcode %}
|
||
|
|
||
|
Obrigado ao crxviewer pelo [URL de download mágico](https://github.com/Rob--W/crxviewer/blob/6113c25e3569e1ec59365ad9a177aa97e2bcda61/src/cws\_pattern.js#L27-L74).
|
||
|
|
||
|
### Opção 2: Use o site CRX Viewer
|
||
|
|
||
|
[https://robwu.nl/crxviewer/](https://robwu.nl/crxviewer/)
|
||
|
|
||
|
### Opção 3: Use a extensão CRX Viewer
|
||
|
|
||
|
A [Chrome extension source viewer](https://chrome.google.com/webstore/detail/chrome-extension-source-v/jifpbeccnghkjeaalbbjmodiffmgedin?hl=en) é open source ([repositório github](https://github.com/Rob--W/crxviewer)) e facilita muito esse processo.
|
||
|
|
||
|
### Opção 3: Visualizar o código-fonte da extensão instalada localmente
|
||
|
|
||
|
1. Encontre o diretório do perfil local do Chrome. Abra `chrome://version/` e localize o campo "Caminho do Perfil:". Abra essa pasta.
|
||
|
2. Abra a subpasta `Extensions/`
|
||
|
3. Todas as suas extensões estão aqui, com o código-fonte geralmente legível.
|
||
|
|
||
|
#### Mapeamento entre IDs de extensões instaladas localmente e nomes
|
||
|
|
||
|
* Em `about:extensions`, ative o Modo Desenvolvedor e você verá IDs sob cada entrada
|
||
|
* Dentro das pastas `Extensions/`, o arquivo manifest.json tem um campo `name` legível
|
||
|
|
||
|
## Lista de Verificação de Auditoria de Segurança
|
||
|
|
||
|
Embora as Extensões de Navegador tenham uma **superfície de ataque limitada**, algumas delas podem conter **vulnerabilidades** ou **melhorias de proteção potenciais**. As mais comuns são:
|
||
|
|
||
|
* [ ] **Limitar** o máximo possível as **`permissions`** 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 **URL vulnerável a XSS ou a takeover** for mencionada aqui, um atacante poderá **enviar mensagens diretamente aos scripts de background**. Um bypass muito poderoso.
|
||
|
* [ ] **Limitar** o máximo possível os **`web_accessible_resources`**, até mesmo vazio se possível.
|
||
|
* [ ] Se **`web_accessible_resources`** não for nenhum, verificar [**ClickJacking**](browext-clickjacking.md)
|
||
|
* [ ] Se houver alguma **comunicação** da **extensão** para a **página web**, [**verificar vulnerabilidades de XSS**](browext-xss-example.md) causadas na comunicação.
|
||
|
* [ ] Se Post Messages forem usados, verificar [**vulnerabilidades de Post Message**](../postmessage-vulnerabilities/)**.**
|
||
|
* [ ] Se o **Content Script acessar detalhes do DOM**, verificar se eles **não estão introduzindo um XSS** se forem **modificados** pela web
|
||
|
* [ ] Dar uma ênfase especial se essa comunicação também estiver envolvida na **comunicação Content Script -> Background script**
|
||
|
* [ ] **Informações sensíveis não devem ser armazenadas** no código da Extensão de Navegador
|
||
|
* [ ] **Informações sensíveis não devem ser armazenadas** na memória da Extensão de Navegador
|
||
|
|
||
|
## Ferramentas
|
||
|
|
||
|
### [**Tarnish**](https://thehackerblog.com/tarnish/)
|
||
|
|
||
|
* Baixa qualquer extensão do Chrome de um link fornecido da Chrome webstore.
|
||
|
* **Visualizador de [**manifest.json**](https://developer.chrome.com/extensions/manifest)**: simplesmente exibe uma versão em JSON formatado 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 para fingerprinting de extensões 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 a clickjacking dependendo da finalidade 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 quando um usuário tentar instalar a extensão.
|
||
|
* **Função(ões) Perigosa(s)**: mostra a localização de funções perigosas que podem potencialmente ser exploradas por um atacante (por exemplo, funções como innerHTML, chrome.tabs.executeScript).
|
||
|
* **Ponto(s) de Entrada**: mostra onde a extensão recebe entrada de usuário/externa. Isso é útil para entender a área de superfície de uma extensão e procurar pontos potenciais para enviar dados maliciosamente elaborados para a extensão.
|
||
|
* Tanto o scanner de Função(ões) Perigosa(s) quanto o 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 "Ver Arquivo" para visualizar o arquivo de código completo.
|
||
|
* O caminho do arquivo alertado.
|
||
|
* O URI completo da extensão do Chrome do arquivo alertado.
|
||
|
* O tipo de arquivo, como um script de Página de Fundo, Content Script, 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 o uso de bibliotecas JavaScript conhecidas por serem 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 formatados).
|
||
|
* Cache automático dos resultados da análise, executar uma análise de extensão levará um bom tempo na primeira vez que você executá-la. No entanto, a segunda vez, assumindo que a extensão não foi atualizada, será quase instantânea devido aos resultados estarem em cache.
|
||
|
* URLs de Relatório Linkáveis, facilmente linkar alguém para 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 navegadores bem 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-fonte 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/)
|
||
|
|
||
|
<details>
|
||
|
|
||
|
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
|
||
|
Outras maneiras 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 [**merchandising oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
|
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
|
||
|
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga** me no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||
|
* **Compartilhe suas dicas de hacking enviando PRs para os repositórios github do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
|
||
|
</details>
|