.. | ||
browext-clickjacking.md | ||
browext-permissions-and-host_permissions.md | ||
browext-xss-example.md | ||
README.md |
Browser Extension Pentesting Methodology
Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!
Other ways to support HackTricks:
- If you want to see your company advertised in HackTricks or download HackTricks in PDF Check the SUBSCRIPTION PLANS!
- Get the official PEASS & HackTricks swag
- Discover The PEASS Family, our collection of exclusive NFTs
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @carlospolopm.
- Share your hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Basic Information
Browser extensions are written in JavaScript and loaded by the browser in the background. It has its DOM but can interact with other sites' DOMs. This means that it may compromise other sites' confidentiality, integrity, and availability (CIA).
Main Components
Extension layouts look best when visualised and consists of three components. Let’s look at each component in depth.
Content Scripts
Each content script has direct access to the DOM of a single web page and is thereby exposed to potentially malicious input. However, the content script contains no permissions other than the ability to send messages to the extension core.
Extension Core
The extension core contains most of the extension privileges/access, but the extension core can only interact with web content via XMLHttpRequest and content scripts. Also, the extension core does not have direct access to the host machine.
Native Binary
The extension allows a native binary that can access the host machine with the user’s full privileges. The native binary interacts with the extension core through the standard Netscape Plugin Application Programming Interface (NPAPI) used by Flash and other browser plug-ins.
Boundaries
{% hint style="danger" %} To obtain the user's full privileges, an attacker must convince the extension to pass malicious input from the content script to the extension's core and from the extension's core to the native binary. {% endhint %}
Each component of the extension is separated from each other by strong protective boundaries. Each component runs in a separate operating system process. Content scripts and extension cores run in sandbox processes unavailable to most operating system services.
Moreover, content scripts separate from their associated web pages by running in a separate JavaScript heap. The content script and web page have access to the same underlying DOM, but the two never exchange JavaScript pointers, preventing the leaking of JavaScript functionality.
manifest.json
A Chrome extension is just a ZIP folder with a .crx file extension. The extension's core is the manifest.json
file at the root of the folder, which specifies layout, permissions, and other configuration options.
Example:
{
"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
Content scripts are loaded whenever the user navigates to a matching page, in our case any page matching the https://example.com/*
expression and not matching the *://*/*/business*
regex. They execute like the page’s own scripts and have arbitrary access to the page’s Document Object Model (DOM).
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
include_globs
and exclude_globs
cha'logh URLs 'e' vItlhutlh.
the storage API vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh 'e' vItlhutlh 'ej 'op 'e' vItlhutlh '
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-vam vItlhutlhlaHbe'lu'chugh content script vItlhutlhlaHbe'lu'chugh button click Daq vItlhutlhlaHbe'. content script vItlhutlhlaHbe'lu'chugh API-vo' vItlhutlhlaHbe'lu'chugh limitation, 'ej storage
vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh. vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh.
{% hint style="warning" %}
browser, content script vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh. Chromium-based browsers, vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh Chrome Developers documentation, 'ej Firefox, MDN vItlhutlhlaHbe'lu'chugh.
content script vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh.
{% endhint %}
Chrome vItlhutlhlaHbe'lu'chugh, Chrome developer tools menu Options > More tools > Developer tools OR Ctrl + Shift + I vItlhutlhlaHbe'lu'chugh.
Developer tools vItlhutlhlaHbe'lu'chugh, Source tab vItlhutlhlaHbe'lu'chugh, Content Scripts tab vItlhutlhlaHbe'lu'chugh. vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh.
Injected content scripts
{% hint style="success" %}
Content Scripts vItlhutlhlaHbe'lu'chugh chay' vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh inject vItlhutlhlaHbe'lu'chugh programatically inject vItlhutlhlaHbe'lu'chugh web pages tabs.executeScript
vItlhutlhlaHbe'lu'chugh. vItlhutlhlaHbe'lu'chugh granular controls vItlhutlhlaHbe'lu'chugh.
{% endhint %}
programmatic injection vItlhutlhlaHbe'lu'chugh content script, vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh host permissions vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh. permissions vItlhutlhlaHbe'lu'chugh requesting vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh vItlhutlhlaHbe'lu'chugh activeTab vItlhutlhlaHbe'lu'chugh.
Example activeTab-based extension
{% code title="manifest.json" %}
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
{% endcode %}
-
Inject a JS file on click:
-
Inject a JS file on click:
// 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"]
});
});
-
Inject a function on click:
-
Inject a function on click:
//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,
});
});
Scripting permissions Example
Description
This example demonstrates how to exploit a browser extension that has scripting permissions enabled. By leveraging this vulnerability, an attacker can execute arbitrary code on the victim's browser, potentially leading to further compromise of the system.
Methodology
- Identify the target browser extension that has scripting permissions enabled.
- Analyze the extension's manifest file to understand its functionality and potential vulnerabilities.
- Look for any exposed endpoints or APIs that can be abused to execute arbitrary code.
- Craft a payload using a scripting language (e.g., JavaScript) to exploit the identified vulnerability.
- Inject the payload into a vulnerable endpoint or API to execute the arbitrary code.
- Verify the successful execution of the payload by observing the desired outcome (e.g., command execution, data exfiltration).
- Document the findings, including the vulnerable extension, the exploited vulnerability, and the impact of the attack.
Mitigation
To mitigate this vulnerability, consider the following measures:
- Regularly update browser extensions to ensure they are patched with the latest security fixes.
- Disable scripting permissions for extensions that do not require them.
- Implement a strong content security policy (CSP) to restrict the execution of arbitrary code within the browser.
- Educate users about the risks associated with installing untrusted browser extensions and encourage them to only use reputable sources for extensions.
References
// 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" });
Content Scripts run_at
The run_at
field controls when JavaScript files are injected into the web page. The preferred and default value is "document_idle"
.
The possible values are:
document_idle
: Whenever possibledocument_start
: After any files fromcss
, but before any other DOM is constructed or any other script is run.document_end
: Immediately after the DOM is complete, but before subresources like images and frames have loaded.
Via manifest.json
Content Scripts run_at
The run_at
field controls when JavaScript files are injected into the web page. The preferred and default value is "document_idle"
.
The possible values are:
document_idle
: Whenever possibledocument_start
: After any files fromcss
, but before any other DOM is constructed or any other script is run.document_end
: Immediately after the DOM is complete, but before subresources like images and frames have loaded.
Via manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
service-worker.js
-Da
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.example.com/*" ],
runAt : "document_idle",
js : [ "contentScript.js" ],
}]);
qorwagh
background pagewa' content scriptmey DuHIvDI' 'e' vItlhutlh. background page 'e' vItlhutlh, 'ej extension'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh
chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
{
if (request == "explain")
{
chrome.tabs.create({ url: "https://example.net/explanation" });
}
})
It uses runtime.onMessage API to listen to messages. When an "explain"
message is received, it uses tabs API to open a page in a new tab.
To debug the background script you could go to the extension details and inspect the service worker, this will open the developer tools with the background script:
Options pages and other
Browser extensions can contain various kinds of pages:
- Action pages are displayed in a drop-down when the extension icon is clicked.
- Pages that the extension will load in a new tab.
- Option Pages: This page displays on top of the extension when clicked. In the previous manifest In my case I was able to access this page in
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
or clicking:
Note that these pages aren't persistent like background pages as they load dynamically content on necessity. Despite this, they share certain capabilities with the background page:
- Communication with Content Scripts: Similar to the background page, these pages can receive messages from content scripts, facilitating interaction within the extension.
- Access to Extension-Specific APIs: These pages enjoy comprehensive access to extension-specific APIs, subject to the permissions defined for the extension.
permissions
& host_permissions
permissions
and host_permissions
are entries from the manifest.json
that will indicate which permissions the browser extensions has (storage, location...) and in which web pages.
As browser extensions can be so privileged, a malicious one or one being compromised could allow the attacker different means to steal sensitive information and spy on the user.
Check how these settings work and how thye could get abused in:
{% content-ref url="browext-permissions-and-host_permissions.md" %} browext-permissions-and-host_permissions.md {% endcontent-ref %}
content_security_policy
A content security policy can be declared also inside the manifest.json
. If there is one defined, it could be vulnerable.
The default setting for browser extension pages is rather restrictive:
script-src 'self'; object-src 'self';
For more info about CSP and potential bypasses check:
{% content-ref url="../content-security-policy-csp-bypass/" %} content-security-policy-csp-bypass {% endcontent-ref %}
web_accessible_resources
in order for a webpage to access a page of a Browser Extension, a .html
page for example, this page needs to be mentioned in the web_accessible_resources
field of the manifest.json
.
For example:
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
DaH jImej URL 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' **'e
chrome-extension://<extension-id>/message.html
ghItlhvam'e' vItlhutlh. 'Iq extension-id 'e' vItlhutlh:
'ach, manifest.json
parameter use_dynamic_url
vItlhutlh, 'Iq vItlhutlh 'e' vItlhutlh.
vItlhutlh pagh potentially vulnerable ClickJacking 'e' vItlhutlh:
{% content-ref url="browext-clickjacking.md" %} browext-clickjacking.md {% endcontent-ref %}
{% hint style="success" %} 'Iq vItlhutlh pagh extension 'ej random URLs vItlhutlh pagh CLickJacking attacks 'e' vItlhutlh. {% endhint %}
externally_connectable
Docs 'e' per 'e' manifest property "externally_connectable" vItlhutlh which extensions and web pages can connect to your extension via runtime.connect 'ej runtime.sendMessage.
- 'Iq
externally_connectable
key vItlhutlh not declared 'e' extension's manifest 'ej 'oH declared 'e'"ids": ["*"]
, all extensions can connect, but no web pages can connect. - 'Iq specific IDs vItlhutlh, like in
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, only those applications can connect. - 'Iq matches vItlhutlh, those web apps will be able to connect:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
- QaStaHvIS "externally_connectable": {} jatlh vaj web pagh ghItlh jatlh 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' 'e' **
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);
{% code title="example.js" %}
document.getElementById("theButton").addEventListener("click", () => {
window.postMessage(
{type : "FROM_PAGE", text : "Hello from the webpage!"}, "*");
}, false);
{% endcode %}
'Ivqu' Post Message communication qaStaHvIS check 'e' received message, ghaH can be done checking:
event.isTrusted
: qaStaHvIS True 'e' 'e' triggered 'e' user action- content script qaStaHvIS expecting 'e' message qaStaHvIS user performs 'e' action
- origin domain: qaStaHvIS expecting 'e' message qaStaHvIS allowlist 'e' domains.
- regex 'e' used, be very careful
- Source:
received_message.source !== window
qaStaHvIS used check message 'e' same window Content Script listening.
previous checks, even qaStaHvIS, could be vulnerable, so check following page potential Post Message bypasses:
{% content-ref url="../postmessage-vulnerabilities/" %} postmessage-vulnerabilities {% endcontent-ref %}
Iframe
Another possible way communication might be through Iframe URLs, can find example 'e':
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
DOM
This isn't "exactly" communication way, 'ach web content script 'e' access web DOM. So, 'ach content script reading information 'e', trusting web DOM, web could modify data (because web shouldn't be trusted, 'ach web vulnerable XSS) compromise Content Script.
can also find example DOM based XSS compromise browser extension 'e':
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
Sensitive Information Memory/Code
'ach Browser Extension stores sensitive information inside memory, qaStaHvIS dumped (specially Windows machines) searched 'e' information.
Therefore, memory Browser Extension qaStaHvIS considered secure sensitive information credentials mnemonic phrases qaStaHvIS stored.
'ach, not put sensitive information code, 'ach 'e' public.
Content Script ↔︎ Background Script Communication
Content Script 'e' use functions runtime.sendMessage() 'ej tabs.sendMessage() send one-time JSON-serializable message.
handle response, use returned Promise. Although, backward compatibility, 'ach 'e' pass callback 'e' last argument.
Sending request 'e' content script looks 'e':
(async () => {
const response = await chrome.runtime.sendMessage({greeting: "hello"});
// do something with response here, not outside the function
console.log(response);
})();
extension (ghItlh) vItlhutlh. (background script) vItlhutlh'e'. Content Script vItlhutlh'e' vItlhutlh'e', 'ej vaj vItlhutlh'e' vItlhutlh'e' vItlhutlh'e'. vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhutlh'e' vItlhut
// 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);
})();
Qa'legh ghItlh receiving end DaH runtime.onMessage event listener set up nIvbogh. content script extension page DaH ghItlh vItlhutlh.
// 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"});
}
);
In the example highlighted, sendResponse()
was executed in a synchronous fashion. To modify the onMessage
event handler for asynchronous execution of sendResponse()
, it's imperative to incorporate return true;
.
An important consideration is that in scenarios where multiple pages are set to receive onMessage
events, the first page to execute sendResponse()
for a specific event will be the only one able to deliver the response effectively. Any subsequent responses to the same event will not be taken into account.
When crafting new extensions, the preference should be towards promises as opposed to callbacks. Concerning the use of callbacks, the sendResponse()
function is considered valid only if it's executed directly within the synchronous context, or if the event handler indicates an asynchronous operation by returning true
. Should none of the handlers return true
or if the sendResponse()
function is removed from memory (garbage-collected), the callback associated with the sendMessage()
function will be triggered by default.
Loading an Extension in the Browser
- Download the Browser Extension & unzipped
- Go to
chrome://extensions/
and enable theDeveloper Mode
- Click the
Load unpacked
button
In Firefox you go to about:debugging#/runtime/this-firefox
and click Load Temporary Add-on
button.
Getting the source code from the store
The source code of a Chrome extension can be obtained through various methods. Below are detailed explanations and instructions for each option.
Download Extension as ZIP via Command Line
The source code of a Chrome extension can be downloaded as a ZIP file using the command line. This involves using curl
to fetch the ZIP file from a specific URL and then extracting the contents of the ZIP file to a directory. Here are the steps:
- Replace
"extension_id"
with the actual ID of the extension. - Execute the following commands:
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 website lo'QeD
CRX Viewer extension lo'QeD
Chrome Extension Source Viewer lo'QeD, 'oH open-source project. 'oH Chrome Web Store laH. viewer source code GitHub repository available.
locally installed extension source HIq
Chrome extensions locally HIqDaq inspect. vaj:
- 'ej 'oH chrome local profile directory laH 'ej "Profile Path" field DaH jImej.
- profile HIqDaq 'ej 'oH
Extensions/
subfolder. - 'ej folder Hoch installed extensions, typically readable format source code.
extensions, 'oH ghaH 'oH, 'ej names IDs map:
- Enable Developer Mode 'oH
about:extensions
page IDs each extension QaQ. - Hoch extension folder,
manifest.json
file readablename
field, Hoch extension QaQ.
File Archiver or Unpacker lo'QeD
Chrome Web Store HIqDaq extension download. file .crx
extension HIqDaq vItlhutlh.
file extension .crx
HIqDaq .zip
HIqDaq vItlhutlh.
file archiver (WinRAR, 7-Zip, etc.) HIqDaq ZIP file contents extract.
Developer Mode in Chrome lo'QeD
Chrome HIqDaq 'ej 'oH chrome://extensions/
laH.
"Developer mode" enable top right.
"Load unpacked extension..." click.
extension HIqDaq directory navigate.
vItlhutlh source code download, 'ach 'oH vItlhutlhDaq 'ej modification code HIqDaq vItlhutlhDaq.
Security Audit Checklist
Browser Extensions limited attack surface HIqDaq, 'ach chenmoH vulnerabilities 'ej potential hardening improvements HIqDaq. 'ej Hoch 'oH:
permissions
requested limit 'ej as much as possiblehost_permissions
requested limit 'ej as much as possiblecontent_security_policy
strong useexternally_connectable
limit 'ej as much as possible, 'ej none 'e' vItlhutlhDaq 'ej possible,{}
specify- URL vulnerable to XSS or to takeover mentioned, attacker send messages to the background scripts directly able. bypass powerful.
web_accessible_resources
limit 'ej as much as possible, 'ej empty 'e' vItlhutlhDaq 'ej possible.web_accessible_resources
none 'e' vItlhutlhDaq, ClickJacking check- communication extension web page Hoch, check for XSS vulnerabilities caused communication.
- Post Messages 'e' vItlhutlhDaq, Post Message vulnerabilities check.
- Content Script access DOM details, Hoch aren't introducing a XSS 'e' vItlhutlhDaq modified web
- 'ej 'oH communication Content Script -> Background script communication Hoch emphasis
- Sensitive information shouldn't be stored Browser Extension code Hoch
- Sensitive information shouldn't be stored Browser Extension memory Hoch
Tools
Tarnish
- Chrome webstore link provided Chrome extension Pulls.
- manifest.json viewer: simply displays a JSON-prettified version of the extension’s manifest.
- Fingerprint Analysis: Detection of web_accessible_resources and automatic generation of Chrome extension fingerprinting JavaScript.
- Potential Clickjacking Analysis: Detection of extension HTML pages with the web_accessible_resources directive set. These are potentially vulnerable to clickjacking depending on the purpose of the pages.
- Permission Warning(s) viewer: which shows a list of all the Chrome permission prompt warnings which will be displayed upon a user attempting to install the extension.
- Dangerous Function(s): shows the location of dangerous functions which could potentially be exploited by an attacker (e.g. functions such as innerHTML, chrome.tabs.executeScript).
- Entry Point(s): shows where the extension takes in user/external input. This is useful for understanding an extension’s surface area and looking for potential points to send maliciously-crafted data to the extension.
- Both the Dangerous Function(s) and Entry Point(s) scanners have the following for their generated alerts:
- Relevant code snippet and line that caused the alert.
- Description of the issue.
- A “View File” button to view the full source file containing the code.
- The path of the alerted file.
- The full Chrome extension URI of the alerted file.
- The type of file it is, such as a Background Page script, Content Script, Browser Action, etc.
- If the vulnerable line is in a JavaScript file, the paths of all of the pages where it is included as well as these page’s type, and web_accessible_resource status.
- Content Security Policy (CSP) analyzer and bypass checker: This will point out weaknesses in your extension’s CSP and will also illuminate any potential ways to bypass your CSP due to whitelisted CDNs, etc.
- Known Vulnerable Libraries: This uses Retire.js to check for any usage of known-vulnerable JavaScript libraries.
- Download extension and formatted versions.
- Download the original extension.
- Download a beautified version of the extension (auto prettified HTML and JavaScript).
- Automatic caching of scan results, running an extension scan will take a good amount of time the first time you run it. However the second time, assuming the extension hasn’t been updated, will be almost instant due to the results being cached.
- Linkable Report URLs, easily link someone else to an extension report generated by tarnish.
Neto
Project Neto 'oH Python 3 package conceived to analyse and unravel hidden features of browser plugins and extensions for well-known browsers such as Firefox and Chrome. It automates the process of unzipping the packaged files to extract these features from relevant resources in a extension like manifest.json
, localization folders or Javascript and HTML source files.
References
- Thanks to @naivenom for the help with this methodology
- 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](https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb
- HackTricks vItlhutlh company advertise want If or PDF in download to SUBSCRIPTION PLANS Check!
- PEASS & HackTricks official swag Get The PEASS Family Discover exclusive collection our of NFTs
- Join 💬 Discord group or telegram group or follow us on Twitter 🐦 @carlospolopm.
- Share your hacking tricks by PRs submitting tricks hacking your Share HackTricks and HackTricks Cloud github the to by submitting PRs