hacktricks/pentesting-web/browser-extension-pentesting-methodology
2024-07-31 09:35:42 +00:00
..
browext-clickjacking.md Translated ['pentesting-web/browser-extension-pentesting-methodology/REA 2024-07-19 15:59:20 +00:00
browext-permissions-and-host_permissions.md Translated ['pentesting-web/browser-extension-pentesting-methodology/REA 2024-07-19 15:59:20 +00:00
browext-xss-example.md Translated ['generic-methodologies-and-resources/basic-forensic-methodol 2024-07-19 10:11:43 +00:00
README.md Translated ['pentesting-web/browser-extension-pentesting-methodology/REA 2024-07-31 09:35:42 +00:00

Browser Extension Pentesting Methodology

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

基本信息

浏览器扩展是用 JavaScript 编写的,并由浏览器在后台加载。它有自己的 DOM,但可以与其他网站的 DOM 进行交互。这意味着它可能会危害其他网站的机密性、完整性和可用性CIA

主要组件

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

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

内容脚本

每个内容脚本可以直接访问 单个网页 的 DOM因此暴露于 潜在的恶意输入。然而,内容脚本除了能够向扩展核心发送消息外,没有其他权限。

扩展核心

扩展核心包含大部分扩展权限/访问,但扩展核心只能通过 XMLHttpRequest 和内容脚本与网页内容进行交互。此外,扩展核心无法直接访问主机机器。

本地二进制

扩展允许一个本地二进制文件,可以 以用户的完全权限访问主机机器。 本地二进制通过 Flash 和其他浏览器插件使用的标准 Netscape 插件应用程序编程接口 (NPAPI) 与扩展核心进行交互。

边界

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

扩展的每个组件之间由 强保护边界 隔开。每个组件在 单独的操作系统进程 中运行。内容脚本和扩展核心在 沙箱进程 中运行,这些进程对大多数操作系统服务不可用。

此外,内容脚本通过 在单独的 JavaScript 堆中运行 与其关联的网页分开。内容脚本和网页可以 访问相同的底层 DOM,但两者 从不交换 JavaScript 指针,防止 JavaScript 功能的泄露。

manifest.json

Chrome 扩展只是一个带有 .crx 文件扩展名 的 ZIP 文件夹。扩展的核心是位于文件夹根部的 manifest.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)具有任意访问权限。

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

为了包含或排除更多的 URL您还可以使用 include_globsexclude_globs

这是一个示例内容脚本,当使用 存储 API 从扩展的存储中检索 message 值时,将向页面添加一个解释按钮。

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

当点击此按钮时,通过利用runtime.sendMessage() API内容脚本向扩展页面发送消息。这是由于内容脚本在直接访问API方面的限制storage是少数例外之一。对于超出这些例外的功能,消息被发送到扩展页面,内容脚本可以与之通信。

{% hint style="warning" %} 根据浏览器的不同内容脚本的能力可能会略有不同。对于基于Chromium的浏览器能力列表可在Chrome Developers documentation中找到而对于FirefoxMDN是主要来源。
值得注意的是,内容脚本能够与后台脚本进行通信,使其能够执行操作并传递响应。 {% endhint %}

要在Chrome中查看和调试内容脚本可以通过选项 > 更多工具 > 开发者工具访问Chrome开发者工具菜单或按Ctrl + Shift + I。

当开发者工具显示后,点击选项卡,然后点击内容脚本选项卡。这允许观察来自各种扩展的运行内容脚本,并设置断点以跟踪执行流程。

注入的内容脚本

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

对于内容脚本的程序化注入,扩展需要对要注入脚本的页面具有主机权限。这些权限可以通过在扩展的清单中请求它们或通过activeTab临时获取。

示例 activeTab 基础扩展

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

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

{% endcode %}

  • 点击时注入一个JS文件
// 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"]
});
});
  • 在点击时注入一个函数:
//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,
});
});

示例与脚本权限

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

内容脚本 run_at

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

可能的值有:

  • document_idle:尽可能地
  • document_start:在任何 css 文件之后,但在构建任何其他 DOM 或运行任何其他脚本之前。
  • document_end:在 DOM 完成后立即,但在子资源(如图像和框架)加载之前。

通过 manifest.json

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

