# Browser Extension Pentesting Methodology

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中被广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## 基本信息

浏览器扩展是用JavaScript编写的，并由浏览器在后台加载。它有自己的[DOM](https://www.w3schools.com/js/js_htmldom.asp)，但可以与其他网站的DOM进行交互。这意味着它可能会危及其他网站的机密性、完整性和可用性（CIA）。

## 主要组件

扩展布局在可视化时效果最佳，由三个组件组成。让我们深入了解每个组件。

<figure><img src="/files/D6rEu2FlqnA2zNj6qqH3" 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>

### **内容脚本**

每个内容脚本直接访问**单个网页**的DOM，因此容易受到**潜在恶意输入**的影响。但是，内容脚本除了能够向扩展核心发送消息外，不具备其他权限。

### **扩展核心**

扩展核心包含大部分扩展的权限/访问，但扩展核心只能通过[XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)和内容脚本与Web内容进行交互。此外，扩展核心无法直接访问主机机器。

### **本地二进制**

扩展允许本地二进制文件以用户完整权限访问主机机器。本地二进制通过标准的Netscape插件应用程序编程接口（[NPAPI](https://en.wikipedia.org/wiki/NPAPI)）与扩展核心进行交互，该接口被Flash和其他浏览器插件使用。

### 边界

{% hint style="danger" %}
要获得用户的完整权限，攻击者必须说服扩展将内容脚本中的恶意输入传递给扩展核心，再从扩展核心传递给本地二进制文件。
{% endhint %}

扩展的每个组件之间由**强大的保护边界**分隔。每个组件在**单独的操作系统进程**中运行。内容脚本和扩展核心在**沙盒进程**中运行，无法访问大多数操作系统服务。

此外，内容脚本通过**在单独的JavaScript堆中运行**与其关联的网页分离。内容脚本和网页具有**对同一底层DOM的访问权限**，但两者**不会交换JavaScript指针**，从而防止JavaScript功能的泄漏。

## **`manifest.json`**

Chrome扩展只是一个带有[.crx文件扩展名](https://www.lifewire.com/crx-file-2620391)的ZIP文件夹。扩展的核心是位于文件夹根目录下的\*\*`manifest.json`\*\*文件，用于指定布局、权限和其他配置选项。

示例：

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

内容脚本在用户导航到匹配页面时加载，对于我们的情况是任何匹配 **`https://example.com/*`** 表达式的页面，但不匹配 **`*://*/*/business*`** 正则表达式。它们像页面自己的脚本一样执行，并且可以任意访问页面的[文档对象模型（DOM）](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)。

```json
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
```

为了包含或排除更多的URL，也可以使用\*\*`include_globs`**和**`exclude_globs`\*\*。

以下是一个示例内容脚本，当使用[存储API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage)从扩展的存储中检索`message`值时，将在页面上添加一个解释按钮。

```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="/files/nkBejtGV1C3FM9TR1PFF" alt=""><figcaption></figcaption></figure>

当单击此按钮时，内容脚本通过利用[runtime.sendMessage() API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage)向扩展页面发送消息。这是因为内容脚本在直接访问API方面存在限制，`storage`是少数例外之一。对于超出这些例外的功能，消息将发送到内容脚本可以与之通信的扩展页面。

{% hint style="warning" %}
根据浏览器的不同，内容脚本的功能可能略有不同。对于基于Chromium的浏览器，功能列表可在[Chrome开发者文档](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities)中找到，而对于Firefox，[MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis)是主要来源。\
值得注意的是，内容脚本可以与后台脚本通信，使其能够执行操作并传递响应。
{% endhint %}

要在Chrome中查看和调试内容脚本，可以从“选项”>“更多工具”>“开发者工具”或按Ctrl + Shift + I打开Chrome开发者工具菜单。

在显示开发者工具后，应单击**源标签**，然后单击**内容脚本**标签。这样可以观察各种扩展中正在运行的内容脚本，并设置断点以跟踪执行流程。

### 注入的内容脚本

{% hint style="success" %}
请注意**内容脚本不是强制性的**，也可以通过**动态注入**脚本和通过\*\*`tabs.executeScript`**在网页中**以编程方式注入**它们。这实际上提供了更多**细粒度控制\*\*。
{% endhint %}

要对内容脚本进行编程注入，扩展需要具有[主机权限](https://developer.chrome.com/docs/extensions/reference/permissions)，以便将脚本注入到页面中。这些权限可以通过在扩展的清单中**请求**它们或通过[**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab)在临时基础上获得。

#### 基于activeTab的示例扩展

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

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

{% endcode %}

* **点击时注入JS文件：**

```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"]
});
});
```

* **点击时注入函数**:

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

#### 具有脚本权限的示例

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

为了包含或排除更多的URL，也可以使用\*\*`include_globs`**和**`exclude_globs`\*\*。

### 内容脚本 `run_at`

`run_at`字段控制**何时将JavaScript文件注入到网页**中。首选和默认值是`"document_idle"`。

可能的值包括：

* **`document_idle`**：尽可能早
* **`document_start`**：在`css`文件之后，但在构建任何其他DOM或运行任何其他脚本之前。
* **`document_end`**：在DOM完成后立即，但在加载图像和框架等子资源之前。

#### 通过 `manifest.json`

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

```

