Browser Extensions are features that allow users to customize and expand the functionality of web browsers. Major browsers like Chrome, Safari, Firefox, and Edge all support them, and Chrome-based browsers (Brave, Whale, etc.) also support extensions.
This document outlines methods for testing and finding security vulnerabilities in Browser Extensions.
Structure
Chrome/Firefox Extension
Chrome and Firefox fundamentally share the same Extension structure, leading to the existence of mutually compatible Extensions. However, as versions advance, they increasingly adopt slightly different processing structures, often leading to incompatibility.
Safari App Extension
Unlike Web Extensions used in Chrome and Firefox, Safari app extensions are applications built with Swift code. While their internal composition is quite different, they ultimately control parts of the DOM with JavaScript and HTML, allowing for similar testing methods as described below.
Safari Web Extension
Safari Web Extension is the same type of Extension as Web Extensions used in Chrome/Firefox. The way to distinguish between App Extension and Web Extension is by installation method.
- App Extension: Installed only through the AppStore
- Web Extension: File-based installation, similar to Chrome
API Documents
- Chrome: https://developer.chrome.com/docs/extensions/reference/
- Firefox: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions
- Safari - App Extension: https://developer.apple.com/documentation/safariservices/safari_app_extensions - Web Extension: https://developer.apple.com/documentation/safariservices/safari_web_extensions
Hack Mechanism
Although the internal operation methods differ for each browser, the scope of what they ultimately perform is similar. Therefore, you can test and find security issues in all browser extensions in a similar manner.
Code audit
Browser extensions are essentially ZIP files, so you can download them, extract them, and examine the source code and resources. However, since the stores do not directly provide the files, you need to use a small trick to locate them.
Find source code
Chrome extensions are saved in the following paths upon installation:
- MacOS:
~/Library/Application\ Support/Google/Chrome/Default/Extensions
- Linux:
~/.config/google-chrome/Default/Extensions/
- Windows:
C:\Users\<Your_User_Name>\AppData\Local\Google\Chrome\User Data\Default\Extensions
In this directory, you will find folders named after the extension's key.
ll ~/Library/Application\ Support/Google/Chrome/Default/Extensions
# drwx------@ 2 hahwul staff 64B 12 24 00:37 Temp
# drwx------@ 3 hahwul staff 96B 9 29 2019 aapocclcgogkmnckokdopfmhonfmgoek
# drwx------@ 3 hahwul staff 96B 9 29 2019 aohghmighlieiainnegkcijnfilokake
# drwx------@ 3 hahwul staff 96B 11 14 18:39 apdfllckaahabafndbhieahigkjlhalf
# drwx------@ 3 hahwul staff 96B 7 12 00:48 baacjfeencnlcclennchejfnbcplfmbb
# drwx------@ 3 hahwul staff 96B 7 9 00:53 phbjaiacjbplfmapmlljdoacomhbpfoe
The extension's key can be found on the Chrome extensions page.
Once you've found the files, you can copy them to an analysis directory and proceed with your work.
cp -r ~/Library/Application\ Support/Google/Chrome/Default/Extensions/phbjaiacjbplfmapmlljdoacomhbpfoe .
Manifest
Browser extensions typically declare most of their policies and permissions in the manifest.json
file. Check this file to understand the allowed policies and identify any misconfigured settings.
{
"author": "MM3Tools",
"background": {
"scripts": [ "util.js", "ProxySwitch.js" ]
},
"browser_action": {
"browser_style": true,
"default_icon": {
"16": "img/MM3_16off.png",
"32": "img/MM3_32off.png"
},
"default_popup": "popup.html"
},
"commands": {
"ProxySwitch-1": {
"description": "1",
"suggested_key": {
"default": "Ctrl+Shift+1"
}
},
"ProxySwitch-2": {
"description": "2",
"suggested_key": {
"default": "Ctrl+Shift+2"
}
},
"ProxySwitch-3": {
"description": "3",
"suggested_key": {
"default": "Ctrl+Shift+3"
}
},
"ProxySwitch-4": {
"description": "4",
"suggested_key": {
"default": "Ctrl+Shift+4"
}
}
},
"default_locale": "en",
"description": "__MSG_appDescription__",
"icons": {
"48": "img/MM3_48.png",
"96": "img/MM3_96.png"
},
"key": "...snip...",
"manifest_version": 2,
"name": "MM3-ProxySwitch",
"options_ui": {
"open_in_tab": true,
"page": "setting.html"
},
"permissions": [ "storage", "proxy", "BrowseData", "http://*/*", "https://*/*" ],
"short_name": "ProxySwitch",
"update_url": "https://clients2.google.com/service/update2/crx",
"version": "2018.332"
}
*For each permission, please refer to https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions!
Source code
The source code within the extension directory consists of the actual code used for operation. This includes markup for rendering pages like popup.html
, as well as JavaScript files containing the actual logic. Examine these codes for exposed sensitive values (secrets, keys, etc.) and for any inputs that can be received from external sources.
Key areas to look at are:
- postMessage
- SSE
- webSocket
- wasm
- API Call (ajax, xmlhttprequest, etc..)
- localStorage / sessionStorage
Live audit
Test with devtools
Extensions operate in a separate DOM from web pages. While you can open DevTools for regular web pages, extensions might not provide a view or might be difficult to trigger a view depending on the code. In such cases, you can open the DOM area using the following method:
Options > Extensions > Target Extension > Inspect views
Once you've loaded the page by inspecting the view, each JavaScript file in the background will already be loaded, allowing you to test it through the DevTools console or debugger. Function information can be found by filtering the source code you're analyzing with cat
and grep
.
cat util.js
"use strict";function err(ex){if(ex!=null)console.error(ex,ex.message,chrome.runtime.lastError);else console.error(chrome.runtime.lastError);}function myParseInt(value){try{value=value.trim();if(/^(\-|\+)?([0-9]+|Infinity)$/.test(value))return Number(value);}catch(ex){err(ex);}return NaN;}function hostM(host,isProxy){try{let hp={};let i=host.lastIndexOf(':');if(i!=-1){hp.port=host.substring(i+1);let em=null;if(hp.port.length==0)em=chrome.i18n.getMessage('notSpecified');else{let n=myParseInt(hp.port);if(isNaN(n))
chrome-extension
If the extension provides a view, such as popup.html
, you can also directly access it and test it via chrome-extension://
as shown in the image below.
In such cases, it is much more convenient as you can test while visually observing the actual behavior. Note that the chrome-extension://
protocol can also become a testing point if the popup or other pages process values through query parsing.
chrome-extension://vulnapp/landing?c=};alert(45);function a(){//
User input
Although browser extensions operate as web pages with their own DOM, isolated from the general Browse area, they can communicate with web pages, APIs, and process data within the DOM through various features like postMessage
and SSE. This means that browser extensions are also susceptible to web vulnerabilities, just like regular web pages.
Testing should be conducted on the endpoints identified through source code analysis.
- https://www.hahwul.com/2020/05/14/vulnerability-of-postmessage/
- https://www.hahwul.com/2016/08/29/web-hacking-html5-postmessage-api/
A major weakness
Sensitive Data Leak
Depending on the extension's functionality, it may contain sensitive information internally. If this information can be exfiltrated externally via postMessage
or similar methods, it becomes an issue where users' critical information can be compromised.
Generally, there is much discussion about storage locations, and based on Manifest V3, it is recommended to store sensitive information in session storage.
XSS
While most web vulnerabilities are potential targets, XSS seems to be the most critical aspect to focus on. Since it involves client-side risks beyond domain-based issues, potentially leading to widespread UXSS or further attacks via Browser APIs, it appears to be a more significant area for extensions.
Bypass CSP
In browser extensions, CSP is declared in the Manifest. CSP policies can generally be bypassed using known CSP bypass techniques, which can significantly aid in increasing the risk of XSS vulnerabilities.
Javascript CVE
Naturally, as a web-based page, it is affected by publicly known JavaScript library vulnerabilities. Updates usually require package updates for the extension, so they are generally slower than web pages. This can be easily checked with tools like retire.js
.
API Security
The API server linked to the extension is a primary target for analysis. Naturally, common vulnerabilities can be found here, and because of its interconnectedness with the extension, exploiting these vulnerabilities can create vulnerabilities that affect the extension itself.
If there's a vulnerability that allows arbitrary data to be stored on the API Server, and this data acts as an XSS in the extension, it can escalate the risk, potentially leading to UXSS or attacks that leverage Browser Extension APIs.
🛠 Environment
Include WASM
If the Extension includes WASM (Web Assembly), additional analysis of WASM will be required. For more details on WASM analysis, please refer to the link below.
Inclulde SSE
If the extension uses SSE, a tool capable of handling SSE is required. Both ZAP and Burpsuite can do this; refer to the link below for more details.
Include WebSocket
If the extension uses WebSocket, a tool capable of handling WebSocket is required. Similar to SSE, both ZAP and Burpsuite can do this; refer to the link below for more details.
Articles
References
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension
- https://www.slideshare.net/OleksandrZinevych/chrome-extensions-56125231
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json
- https://developer.apple.com/documentation/safariservices/safari_web_extensions