通过 service-worker.js

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

background

由内容脚本发送的消息由背景页面接收背景页面在协调扩展的组件中发挥着核心作用。值得注意的是背景页面在扩展的整个生命周期中持续存在默默运行而无需直接用户交互。它拥有自己的文档对象模型DOM能够实现复杂的交互和状态管理。

关键点

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

{% hint style="success" %} 浏览器在自动生成背景页面(当未明确声明时)所提供的便利,确保所有必要的背景脚本都被集成并正常运行,从而简化了扩展的设置过程。 {% endhint %}

示例背景脚本:

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

它使用 runtime.onMessage API 来监听消息。当接收到 "explain" 消息时,它使用 tabs API 在新标签页中打开一个页面。

要调试后台脚本,您可以转到 扩展详细信息并检查服务工作者, 这将打开带有后台脚本的开发者工具:

选项页面和其他

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

  • 操作页面 在点击扩展图标时显示在 下拉菜单中
  • 扩展将 在新标签页中加载的页面
  • 选项页面:此页面在点击时显示在扩展顶部。在之前的清单中,我能够通过 chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca 访问此页面,或点击:

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

  • 与内容脚本的通信: 类似于后台页面,这些页面可以接收来自内容脚本的消息,促进扩展内的交互。
  • 访问扩展特定的 API 这些页面享有对扩展特定 API 的全面访问,受扩展定义的权限限制。

permissions & host_permissions

permissionshost_permissionsmanifest.json 中的条目,指示 浏览器扩展具有哪些权限(存储、位置等)以及 在哪些网页上

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

检查这些设置如何工作以及它们如何被滥用:

{% content-ref url="browext-permissions-and-host_permissions.md" %} browext-permissions-and-host_permissions.md {% endcontent-ref %}

content_security_policy

内容安全策略 也可以在 manifest.json 中声明。如果定义了内容安全策略,它可能是 脆弱的

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

script-src 'self'; object-src 'self';

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

{% content-ref url="../content-security-policy-csp-bypass/" %} content-security-policy-csp-bypass {% endcontent-ref %}

web_accessible_resources

为了让网页访问浏览器扩展的页面,例如一个.html页面,该页面需要在manifest.json的**web_accessible_resources**字段中提到。
例如:

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

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

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

在公共扩展中,extension-id 是可访问的

不过,如果使用 manifest.json 参数 use_dynamic_url,则该 id 可能是动态的

{% hint style="success" %} 请注意,即使此处提到某个页面,它也可能由于 内容安全策略受到 ClickJacking 保护。因此,在确认 ClickJacking 攻击是否可能之前您还需要检查它frame-ancestors 部分)。 {% endhint %}

允许访问这些页面使这些页面 可能容易受到 ClickJacking 攻击

{% content-ref url="browext-clickjacking.md" %} browext-clickjacking.md {% endcontent-ref %}

{% hint style="success" %} 仅允许这些页面由扩展加载,而不是由随机 URL 加载,可以防止 ClickJacking 攻击。 {% endhint %}

{% hint style="danger" %} 请注意,web_accessible_resources 中的页面和扩展的其他页面也能够 联系后台脚本。因此,如果这些页面中的一个容易受到 XSS 攻击,它可能会打开更大的漏洞。

此外,请注意,您只能在 iframe 中打开 web_accessible_resources 中指示的页面,但从新标签页可以访问扩展中的任何页面,只需知道扩展 ID。因此如果发现 XSS 利用相同参数,即使页面未在 web_accessible_resources 中配置,也可能被利用。 {% endhint %}

externally_connectable

根据 文档"externally_connectable" 清单属性声明 哪些扩展和网页可以通过 runtime.connectruntime.sendMessage 连接到您的扩展。

  • 如果在扩展的清单中 未声明 externally_connectable 键或声明为 "ids": ["*"]所有扩展都可以连接,但没有网页可以连接
  • 如果指定了 特定 ID,如 "ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]只有这些应用程序可以连接。
  • 如果指定了 匹配项,这些网页应用程序将能够连接:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
  • 如果指定为空:"externally_connectable": {},则没有应用程序或网页能够连接。

这里指示的扩展和URL越少攻击面就越小

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