通过 **`service-worker.js`**

```javascript
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.example.com/*" ],
runAt : "document_idle",
js : [ "contentScript.js" ],
}]);
```

### `背景`

内容脚本发送的消息由**背景页**接收，背景页在协调扩展组件方面起着中心作用。值得注意的是，背景页在整个扩展的生命周期中持续存在，不需要直接用户交互。它拥有自己的文档对象模型（DOM），可以实现复杂的交互和状态管理。

**关键要点**：

* **背景页角色：** 充当扩展的神经中枢，确保扩展各部分之间的通信和协调。
* **持久性：** 它是一个始终存在的实体，对用户不可见但对扩展的功能至关重要。
* **自动生成：** 如果没有明确定义，浏览器将自动创建一个背景页。这个自动生成的页面将包括扩展清单中指定的所有背景脚本，确保扩展的后台任务无缝运行。

{% hint style="success" %}
浏览器自动生成背景页（当没有明确定义时）的便利性确保了所有必要的背景脚本被集成和运行，简化了扩展的设置过程。
{% endhint %}

示例背景脚本：

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

它使用[runtime.onMessage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)来监听消息。当收到一个`"explain"`消息时，它使用[tabs API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs)在新标签页中打开一个页面。

要调试后台脚本，您可以转到**扩展详细信息并检查服务工作者**，这将使用后台脚本打开开发者工具：

<figure><img src="https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/browser-extension-pentesting-methodology/broken-reference" alt=""><figcaption></figcaption></figure>

### 选项页面和其他

浏览器扩展可以包含各种类型的页面：

* **操作页面**在单击扩展图标时显示在**下拉菜单**中。
* 扩展将在**新标签页中加载**的页面。
* **选项页面**：单击时显示在扩展顶部的页面。在我的情况下，我能够在`chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca`或单击以下链接中访问此页面：

<figure><img src="/files/9zfz3p8oritCjrOrUi6V" alt="" width="375"><figcaption></figcaption></figure>

请注意，这些页面不像后台页面那样持久，因为它们根据需要动态加载内容。尽管如此，它们与后台页面共享某些功能：

* \*\*与内容脚本通信：\*\*与后台页面类似，这些页面可以从内容脚本接收消息，促进扩展内的交互。
* \*\*访问扩展特定的API：\*\*这些页面可以全面访问扩展特定的API，取决于为扩展定义的权限。

### `permissions`和`host_permissions`

**`permissions`和`host_permissions`是`manifest.json`中的条目，将指示浏览器扩展具有哪些权限（存储、位置...）和在哪些网页**中。

由于浏览器扩展可能具有如此**特权**，一个恶意的扩展或被入侵的扩展可能允许攻击者**以不同方式窃取敏感信息并监视用户**。

查看这些设置如何工作以及它们如何可能在以下情况中被滥用：

