Методологія пентестингу розширень браузера
{{#include ../../banners/hacktricks-training.md}}
Основна інформація
Розширення браузера написані на JavaScript і завантажуються браузером у фоновому режимі. Воно має свій DOM, але може взаємодіяти з DOM інших сайтів. Це означає, що воно може скомпрометувати конфіденційність, цілісність і доступність (CIA) інших сайтів.
Основні компоненти
Макети розширень виглядають найкраще, коли їх візуалізують, і складаються з трьох компонентів. Розглянемо кожен компонент детальніше.

Скрипти контенту
Кожен скрипт контенту має прямий доступ до DOM однієї веб-сторінки і, таким чином, піддається потенційно шкідливому вводу. Однак скрипт контенту не має жодних дозволів, окрім можливості надсилати повідомлення до ядра розширення.
Ядро розширення
Ядро розширення містить більшість привілеїв/доступу розширення, але ядро розширення може взаємодіяти з веб-контентом лише через XMLHttpRequest та скрипти контенту. Крім того, ядро розширення не має прямого доступу до хост-машини.
Рідний бінарний файл
Розширення дозволяє рідний бінарний файл, який може доступатися до хост-машини з повними привілеями користувача. Рідний бінарний файл взаємодіє з ядром розширення через стандартний Інтерфейс програмування додатків плагінів Netscape (NPAPI), який використовується Flash та іншими плагінами браузера.
Межі
Caution
Щоб отримати повні привілеї користувача, зловмисник повинен переконати розширення передати шкідливий ввід від скрипта контенту до ядра розширення і від ядра розширення до рідного бінарного файлу.
Кожен компонент розширення відокремлений один від одного сильними захисними межами. Кожен компонент працює в окремому процесі операційної системи. Скрипти контенту та ядра розширення працюють у пісочницях, недоступних для більшості служб операційної системи.
Більше того, скрипти контенту відокремлені від своїх асоційованих веб-сторінок, працюючи в окремій купі JavaScript. Скрипт контенту та веб-сторінка мають доступ до одного й того ж базового DOM, але двоє ніколи не обмінюються вказівниками JavaScript, що запобігає витоку функціональності JavaScript.
manifest.json
Розширення Chrome - це просто ZIP-папка з .crx розширенням файлу. Ядро розширення - це 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
Content scripts завантажуються щоразу, коли користувач переходить на відповідну сторінку, у нашому випадку на будь-яку сторінку, що відповідає виразу https://example.com/* і не відповідає регулярному виразу *://*/*/business*. Вони виконуються як власні скрипти сторінки і мають довільний доступ до Document Object Model (DOM) сторінки.
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
Щоб включити або виключити більше URL-адрес, також можна використовувати include_globs та exclude_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 є одним з небагатьох винятків. Для функціональностей, що виходять за межі цих винятків, повідомлення надсилаються на сторінки розширення, з якими можуть спілкуватися скрипти контенту.
Warning
Залежно від браузера, можливості скрипта контенту можуть трохи відрізнятися. Для браузерів на базі Chromium список можливостей доступний у документації Chrome Developers, а для Firefox основним джерелом є MDN.
Також варто зазначити, що скрипти контенту мають можливість спілкуватися зі скриптами фону, що дозволяє їм виконувати дії та передавати відповіді назад.
Для перегляду та налагодження скриптів контенту в Chrome меню інструментів розробника можна відкрити з Options > More tools > Developer tools АБО натиснувши Ctrl + Shift + I.
Після відображення інструментів розробника потрібно натиснути на Source tab, а потім на Content Scripts tab. Це дозволяє спостерігати за запущеними скриптами контенту з різних розширень і встановлювати точки зупинки для відстеження потоку виконання.
Впроваджені скрипти контенту
Tip
Зверніть увагу, що скрипти контенту не є обов'язковими, оскільки також можливо динамічно впроваджувати скрипти та програмно впроваджувати їх на веб-сторінках за допомогою
tabs.executeScript. Це насправді забезпечує більш докладний контроль.
Для програмного впровадження скрипта контенту розширення повинно мати host permissions для сторінки, на яку потрібно впровадити скрипти. Ці дозволи можуть бути отримані або запитуючи їх у маніфесті розширення, або тимчасово через activeTab.
Приклад розширення на основі activeTab
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
- Вставити 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_globs та exclude_globs.
Content Scripts run_at
Поле run_at контролює коли JavaScript файли впроваджуються на веб-сторінку. Бажане та значення за замовчуванням - це "document_idle".
Можливі значення:
document_idle: Коли це можливоdocument_start: Після будь-яких файлів зcss, але до того, як буде побудовано будь-який інший DOM або виконано будь-який інший скрипт.document_end: Негайно після завершення DOM, але до завантаження підресурсів, таких як зображення та фрейми.
Via 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), що дозволяє здійснювати складні взаємодії та управління станом.
Ключові моменти:
- Роль фонової сторінки: Виконує функцію нервового центру для розширення, забезпечуючи зв'язок і координацію між різними частинами розширення.
- Постійність: Це завжди присутній об'єкт, невидимий для користувача, але важливий для функціональності розширення.
- Автоматичне створення: Якщо не визначено явно, браузер автоматично створить фонову сторінку. Ця автоматично згенерована сторінка міститиме всі фонові скрипти, зазначені в маніфесті розширення, забезпечуючи безперебійну роботу фонових завдань розширення.
Tip
Зручність, яку надає браузер, автоматично створюючи фонову сторінку (коли не оголошено явно), забезпечує інтеграцію та функціонування всіх необхідних фонових скриптів, спрощуючи процес налаштування розширення.
Приклад фонового скрипта:
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
permissions та host_permissions є записами з manifest.json, які вказують які дозволи має розширення браузера (сховище, місцезнаходження...) і на яких веб-сторінках.
Оскільки розширення браузера можуть бути настільки привілейованими, зловмисне або скомпрометоване може дозволити зловмиснику різні способи крадіжки чутливої інформації та шпигунства за користувачем.
Перевірте, як працюють ці налаштування і як їх можна зловживати в:
{{#ref}} browext-permissions-and-host_permissions.md {{#endref}}
content_security_policy
Політику безпеки вмісту також можна оголосити всередині manifest.json. Якщо вона визначена, вона може бути вразливою.
За замовчуванням налаштування для сторінок розширення браузера є досить обмежувальними:
script-src 'self'; object-src 'self';
Для отримання додаткової інформації про CSP та потенційні обходи, перегляньте:
{{#ref}} ../content-security-policy-csp-bypass/ {{#endref}}
web_accessible_resources
щоб веб-сторінка могла отримати доступ до сторінки розширення браузера, наприклад, .html сторінки, ця сторінка повинна бути зазначена в полі web_accessible_resources файлу manifest.json.
Наприклад:
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
Ці сторінки доступні за URL, як:
chrome-extension://<extension-id>/message.html
У публічних розширеннях ідентифікатор-розширення доступний:

Однак, якщо параметр manifest.json use_dynamic_url використовується, цей ідентифікатор може бути динамічним.
Tip
Зверніть увагу, що навіть якщо сторінка згадується тут, вона може бути захищена від ClickJacking завдяки Політиці безпеки контенту. Тому вам також потрібно перевірити це (розділ frame-ancestors) перед підтвердженням можливості атаки ClickJacking.
Доступ до цих сторінок робить їх потенційно вразливими до ClickJacking:
{{#ref}} browext-clickjacking.md {{#endref}}
Tip
Дозволяючи завантажувати ці сторінки лише через розширення, а не через випадкові URL-адреси, можна запобігти атакам ClickJacking.
Caution
Зверніть увагу, що сторінки з
web_accessible_resourcesта інші сторінки розширення також можуть контактувати з фоновими скриптами. Тому, якщо одна з цих сторінок вразлива до XSS, це може відкрити більшу вразливість.Більше того, зверніть увагу, що ви можете відкривати лише сторінки, вказані в
web_accessible_resources, всередині iframe, але з нової вкладки можливо отримати доступ до будь-якої сторінки в розширенні, знаючи ідентифікатор розширення. Тому, якщо XSS виявлено, зловживаючи тими ж параметрами, це може бути використано, навіть якщо сторінка не налаштована вweb_accessible_resources.
externally_connectable
Згідно з документацією, властивість маніфесту "externally_connectable" оголошує які розширення та веб-сторінки можуть підключатися до вашого розширення через runtime.connect та runtime.sendMessage.
- Якщо ключ
externally_connectableне оголошений у маніфесті вашого розширення або він оголошений як"ids": ["*"], всі розширення можуть підключатися, але жодні веб-сторінки не можуть підключатися. - Якщо вказані конкретні ідентифікатори, як у
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], тільки ці програми можуть підключатися. - Якщо вказані збіги, ці веб-додатки зможуть підключатися:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
- Якщо вказано як порожнє:
"externally_connectable": {}, жоден додаток або веб-сайт не зможе підключитися.
Чим менше розширень і URL-адрес вказано тут, тим менша площа атаки буде.
Caution
Якщо веб-сторінка вразлива до XSS або захоплення вказана в
externally_connectable, зловмисник зможе надсилати повідомлення безпосередньо до фонового скрипта, повністю обходячи Content Script та його CSP.Отже, це дуже потужний обхід.
Більше того, якщо клієнт встановить шкідливе розширення, навіть якщо йому не дозволено спілкуватися з вразливим розширенням, воно може впроваджувати XSS дані на дозволеній веб-сторінці або зловживати
WebRequestабоDeclarativeNetRequestAPI для маніпуляції запитами на цільовому домені, змінюючи запит сторінки на JavaScript файл. (Зверніть увагу, що CSP на цільовій сторінці може запобігти цим атакам). Ця ідея походить з цього опису.
Підсумок комунікації
Розширення <--> Веб-додаток
Для комунікації між контент-скриптом і веб-сторінкою зазвичай використовуються повідомлення. Тому в веб-додатку ви зазвичай знайдете виклики функції 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`, можуть надсилати запити, використовуючи:
```javascript
chrome.runtime.sendMessage(extensionId, ...
Де потрібно згадати ідентифікатор розширення.
Native Messaging
Можливо, щоб фонові скрипти спілкувалися з двійковими файлами всередині системи, які можуть бути схильні до критичних вразливостей, таких як RCE якщо це спілкування не буде належним чином захищене. Більше про це пізніше.
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)
Web ↔︎ Content Script Communication
Середовища, в яких працюють content scripts, і де існують хост-сторінки, відокремлені одне від одного, що забезпечує ізоляцію. Незважаючи на цю ізоляцію, обидві сторони мають можливість взаємодіяти з Document Object Model (DOM) сторінки, спільним ресурсом. Щоб хост-сторінка могла взаємодіяти з content script, або опосередковано з розширенням через content script, необхідно використовувати DOM, доступний обом сторонам, як канал зв'язку.
Post Messages
// 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
)
document.getElementById("theButton").addEventListener(
"click",
() => {
window.postMessage(
{ type: "FROM_PAGE", text: "Hello from the webpage!" },
"*"
)
},
false
)
Безпечна комунікація Post Message повинна перевіряти автентичність отриманого повідомлення, це можна зробити, перевіряючи:
event.isTrusted: Це True лише якщо подія була викликана дією користувача- Контентний скрипт може очікувати повідомлення лише якщо користувач виконує якусь дію
- origin domain: може очікувати повідомлення лише з дозволеного списку доменів.
- Якщо використовується regex, будьте дуже обережні
- Source:
received_message.source !== windowможна використовувати для перевірки, чи повідомлення було з того ж вікна, де слухає Контентний Скрипт.
Попередні перевірки, навіть якщо їх виконано, можуть бути вразливими, тому перевірте на наступній сторінці потенційні обходи Post Message:
{{#ref}} ../postmessage-vulnerabilities/ {{#endref}}
Iframe
Ще один можливий спосіб комунікації може бути через Iframe URLs, ви можете знайти приклад у:
{{#ref}} browext-xss-example.md {{#endref}}
DOM
Це не "точно" спосіб комунікації, але веб і контентний скрипт матимуть доступ до веб DOM. Тому, якщо контентний скрипт читає якусь інформацію з нього, довіряючи веб DOM, веб може модифікувати ці дані (тому що веб не повинен бути довіреним, або тому що веб вразливий до XSS) і компрометувати Контентний Скрипт.
Ви також можете знайти приклад DOM-орієнтованого XSS для компрометації розширення браузера у:
{{#ref}} browext-xss-example.md {{#endref}}
Комунікація Контентного Скрипта ↔︎ Фоновий Скрипт
Контентний Скрипт може використовувати функції runtime.sendMessage() або tabs.sendMessage() для відправки одноразового JSON-серіалізованого повідомлення.
Для обробки відповіді використовуйте повернутий Promise. Хоча, для зворотної сумісності, ви все ще можете передати callback як останній аргумент.
Відправка запиту з контентного скрипта виглядає так:
;(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() для конкретної події, буде єдиною, яка зможе ефективно доставити відповідь. Будь-які подальші відповіді на ту ж подію не будуть враховані.
При створенні нових розширень слід віддавати перевагу промісам, а не зворотним викликам. Щодо використання зворотних викликів, функція sendResponse() вважається дійсною лише в тому випадку, якщо вона виконується безпосередньо в синхронному контексті або якщо обробник події вказує на асинхронну операцію, повертаючи true. Якщо жоден з обробників не повертає true або якщо функція sendResponse() видаляється з пам'яті (збирається сміття), зворотний виклик, пов'язаний з функцією sendMessage(), буде викликаний за замовчуванням.
Native Messaging
Розширення браузера також дозволяють спілкуватися з бінарними файлами в системі через stdin. Додаток повинен встановити json, що вказує на це, у форматі 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() або runtime.sendNativeMessage() для зв'язку з додатком з фонових скриптів розширення браузера. path - це шлях до бінарного файлу, є лише 1 дійсний type, який є stdio (використовуйте stdin і stdout), а allowed_origins вказує на розширення, які можуть отримати доступ до нього (і не можуть мати символи підстановки).
Chrome/Chromium буде шукати цей json у деяких реєстрах Windows і деяких шляхах у macOS і Linux (більше інформації в docs).
Tip
Розширення браузера також потребує дозволу
nativeMessaing, щоб мати можливість використовувати це спілкування.
Ось як виглядає код деякого фонового скрипта, що надсилає повідомлення до рідного додатку:
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)
У цьому блозі пропонується вразливий шаблон, що зловживає нативними повідомленнями:
- Розширення браузера має шаблон з підстановкою для контентного скрипта.
- Контентний скрипт передає повідомлення
postMessageдо фонового скрипта, використовуючиsendMessage. - Фоновий скрипт передає повідомлення до нативного додатку, використовуючи
sendNativeMessage. - Нативний додаток обробляє повідомлення небезпечно, що призводить до виконання коду.
І в ньому пояснюється приклад переміщення з будь-якої сторінки до RCE, зловживаючи розширенням браузера.
Чутлива інформація в пам'яті/коді/буфері обміну
Якщо Розширення Браузера зберігає чутливу інформацію в своїй пам'яті, її можна вивантажити (особливо на машинах з Windows) і пошукати цю інформацію.
Отже, пам'ять Розширення Браузера не повинна вважатися безпечною, і чутливу інформацію, таку як облікові дані або мнемонічні фрази, не слід зберігати.
Звичайно, не включайте чутливу інформацію в код, оскільки вона буде публічною.
Щоб вивантажити пам'ять з браузера, ви можете вивантажити пам'ять процесу або перейти до налаштувань розширення браузера, натиснувши Inspect pop-up -> У розділі Memory -> Take a snapshot і CTRL+F для пошуку чутливої інформації в знімку.
Більш того, надзвичайно чутлива інформація, така як мнемонічні ключі або паролі, не повинна дозволятися для копіювання в буфер обміну (або принаймні видаляти її з буфера обміну через кілька секунд), оскільки тоді процеси, що моніторять буфер обміну, зможуть їх отримати.
Завантаження розширення в браузері
- Завантажте Розширення Браузера та розпакуйте його.
- Перейдіть до
chrome://extensions/і увімкнітьРежим розробника. - Натисніть кнопку
Завантажити розпаковане.
У Firefox перейдіть до about:debugging#/runtime/this-firefox і натисніть кнопку Завантажити тимчасове доповнення.
Отримання вихідного коду з магазину
Вихідний код розширення Chrome можна отримати різними способами. Нижче наведені детальні пояснення та інструкції для кожного варіанту.
Завантаження розширення як ZIP через командний рядок
Вихідний код розширення Chrome можна завантажити як ZIP-файл, використовуючи командний рядок. Це передбачає використання curl для отримання ZIP-файлу з певного URL, а потім розпакування вмісту ZIP-файлу в каталог. Ось кроки:
- Замініть
"extension_id"на фактичний ID розширення. - Виконайте наступні команди:
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
Використовуйте розширення CRX Viewer
Ще один зручний метод - це використання Chrome Extension Source Viewer, який є проектом з відкритим кодом. Його можна встановити з Chrome Web Store. Код джерела переглядача доступний у його GitHub репозиторії.
Перегляд коду локально встановленого розширення
Локально встановлені розширення Chrome також можна перевірити. Ось як:
- Доступ до вашого локального профілю Chrome, відвідавши
chrome://version/і знайдіть поле "Profile Path". - Перейдіть до підпапки
Extensions/у каталозі профілю. - Ця папка містить всі встановлені розширення, зазвичай з їхнім кодом у читабельному форматі.
Щоб ідентифікувати розширення, ви можете зіставити їхні 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:
# 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')"
Перевірочний список безпеки
Навіть якщо розширення браузера має обмежену поверхню атаки, деякі з них можуть містити вразливості або потенційні поліпшення безпеки. Найбільш поширені з них:
- Обмежити запитувані
permissionsякомога більше - Обмежити
host_permissionsякомога більше - Використовувати сильну
content_security_policy - Обмежити
externally_connectableякомога більше, якщо це не потрібно і можливо, не залишайте його за замовчуванням, вкажіть{} - Якщо тут згадується URL, вразливий до XSS або захоплення, зловмисник зможе надсилати повідомлення безпосередньо до фонових скриптів. Дуже потужний обхід.
- Обмежити
web_accessible_resourcesякомога більше, навіть порожні, якщо можливо. - Якщо
web_accessible_resourcesне порожнє, перевірте на ClickJacking - Якщо відбувається будь-яка комунікація від розширення до веб-сторінки, перевірте на XSS вразливості, викликані в комунікації.
- Якщо використовуються повідомлення Post, перевірте на вразливості Post Message.
- Якщо Content Script отримує доступ до деталей DOM, перевірте, що вони не вводять XSS, якщо їх модифікують веб
- Зробіть особливий акцент, якщо ця комунікація також залучена в комунікацію Content Script -> фоновий скрипт
- Якщо фоновий скрипт спілкується через native messaging, перевірте, що комунікація є безпечною та очищеною
- Чутливу інформацію не слід зберігати всередині коду розширення браузера
- Чутливу інформацію не слід зберігати всередині пам'яті розширення браузера
- Чутливу інформацію не слід зберігати всередині файлової системи без захисту
Ризики розширення браузера
- Додаток https://crxaminer.tech/ аналізує деякі дані, такі як дозволи, які запитує розширення браузера, щоб надати рівень ризику використання розширення браузера.
Інструменти
Tarnish
- Завантажує будь-яке розширення Chrome з наданого посилання на веб-магазин Chrome.
- manifest.json переглядач: просто відображає версію JSON з форматуванням розширення.
- Аналіз відбитків: Виявлення web_accessible_resources та автоматичне генерування JavaScript для відбитків розширення Chrome.
- Аналіз потенційного Clickjacking: Виявлення HTML-сторінок розширення з директивою web_accessible_resources. Вони можуть бути вразливими до clickjacking в залежності від мети сторінок.
- Переглядач попереджень про дозволи: який показує список усіх попереджень про запити дозволів Chrome, які будуть відображені при спробі користувача встановити розширення.
- Небезпечні функції: показує місце розташування небезпечних функцій, які можуть бути потенційно використані зловмисником (наприклад, функції, такі як innerHTML, chrome.tabs.executeScript).
- Точки входу: показує, де розширення приймає вхідні дані від користувача/зовнішні дані. Це корисно для розуміння поверхні розширення та пошуку потенційних точок для надсилання зловмисно створених даних до розширення.
- Як сканери Небезпечних функцій, так і Точок входу мають наступне для своїх згенерованих сповіщень:
- Відповідний фрагмент коду та рядок, що викликав сповіщення.
- Опис проблеми.
- Кнопка "Переглянути файл" для перегляду повного вихідного файлу, що містить код.
- Шлях до сповіщеного файлу.
- Повний URI розширення Chrome сповіщеного файлу.
- Тип файлу, наприклад, скрипт фонової сторінки, скрипт контенту, дія браузера тощо.
- Якщо вразливий рядок знаходиться в JavaScript-файлі, шляхи всіх сторінок, де він включений, а також типи цих сторінок і статус web_accessible_resource.
- Аналізатор політики безпеки контенту (CSP) та перевірка обходу: Це вказуватиме на слабкі місця в CSP вашого розширення та також виявлятиме будь-які потенційні способи обходу вашого CSP через білих CDN тощо.
- Відомі вразливі бібліотеки: Це використовує Retire.js для перевірки наявності використання відомих вразливих JavaScript-бібліотек.
- Завантажити розширення та відформатовані версії.
- Завантажити оригінальне розширення.
- Завантажити покращену версію розширення (автоформатований HTML та JavaScript).
- Автоматичне кешування результатів сканування, запуск сканування розширення займе багато часу під час першого запуску. Однак під час другого запуску, якщо розширення не було оновлено, це буде майже миттєво через кешовані результати.
- Посилання на звіти, які легко посилати комусь іншому на звіт про розширення, згенерований tarnish.
Neto
Проект Neto - це пакет Python 3, призначений для аналізу та виявлення прихованих функцій плагінів і розширень браузера для відомих браузерів, таких як Firefox і Chrome. Він автоматизує процес розпакування упакованих файлів для вилучення цих функцій з відповідних ресурсів у розширенні, таких як manifest.json, папки локалізації або вихідні файли Javascript і HTML.
Посилання
- Дякуємо @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
{{#include ../../banners/hacktricks-training.md}}