因此,这是一个非常强大的绕过

此外,如果客户端安装了一个恶意扩展,即使它不被允许与易受攻击的扩展通信,它也可能在允许的网页中注入XSS数据,或滥用**WebRequestDeclarativeNetRequest** API来操纵目标域上的请求改变页面对JavaScript文件的请求。请注意目标页面上的CSP可能会阻止这些攻击。这个想法来自这篇文章。 {% endhint %}

通信总结

扩展 <--> WebApp

在内容脚本和网页之间,通常使用后续消息进行通信。因此,在网页应用程序中,您通常会找到对函数**window.postMessage的调用,而在内容脚本中则有像window.addEventListener这样的监听器。然而,请注意,扩展也可以通过发送Post Message与网页应用程序通信**(因此网页应该预期此情况),或者仅使网页加载一个新脚本。

在扩展内部

通常使用函数**chrome.runtime.sendMessage在扩展内部发送消息(通常由background脚本处理),为了接收和处理它,声明一个监听器调用chrome.runtime.onMessage.addListener**。

也可以使用**chrome.runtime.connect()来建立持久连接,而不是发送单个消息,可以使用它来发送接收****消息**,如下例所示:

chrome.runtime.connect() 示例 ```javascript var port = chrome.runtime.connect();

// Listen for messages from the web page window.addEventListener("message", (event) => { // Only accept messages from the same window if (event.source !== window) { return; }

// Check if the message type is "FROM_PAGE" if (event.data.type && (event.data.type === "FROM_PAGE")) { console.log("Content script received: " + event.data.text); // Forward the message to the background script port.postMessage({ type: 'FROM_PAGE', text: event.data.text }); } }, false);

// Listen for messages from the background script port.onMessage.addListener(function(msg) { console.log("Content script received message from background script:", msg); // Handle the response message from the background script });

</details>

也可以从后台脚本向位于特定标签页中的内容脚本发送消息,调用 **`chrome.tabs.sendMessage`**,在此您需要指明要发送消息的 **标签页 ID**。

### 从允许的 `externally_connectable` 到扩展

在 `externally_connectable` 配置中允许的 **Web 应用程序和外部浏览器扩展** 可以使用以下方式发送请求:
```javascript
chrome.runtime.sendMessage(extensionId, ...

需要提到 extension ID 的地方。

本地消息传递

背景脚本可以与系统内的二进制文件进行通信,如果这种通信没有得到妥善保护,可能会 容易受到诸如 RCEs 的关键漏洞稍后会详细介绍

chrome.runtime.sendNativeMessage(
'com.my_company.my_application',
{text: 'Hello'},
function (response) {
console.log('Received ' + response);
}
);

Web ↔︎ 内容脚本通信

内容脚本 操作的环境与主机页面存在的环境是 分开的,确保了 隔离。尽管存在这种隔离,双方都能够与页面的 文档对象模型 (DOM) 进行交互,这是一个共享资源。为了使主机页面能够与 内容脚本 进行通信,或通过内容脚本间接与扩展进行通信,必须利用双方都可以访问的 DOM 作为通信通道。

发送消息

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

安全的 Post Message 通信应检查接收消息的真实性,这可以通过以下方式进行检查:

  • event.isTrusted:只有当事件是由用户操作触发时,这个值才为 True
  • 内容脚本可能只在用户执行某些操作时才期待接收到消息
  • origin domain:可能只允许白名单中的域名接收消息。
  • 如果使用正则表达式,请非常小心
  • Sourcereceived_message.source !== window 可用于检查消息是否来自 同一窗口,即内容脚本正在监听的窗口。

即使执行了上述检查,仍可能存在漏洞,因此请查看以下页面 潜在的 Post Message 绕过

{% content-ref url="../postmessage-vulnerabilities/" %} postmessage-vulnerabilities {% endcontent-ref %}

Iframe

另一种可能的通信方式可能是通过 Iframe URLs,您可以在以下位置找到示例:

{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}

DOM

这并不是“确切的”通信方式,但 网页和内容脚本将可以访问网页 DOM。因此,如果 内容脚本 从中读取某些信息,信任网页 DOM,网页可能会 修改这些数据(因为网页不应被信任,或因为网页易受 XSS 攻击)并 危害内容脚本

您还可以在以下位置找到一个 基于 DOM 的 XSS 以危害浏览器扩展 的示例:

{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}

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

内容脚本可以使用 runtime.sendMessage() tabs.sendMessage() 发送 一次性 JSON 可序列化 消息。

要处理 响应,请使用返回的 Promise。尽管为了向后兼容,您仍然可以将 回调 作为最后一个参数传递。

内容脚本 发送请求的方式如下:

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

扩展(通常是后台脚本)发送请求。以下是如何向选定标签页中的内容脚本发送消息的示例:

// 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 事件监听器 来处理消息。这在内容脚本或扩展页面中看起来是一样的。

// 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() 函数关联的回调将默认被触发。

Native Messaging

浏览器扩展还允许通过 stdin 与系统中的 二进制文件 进行通信。应用程序必须安装一个 json 来指示这一点,格式如下:

{
"name": "com.my_company.my_application",
"description": "My Application",
"path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
"type": "stdio",
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
}
其中 `name` 是传递给 [`runtime.connectNative()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-connectNative) 或 [`runtime.sendNativeMessage()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendNativeMessage) 的字符串,用于从浏览器扩展的后台脚本与应用程序进行通信。`path` 是二进制文件的路径,只有 1 个有效的 `type`,即 stdio使用 stdin 和 stdout`allowed_origins` 表示可以访问它的扩展(不能使用通配符)。

Chrome/Chromium 会在某些 Windows 注册表和 macOS 和 Linux 的某些路径中搜索此 json更多信息请参见 [**docs**](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging))。