{% content-ref url="/pages/F4GKj9pMyzL7yEBqDB3K" %}
[BrowExt - permissions & host\_permissions](/pentesting-web/browser-extension-pentesting-methodology/browext-permissions-and-host_permissions.md)
{% endcontent-ref %}

### `content_security_policy`

**内容安全策略**也可以在`manifest.json`中声明。如果定义了一个，它可能会**存在漏洞**。

浏览器扩展页面的默认设置相当严格：

```bash
script-src 'self'; object-src 'self';
```

有关CSP和潜在的绕过方法的更多信息，请查看：

{% content-ref url="/pages/MNBsDILE5555KkghznPR" %}
[Content Security Policy (CSP) Bypass](/pentesting-web/content-security-policy-csp-bypass.md)
{% endcontent-ref %}

### `web_accessible_resources`

为了让网页访问浏览器扩展的页面，比如一个`.html`页面，这个页面需要在`manifest.json`的\*\*`web_accessible_resources`\*\*字段中提及。\
例如：

```javascript
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
```

这些页面可以通过以下URL访问：

```
chrome-extension://<extension-id>/message.html
```

在公共扩展中，**扩展ID是可访问的**：

<figure><img src="/files/CImUwG0aN5jkAFCA9Bsi" alt="" width="375"><figcaption></figcaption></figure>

尽管如此，如果使用`manifest.json`参数\*\*`use_dynamic_url`**，则此**ID可以是动态的\*\*。

允许访问这些页面使这些页面**潜在易受点击劫持攻击**：

{% content-ref url="/pages/JKb2PRRzSuluOoP4evXJ" %}
[BrowExt - ClickJacking](/pentesting-web/browser-extension-pentesting-methodology/browext-clickjacking.md)
{% endcontent-ref %}

{% hint style="success" %}
只允许扩展加载这些页面，而不是随机URL，可以防止点击劫持攻击。
{% endhint %}

### `externally_connectable`