{% hint style="success" %}
浏览器扩展还需要声明 `nativeMessaing` 权限,以便能够使用此通信。
{% endhint %}

这就是一些后台脚本代码向本地应用程序发送消息的样子:
chrome.runtime.sendNativeMessage(
'com.my_company.my_application',
{text: 'Hello'},
function (response) {
console.log('Received ' + response);
}
);

这篇博客文章中,提出了一种利用本机消息的脆弱模式:

  1. 浏览器扩展对内容脚本有一个通配符模式。
  2. 内容脚本使用sendMessagepostMessage消息传递给后台脚本。
  3. 后台脚本使用sendNativeMessage将消息传递给本机应用程序。
  4. 本机应用程序以危险的方式处理消息,导致代码执行。

在其中,解释了如何从任何页面利用浏览器扩展进行RCE的示例。

内存/代码/剪贴板中的敏感信息

如果浏览器扩展将敏感信息存储在其内存中,则可能会被转储特别是在Windows机器上搜索这些信息。

因此,浏览器扩展的内存不应被视为安全,并且敏感信息如凭据或助记短语不应存储

当然,不要将敏感信息放入代码中,因为它将是公开的

要从浏览器转储内存,您可以转储进程内存,或者要进入浏览器扩展的设置,点击**Inspect pop-up** -> 在**Memory部分 -> Take a snapshot,然后使用CTRL+F**在快照中搜索敏感信息。

此外,像助记密钥或密码这样的高度敏感信息不应允许复制到剪贴板(或至少在几秒钟内将其从剪贴板中移除),因为这样监控剪贴板的进程将能够获取它们。

在浏览器中加载扩展

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

Firefox中,您转到**about:debugging#/runtime/this-firefox并点击加载临时附加组件**按钮。

从商店获取源代码

Chrome扩展的源代码可以通过多种方法获得。以下是每个选项的详细说明和指示。

通过命令行将扩展下载为ZIP

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

  1. "extension_id"替换为扩展的实际ID。
  2. 执行以下命令:
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 Web Store 安装。查看器的源代码可在其 GitHub 仓库 中找到。

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

本地安装的 Chrome 扩展也可以进行检查。方法如下:

  1. 通过访问 chrome://version/ 并找到“Profile Path”字段来访问您的 Chrome 本地配置文件目录。
  2. 在配置文件目录中导航到 Extensions/ 子文件夹。
  3. 此文件夹包含所有已安装的扩展,通常其源代码以可读格式存放。

要识别扩展,您可以将其 ID 映射到名称:

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

使用文件归档程序或解压缩工具

前往 Chrome Web Store 下载扩展。文件将具有 .crx 扩展名。将文件扩展名从 .crx 更改为 .zip。使用任何文件归档程序(如 WinRAR、7-Zip 等)提取 ZIP 文件的内容。

在 Chrome 中使用开发者模式

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

Chrome 扩展清单数据集

为了尝试发现易受攻击的浏览器扩展,您可以使用 https://github.com/palant/chrome-extension-manifests-dataset 并检查其清单文件以寻找潜在的脆弱迹象。例如,检查用户超过 25000 的扩展,content_scripts 和权限 nativeMessaing

{% code overflow="wrap" %}

# Query example from https://spaceraccoon.dev/universal-code-execution-browser-extensions/
node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.length > 0 && manifest.permissions?.includes('nativeMessaging')"

{% endcode %}

安全审计检查清单

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

  • 尽可能限制请求的**permissions**
  • 尽可能限制****host_permissions
  • 使用的**content_security_policy**
  • 尽可能限制****externally_connectable,如果不需要且可能,请不要默认留空,指定**{}**
  • 如果这里提到的URL易受XSS或接管攻击,攻击者将能够直接向后台脚本发送消息。非常强大的绕过方式。
  • 尽可能限制****web_accessible_resources,如果可能,甚至留空。
  • 如果**web_accessible_resources**不为空,请检查ClickJacking
  • 如果扩展网页之间发生任何通信,请检查XSS 漏洞
  • 如果使用了Post Messages请检查Post Message漏洞
  • 如果内容脚本访问DOM细节,请检查它们是否在被网页修改引入XSS
  • 如果此通信也涉及内容脚本 -> 后台脚本通信,请特别强调。
  • 如果后台脚本通过本机消息传递进行通信,请检查通信是否安全且经过清理。
  • 敏感信息不应存储在浏览器扩展代码中。
  • 敏感信息不应存储在浏览器扩展内存中。
  • 敏感信息不应存储文件系统中未加保护

工具

Tarnish

  • 从提供的Chrome网上应用店链接中提取任何Chrome扩展。
  • manifest.json 查看器简单地显示扩展的manifest的JSON美化版本。
  • 指纹分析:检测web_accessible_resources并自动生成Chrome扩展指纹JavaScript。
  • 潜在的Clickjacking分析:检测设置了web_accessible_resources指令的扩展HTML页面。这些页面可能会受到Clickjacking的攻击具体取决于页面的目的。
  • 权限警告查看器显示用户尝试安装扩展时将显示的所有Chrome权限提示警告的列表。
  • 危险函数显示可能被攻击者利用的危险函数的位置例如innerHTML、chrome.tabs.executeScript等函数
  • 入口点:显示扩展接收用户/外部输入的位置。这对于理解扩展的表面区域和寻找潜在的恶意数据发送点非常有用。
  • 危险函数和入口点扫描器生成的警报包含以下内容:
  • 相关代码片段和导致警报的行。
  • 问题描述。
  • “查看文件”按钮以查看包含代码的完整源文件。
  • 警报文件的路径。
  • 警报文件的完整Chrome扩展URI。
  • 文件类型,例如后台页面脚本、内容脚本、浏览器操作等。
  • 如果易受攻击的行在JavaScript文件中包含所有包含该行的页面的路径以及这些页面的类型和web_accessible_resource状态。
  • 内容安全策略CSP分析器和绕过检查器这将指出扩展CSP中的弱点并将揭示由于白名单CDN等原因绕过CSP的潜在方法。
  • 已知漏洞库:使用Retire.js检查是否使用了已知漏洞的JavaScript库。
  • 下载扩展和格式化版本。
  • 下载原始扩展。
  • 下载美化版本的扩展自动美化的HTML和JavaScript
  • 扫描结果的自动缓存,第一次运行扩展扫描将花费相当多的时间。然而,第二次运行时,假设扩展没有更新,将几乎是瞬时的,因为结果被缓存。
  • 可链接的报告URL轻松将其他人链接到由Tarnish生成的扩展报告。

Neto

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

参考文献

{% hint style="success" %} 学习和实践AWS黑客技术HackTricks培训AWS红队专家ARTE
学习和实践GCP黑客技术HackTricks培训GCP红队专家GRTE

支持HackTricks
{% endhint %}