根据[**文档**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable)，`"externally_connectable"`清单属性声明了**哪些扩展和网页可以通过**[**runtime.connect**](https://developer.chrome.com/docs/extensions/reference/runtime#method-connect)**和**[**runtime.sendMessage**](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage)**连接到您的扩展**。

* 如果在您的扩展清单中**未**声明\*\*`externally_connectable`**键，或者声明为**`"ids": ["*"]`\*\*，**所有扩展都可以连接，但没有网页可以连接**。
* 如果指定了**特定的ID**，例如`"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]`，**只有这些应用程序**可以连接。
* 如果指定了**匹配项**，这些Web应用程序将能够连接：

```json
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
```

* 如果指定为空：**`"externally_connectable": {}`**，则没有应用程序或网页能够连接。

在这里指定的**扩展和 URL 越少**，**攻击面就越小**。

{% hint style="danger" %}
如果一个易受 XSS 或接管攻击的网页在 **`externally_connectable`** 中被指定，攻击者将能够直接向后台脚本发送消息，完全绕过内容脚本及其 CSP。

因此，这是一个**非常强大的绕过**。

此外，如果客户端安装了一个恶意扩展，即使它没有被允许与易受攻击的扩展通信，它也可以在允许的网页中注入 **XSS 数据**，或者滥用 **`WebRequest`** 或 **`DeclarativeNetRequest`** API 来操纵针对特定域的请求，从而更改页面对 **JavaScript 文件** 的请求（请注意，目标页面上的 CSP 可能会阻止这些攻击）。这个想法来自[**这篇文章**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability)。
{% endhint %}

##

## Web **↔︎** 内容脚本通信

**内容脚本**运行的环境和主机页面存在的环境是**分离**的，确保了**隔离**。尽管存在这种隔离，但两者都可以与页面的**文档对象模型（DOM）进行交互，这是一个共享资源。为了使主机页面与内容脚本**进行通信，或者间接地通过内容脚本与扩展进行通信，需要利用双方都可以访问的**DOM**作为通信渠道。

### 发送消息

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

安全的Post Message通信应该检查接收到的消息的真实性，可以通过以下方式进行检查：

* **`event.isTrusted`**：只有在事件由用户操作触发时才为True
* 内容脚本可能只期望在用户执行某些操作时接收消息
* **来源域**：可能只允许白名单中的域发送消息
* 如果使用正则表达式，请非常小心
* **来源**：`received_message.source !== window`可用于检查消息是否来自内容脚本正在侦听的**同一窗口**。

即使执行了上述检查，也可能存在漏洞，请在以下页面检查**潜在的Post Message绕过**：

{% content-ref url="/pages/4cVtCo7Y7JBwHY4oOl6C" %}
[PostMessage Vulnerabilities](/pentesting-web/postmessage-vulnerabilities.md)
{% endcontent-ref %}

### Iframe

另一种可能的通信方式可能是通过**Iframe URLs**，您可以在以下示例中找到：

{% content-ref url="/pages/fBdM7ifiuNReeyNmaOAQ" %}
[BrowExt - XSS Example](/pentesting-web/browser-extension-pentesting-methodology/browext-xss-example.md)
{% endcontent-ref %}

### DOM

这并不是“确切地”一种通信方式，但是**web和内容脚本将可以访问web DOM**。因此，如果**内容脚本**从中读取一些信息，**信任web DOM**，web可能会**修改这些数据**（因为不应信任web，或者因为web容易受到XSS攻击），并**危及内容脚本**。

您还可以在以下示例中找到一个**基于DOM的XSS示例来危及浏览器扩展**：

{% content-ref url="/pages/fBdM7ifiuNReeyNmaOAQ" %}
[BrowExt - XSS Example](/pentesting-web/browser-extension-pentesting-methodology/browext-xss-example.md)
{% endcontent-ref %}

## 内存/代码中的敏感信息

如果浏览器扩展在其内存中存储**敏感信息**，这些信息可能会被**转储**（特别是在Windows机器上），并且可以对这些信息进行**搜索**。

因此，浏览器扩展的内存**不应被视为安全**，**敏感信息**（如凭据或助记词短语）**不应存储**。

当然，**不要将敏感信息放在代码中**，因为它将是**公开的**。

要从浏览器中转储内存，您可以**转储进程内存**或转到浏览器扩展的**设置**，单击\*\*`检查弹出窗口`\*\* -> 在\*\*`内存`**部分 -> `拍摄快照`，然后使用**`CTRL+F`\*\*在快照中搜索敏感信息。

## 内容脚本 **↔︎** 后台脚本通信

内容脚本可以使用函数[**runtime.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage) **或** [**tabs.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/tabs#method-sendMessage) 发送**一次性可JSON序列化**消息。

要处理**响应**，请使用返回的**Promise**。尽管出于向后兼容性考虑，仍然可以将**回调函数**作为最后一个参数传递。

从**内容脚本**发送请求如下所示：

```javascript
(async () => {
const response = await chrome.runtime.sendMessage({greeting: "hello"});
// do something with response here, not outside the function
console.log(response);
})();
```

从**扩展程序**（通常是**后台脚本**）发送请求。内容脚本可以使用这些函数，只是需要指定要发送到哪个标签页。以下是向所选标签页中的内容脚本发送消息的示例：

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

在**接收端**，您需要设置一个[**runtime.onMessage**](https://developer.chrome.com/docs/extensions/reference/runtime#event-onMessage) **事件侦听器**来处理消息。无论是来自内容脚本还是扩展页面，这看起来都是一样的。

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

在突出显示的示例中，**`sendResponse()`** 以同步方式执行。要修改`onMessage`事件处理程序以异步执行`sendResponse()`，必须加入`return true;`。

一个重要的考虑因素是，在设置多个页面接收`onMessage`事件的情况下，**第一个执行`sendResponse()`** 的页面将是唯一能够有效传递响应的页面。对于同一事件的任何后续响应将不被考虑。

在编写新扩展时，应优先选择使用 promises 而不是回调。关于回调的使用，只有在直接在同步上下文中执行`sendResponse()`，或者如果事件处理程序通过返回`true`指示异步操作时，`sendResponse()`函数才被视为有效。如果没有处理程序返回`true`，或者如果`sendResponse()`函数从内存中删除（被垃圾回收），则与`sendMessage()`函数关联的回调将默认触发。

## 在浏览器中加载扩展

1. **下载**浏览器扩展并解压缩
2. 转到\*\*`chrome://extensions/`**并**启用\*\*`开发者模式`
3. 点击\*\*`加载已解压的扩展程序`\*\*按钮

在**Firefox**中，转到\*\*`about:debugging#/runtime/this-firefox`**，然后点击**`加载临时附加组件`\*\*按钮。

## 从商店获取源代码

Chrome扩展的源代码可以通过各种方法获取。以下是每种选项的详细说明和说明。

### 通过命令行下载ZIP格式的扩展

可以使用命令行将Chrome扩展的源代码下载为ZIP文件。这涉及使用`curl`从特定URL获取ZIP文件，然后将ZIP文件的内容提取到一个目录中。以下是步骤：

1. 用实际的扩展ID替换`"extension_id"`。
2. 执行以下命令：

```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"
```

### 使用 CRX Viewer 网站

<https://robwu.nl/crxviewer/>

### 使用 CRX Viewer 扩展

另一种方便的方法是使用 Chrome 扩展源代码查看器，这是一个开源项目。可以从[Chrome 网上应用店](https://chrome.google.com/webstore/detail/chrome-extension-source-v/jifpbeccnghkjeaalbbjmodiffmgedin?hl=en)安装。查看器的源代码可在其[GitHub 存储库](https://github.com/Rob--W/crxviewer)中找到。

### 查看本地安装扩展的源代码

也可以检查本地安装的 Chrome 扩展。操作步骤如下：

1. 访问 `chrome://version/` 查看 Chrome 本地配置文件目录，并找到“Profile Path”字段。
2. 转到配置文件目录中的 `Extensions/` 子文件夹。
3. 该文件夹包含所有已安装的扩展，通常以可读格式显示其源代码。

要识别扩展，可以将其 ID 映射到名称：

* 在 `about:extensions` 页面上启用开发者模式，查看每个扩展的 ID。
* 在每个扩展的文件夹中，`manifest.json` 文件包含一个可读的 `name` 字段，可帮助您识别扩展。

### 使用文件压缩工具或解包工具

前往 Chrome 网上应用店并下载扩展。文件将具有 `.crx` 扩展名。将文件扩展名从 `.crx` 更改为 `.zip`。使用任何文件压缩工具（如 WinRAR、7-Zip 等）提取 ZIP 文件的内容。

### 在 Chrome 中使用开发者模式

打开 Chrome 并转到 `chrome://extensions/`。在右上角启用“开发者模式”。单击“加载已解压的扩展...”。导航到扩展的目录。这不会下载源代码，但对于查看和修改已下载或已开发的扩展的代码很有用。

## 安全审计清单

尽管浏览器扩展具有**有限的攻击面**，但其中一些可能包含**漏洞**或**潜在的加固改进**。以下是最常见的几种：

* [ ] **尽可能限制**所请求的\*\*`权限`\*\*
* [ ] **尽可能限制**所请求的\*\*`host_permissions`\*\*
* [ ] 使用**强大的** **`content_security_policy`**
* [ ] **尽可能限制**`externally_connectable`，如果不需要且可能的话，不要默认留下，指定\*\*`{}`\*\*
* [ ] 如果此处提到了**易受跨站脚本攻击或接管**的 URL，攻击者将能够**直接向后台脚本发送消息**。这是非常强大的绕过方式。
* [ ] **尽可能限制**`web_accessible_resources`，如果可能，甚至为空。
* [ ] 如果\*\*`web_accessible_resources`\*\*不是空的，请检查[**点击劫持**](/pentesting-web/browser-extension-pentesting-methodology/browext-clickjacking.md)
* [ ] 如果从**扩展**到**网页**有任何**通信**，请检查由通信引起的[**跨站脚本攻击**](/pentesting-web/browser-extension-pentesting-methodology/browext-xss-example.md)**漏洞**。
* [ ] 如果使用 Post Messages，请检查[**Post Message 漏洞**](/pentesting-web/postmessage-vulnerabilities.md)**。**
* [ ] 如果**内容脚本访问 DOM 详细信息**，请检查它们是否在被网页**修改**后引入了 XSS
* [ ] 特别强调如果此通信还涉及**内容脚本 -> 后台脚本通信**
* [ ] 不应将**敏感信息**存储在浏览器扩展**代码**中
* [ ] 不应将**敏感信息**存储在浏览器扩展**内存**中

## 工具

### [**Tarnish**](https://thehackerblog.com/tarnish/)

* 从提供的 Chrome 网上应用商店链接中提取任何 Chrome 扩展。
* [**manifest.json**](https://developer.chrome.com/extensions/manifest) **查看器**：简单显示扩展清单的 JSON 格式化版本。
* **指纹分析**：检测[web\_accessible\_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources)并自动生成 Chrome 扩展指纹识别 JavaScript。
* **潜在点击劫持分析**：检测具有[web\_accessible\_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources)指令设置的扩展 HTML 页面。根据页面用途，这些页面可能容易受到点击劫持攻击。
* **权限警告查看器**：显示用户尝试安装扩展时将显示的所有 Chrome 权限提示警告列表。
* **危险函数**：显示可能被攻击者利用的危险函数位置（例如 innerHTML、chrome.tabs.executeScript 等函数）。
* **入口点**：显示扩展接受用户/外部输入的位置。这对于了解扩展的表面积并寻找潜在的发送恶意数据到扩展的点很有用。
* 危险函数和入口点扫描器生成的警报包括以下内容：
* 引发警报的相关代码片段和行。
* 问题描述。
* “查看文件”按钮，可查看包含代码的完整源文件。
* 警报文件的路径。
* 警报文件的完整 Chrome 扩展 URI。
* 文件类型，如后台页面脚本、内容脚本、浏览器操作等。
* 如果易受攻击的行在 JavaScript 文件中，则包括其所包含的所有页面的路径以及这些页面的类型，以及[web\_accessible\_resource](https://developer.chrome.com/extensions/manifest/web_accessible_resources)状态。
* **内容安全策略 (CSP) 分析器和绕过检查器**：指出扩展 CSP 中的弱点，并阐明由于白名单 CDN 等原因绕过 CSP 的潜在方法。
* **已知易受攻击的库**：使用[Retire.js](https://retirejs.github.io/retire.js/)检查已知易受攻击的 JavaScript 库的使用情况。
* 下载扩展和格式化版本。
* 下载原始扩展。
* 下载扩展的美化版本（自动美化的 HTML 和 JavaScript）。
* 自动缓存扫描结果，第一次运行扩展扫描将花费大量时间。但第二次，假设扩展未更新，由于结果已缓存，几乎会立即完成。
* 可链接的报告 URL，轻松地将其他人链接到 tarnish 生成的扩展报告。

### [Neto](https://github.com/elevenpaths/neto)

Neto 项目是一个 Python 3 包，旨在分析和解开浏览器插件和扩展的隐藏功能，适用于 Firefox 和 Chrome 等知名浏览器。它自动解压打包文件，从扩展中提取这些功能，如 `manifest.json`、本地化文件夹或 JavaScript 和 HTML 源文件。

## 参考资料

* **感谢**[**@naivenom**](https://twitter.com/naivenom)**对本方法论的帮助**
* <https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing>
* <https://palant.info/2022/08/10/anatomy-of-a-basic-extension/>
* <https://palant.info/2022/08/24/attack-surface-of-extension-pages/>
* <https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/>
* <https://help.passbolt.com/assets/files/PBL-02-report.pdf>
* <https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts>
* <https://developer.chrome.com/docs/extensions/mv2/background-pages>
* <https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/>
* <https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0>

<details>

<summary><strong>从零开始学习 AWS 黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS 红队专家）</strong></a><strong>！</strong></summary>

支持 HackTricks 的其他方式：

* 如果您想看到您的**公司在HackTricks中被广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或在**Twitter**上关注我们 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hacktricks.xsx.tw/pentesting-web/browser-extension-pentesting-methodology.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
