Методологія пентестингу розширень браузера

Reading time: 25 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Підтримайте HackTricks

Основна інформація

Розширення браузера написані на JavaScript і завантажуються браузером у фоновому режимі. Воно має свій DOM, але може взаємодіяти з DOM інших сайтів. Це означає, що воно може скомпрометувати конфіденційність, цілісність і доступність (CIA) інших сайтів.

Основні компоненти

Макети розширень виглядають найкраще, коли їх візуалізують, і складаються з трьох компонентів. Давайте розглянемо кожен компонент детальніше.

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

Скрипти контенту

Кожен скрипт контенту має прямий доступ до DOM однієї веб-сторінки і, таким чином, піддається потенційно шкідливому вводу. Однак скрипт контенту не має жодних дозволів, окрім можливості надсилати повідомлення до ядра розширення.

Ядро розширення

Ядро розширення містить більшість привілеїв/доступу розширення, але ядро розширення може взаємодіяти з веб-контентом лише через XMLHttpRequest та скрипти контенту. Крім того, ядро розширення не має прямого доступу до хост-машини.

Рідний бінарний файл

Розширення дозволяє рідний бінарний файл, який може доступатися до хост-машини з повними привілеями користувача. Рідний бінарний файл взаємодіє з ядром розширення через стандартний Інтерфейс програмування додатків плагінів Netscape (NPAPI), який використовується Flash та іншими плагінами браузера.

Межі

caution

Щоб отримати повні привілеї користувача, зловмисник повинен переконати розширення передати шкідливий ввід від скрипта контенту до ядра розширення і від ядра розширення до рідного бінарного файлу.

Кожен компонент розширення відокремлений один від одного сильними захисними межами. Кожен компонент працює в окремому процесі операційної системи. Скрипти контенту та ядра розширення працюють у пісочницях, недоступних для більшості служб операційної системи.

Більше того, скрипти контенту відокремлені від своїх асоційованих веб-сторінок, працюючи в окремій купі JavaScript. Скрипт контенту та веб-сторінка мають доступ до одного й того ж базового DOM, але двоє ніколи не обмінюються вказівниками JavaScript, що запобігає витоку функціональності JavaScript.

manifest.json

Розширення Chrome - це просто ZIP-папка з .crx file extension. Ядро розширення - це manifest.json файл у корені папки, який вказує макет, дозволи та інші параметри конфігурації.

Приклад:

json
{
"manifest_version": 2,
"name": "My extension",
"version": "1.0",
"permissions": ["storage"],
"content_scripts": [
{
"js": ["script.js"],
"matches": ["https://example.com/*", "https://www.example.com/*"],
"exclude_matches": ["*://*/*business*"]
}
],
"background": {
"scripts": ["background.js"]
},
"options_ui": {
"page": "options.html"
}
}

content_scripts

Скрипти контенту завантажуються щоразу, коли користувач переміщується на відповідну сторінку, у нашому випадку на будь-яку сторінку, що відповідає виразу https://example.com/* і не відповідає регулярному виразу *://*/*/business*. Вони виконуються як власні скрипти сторінки і мають довільний доступ до Document Object Model (DOM) сторінки.

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

Щоб включити або виключити більше URL-адрес, також можна використовувати include_globs та exclude_globs.

Це приклад контентного скрипта, який додасть кнопку пояснення на сторінку, коли API зберігання буде використовуватися для отримання значення message з сховища розширення.

js
chrome.storage.local.get("message", (result) => {
let div = document.createElement("div")
div.innerHTML = result.message + " <button>Explain</button>"
div.querySelector("button").addEventListener("click", () => {
chrome.runtime.sendMessage("explain")
})
document.body.appendChild(div)
})

Повідомлення надсилається на сторінки розширення скриптом контенту, коли ця кнопка натискається, через використання 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

manifest.json
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
  • Впровадити JS файл при натисканні:
javascript
// content-script.js
document.body.style.backgroundColor = "orange"

//service-worker.js - Inject the JS file
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"],
})
})
  • Впровадити функцію при натисканні:
javascript
//service-worker.js - Inject a function
function injectedFunction() {
document.body.style.backgroundColor = "orange"
}

chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: injectedFunction,
})
})

Приклад з дозволами на скрипти

javascript
// service-workser.js
chrome.scripting.registerContentScripts([
{
id: "test",
matches: ["https://*.example.com/*"],
excludeMatches: ["*://*/*business*"],
js: ["contentScript.js"],
},
])

// Another example
chrome.tabs.executeScript(tabId, { file: "content_script.js" })

Щоб включити або виключити більше URL-адрес, також можна використовувати include_globs та exclude_globs.

Content Scripts run_at

Поле run_at контролює коли JavaScript файли впроваджуються на веб-сторінку. Бажане та значення за замовчуванням - це "document_idle".

Можливі значення:

  • document_idle: Коли це можливо
  • document_start: Після будь-яких файлів з css, але до того, як буде побудовано будь-який інший DOM або виконано будь-який інший скрипт.
  • document_end: Негайно після завершення DOM, але до того, як завантажаться підресурси, такі як зображення та фрейми.

Via manifest.json

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

Шляхом service-worker.js

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

background

Повідомлення, надіслані скриптами контенту, отримуються фоновою сторінкою, яка відіграє центральну роль у координації компонентів розширення. Зокрема, фонова сторінка зберігається протягом усього життя розширення, працюючи непомітно без прямої взаємодії з користувачем. Вона має власну модель об'єктів документа (DOM), що дозволяє здійснювати складні взаємодії та управління станом.

Ключові моменти:

  • Роль фонової сторінки: Виконує функцію нервового центру для розширення, забезпечуючи зв'язок і координацію між різними частинами розширення.
  • Постійність: Це завжди присутня сутність, невидима для користувача, але невід'ємна для функціональності розширення.
  • Автоматичне створення: Якщо не визначено явно, браузер автоматично створить фонову сторінку. Ця автоматично згенерована сторінка міститиме всі фонові скрипти, зазначені в маніфесті розширення, забезпечуючи безперебійну роботу фонових завдань розширення.

tip

Зручність, яку надає браузер, автоматично генеруючи фонову сторінку (коли вона не оголошена явно), забезпечує інтеграцію та функціонування всіх необхідних фонових скриптів, спрощуючи процес налаштування розширення.

Приклад фонового скрипта:

js
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, які вказують які дозволи має розширення браузера (сховище, місцезнаходження...) і на яких веб-сторінках.

Оскільки розширення браузера можуть бути настільки привілейованими, зловмисне або скомпрометоване може дозволити зловмиснику різні способи викрадення чутливої інформації та шпигунства за користувачем.

Перевірте, як працюють ці налаштування і як їх можна зловживати в:

BrowExt - permissions & host_permissions

content_security_policy

Політику безпеки вмісту також можна оголосити всередині manifest.json. Якщо вона визначена, вона може бути вразливою.

За замовчуванням налаштування для сторінок розширення браузера є досить обмежувальними:

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

Для отримання додаткової інформації про CSP та потенційні обходи, перегляньте:

Content Security Policy (CSP) Bypass

web_accessible_resources

щоб веб-сторінка могла отримати доступ до сторінки розширення браузера, наприклад, .html сторінки, ця сторінка повинна бути зазначена в полі web_accessible_resources файлу manifest.json.
Наприклад:

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

Ці сторінки доступні за URL, як:

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

У публічних розширеннях extension-id доступний:

Однак, якщо параметр manifest.json use_dynamic_url використовується, цей id може бути динамічним.

tip

Зверніть увагу, що навіть якщо сторінка згадується тут, вона може бути захищена від ClickJacking завдяки Content Security Policy. Тому вам також потрібно перевірити це (розділ frame-ancestors) перед підтвердженням можливості атаки ClickJacking.

Доступ до цих сторінок робить їх потенційно вразливими до ClickJacking:

BrowExt - ClickJacking

tip

Дозволяючи завантажувати ці сторінки лише через розширення, а не через випадкові URL, можна запобігти атакам ClickJacking.

caution

Зверніть увагу, що сторінки з web_accessible_resources та інші сторінки розширення також можуть контактувати з фоновими скриптами. Тому, якщо одна з цих сторінок вразлива до XSS, це може відкрити більшу вразливість.

Більше того, зверніть увагу, що ви можете відкривати лише сторінки, вказані в web_accessible_resources всередині iframe, але з нової вкладки можливо отримати доступ до будь-якої сторінки в розширенні, знаючи ID розширення. Тому, якщо XSS виявлено, зловживаючи тими ж параметрами, це може бути використано, навіть якщо сторінка не налаштована в web_accessible_resources.

externally_connectable

Згідно з документацією, властивість маніфесту "externally_connectable" оголошує які розширення та веб-сторінки можуть підключатися до вашого розширення через runtime.connect та runtime.sendMessage.

  • Якщо ключ externally_connectable не оголошений у маніфесті вашого розширення або він оголошений як "ids": ["*"], всі розширення можуть підключатися, але жодні веб-сторінки не можуть підключатися.
  • Якщо вказані конкретні ID, як у "ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], тільки ці програми можуть підключатися.
  • Якщо вказані збіги, ці веб-додатки зможуть підключатися:
json
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
  • Якщо вказано як порожнє: "externally_connectable": {}, жоден додаток або веб-сайт не зможе підключитися.

Чим менше розширень і URL-адрес вказано тут, тим менша площа атаки буде.

caution

Якщо веб-сторінка вразлива до XSS або захоплення вказана в externally_connectable, зловмисник зможе надсилати повідомлення безпосередньо до фонового скрипта, повністю обходячи Контентний скрипт і його CSP.

Тому це є дуже потужним обходом.

Більше того, якщо клієнт встановить шкідливе розширення, навіть якщо йому не дозволено спілкуватися з вразливим розширенням, воно може впроваджувати XSS дані на дозволеній веб-сторінці або зловживати WebRequest або DeclarativeNetRequest API для маніпуляції запитами на цільовому домені, змінюючи запит сторінки на 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
})

Також можливо надсилати повідомлення з фонового скрипта до контент-скрипта, розташованого в конкретній вкладці, викликавши chrome.tabs.sendMessage, де вам потрібно буде вказати ID вкладки, до якої потрібно надіслати повідомлення.

Від дозволених externally_connectable до розширення

Веб-додатки та зовнішні розширення браузера, дозволені в конфігурації externally_connectable, можуть надсилати запити, використовуючи:

javascript
chrome.runtime.sendMessage(extensionId, ...

Де потрібно згадати ідентифікатор розширення.

Native Messaging

Можливо, що фонові скрипти спілкуються з двійковими файлами всередині системи, які можуть бути схильні до критичних вразливостей, таких як RCE якщо це спілкування не буде належним чином захищене. More on this later.

javascript
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

content-script.js
// This is like "chrome.runtime.sendMessage" but to maintain the connection
var port = chrome.runtime.connect()

window.addEventListener(
"message",
(event) => {
// We only accept messages from ourselves
if (event.source !== window) {
return
}

if (event.data.type && event.data.type === "FROM_PAGE") {
console.log("Content script received: " + event.data.text)
// Forward the message to the background script
port.postMessage(event.data.text)
}
},
false
)
example.js
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:

PostMessage Vulnerabilities

Iframe

Ще один можливий спосіб комунікації може бути через Iframe URLs, ви можете знайти приклад у:

BrowExt - XSS Example

DOM

Це не "точно" спосіб комунікації, але веб і контент-скрипт матимуть доступ до веб DOM. Тому, якщо контент-скрипт читає якусь інформацію з нього, довіряючи веб DOM, веб може модифікувати ці дані (тому що веб не повинен бути довіреним, або тому що веб вразливий до XSS) і скомпрометувати Контент-скрипт.

Ви також можете знайти приклад DOM-орієнтованого XSS для компрометації розширення браузера у:

BrowExt - XSS Example

Комунікація Контент-скрипта ↔︎ Фоновий скрипт

Контент-скрипт може використовувати функції runtime.sendMessage() або tabs.sendMessage() для відправки одноразового JSON-серіалізованого повідомлення.

Для обробки відповіді використовуйте повернутий Promise. Хоча, для зворотної сумісності, ви все ще можете передати callback як останній аргумент.

Відправка запиту з контент-скрипта виглядає так:

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

Відправка запиту з розширення (зазвичай фоновий скрипт). Приклад того, як надіслати повідомлення до контент-скрипту у вибраній вкладці:

javascript
// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
;(async () => {
const [tab] = await chrome.tabs.query({
active: true,
lastFocusedWindow: true,
})
const response = await chrome.tabs.sendMessage(tab.id, { greeting: "hello" })
// do something with response here, not outside the function
console.log(response)
})()

На приймальному боці вам потрібно налаштувати runtime.onMessage слухача подій, щоб обробити повідомлення. Це виглядає однаково з контентного скрипта або сторінки розширення.

javascript
// From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
console.log(
sender.tab
? "from a content script:" + sender.tab.url
: "from the extension"
)
if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
})

У наведеному прикладі sendResponse() було виконано синхронно. Щоб змінити обробник події onMessage для асинхронного виконання sendResponse(), необхідно додати return true;.

Важливим моментом є те, що в ситуаціях, коли кілька сторінок налаштовані на отримання подій onMessage, перша сторінка, яка виконає sendResponse() для конкретної події, буде єдиною, яка зможе ефективно доставити відповідь. Будь-які подальші відповіді на ту ж подію не будуть враховані.

При створенні нових розширень слід віддавати перевагу промісам, а не зворотним викликам. Що стосується використання зворотних викликів, функція sendResponse() вважається дійсною лише в тому випадку, якщо вона виконується безпосередньо в синхронному контексті або якщо обробник події вказує на асинхронну операцію, повертаючи true. Якщо жоден з обробників не повертає true або якщо функція sendResponse() видаляється з пам'яті (збирається сміття), зворотний виклик, пов'язаний з функцією sendMessage(), буде викликаний за замовчуванням.

Native Messaging

Розширення браузера також дозволяють спілкуватися з бінарними файлами в системі через stdin. Додаток повинен встановити json, що вказує на це, у форматі 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 (більше інформації в документації).

tip

Розширення браузера також потребує дозволу nativeMessaing, щоб мати можливість використовувати це спілкування.

Ось як виглядає код деякого фонового скрипта, що надсилає повідомлення до рідного додатку:

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

У цьому блозі пропонується вразливий шаблон, що зловживає нативними повідомленнями:

  1. Розширення браузера має шаблон з підстановкою для контентного скрипта.
  2. Контентний скрипт передає повідомлення postMessage до фонової скрипта, використовуючи sendMessage.
  3. Фоновий скрипт передає повідомлення до нативного додатку, використовуючи sendNativeMessage.
  4. Нативний додаток обробляє повідомлення небезпечно, що призводить до виконання коду.

І в ньому пояснюється приклад переходу з будь-якої сторінки до RCE, зловживаючи розширенням браузера.

Чутлива інформація в пам'яті/коді/буфері обміну

Якщо Розширення Браузера зберігає чутливу інформацію в своїй пам'яті, це може бути вивантажено (особливо на машинах Windows) і пошукано для цієї інформації.

Отже, пам'ять Розширення Браузера не повинна вважатися безпечною, і чутлива інформація, така як облікові дані або мнемонічні фрази, не повинна зберігатися.

Звичайно, не включайте чутливу інформацію в код, оскільки вона буде публічною.

Щоб вивантажити пам'ять з браузера, ви можете вивантажити пам'ять процесу або перейти до налаштувань розширення браузера, натиснувши Перевірити спливаюче вікно -> У розділі Пам'ять -> Зробити знімок і CTRL+F для пошуку чутливої інформації в знімку.

Більш того, надзвичайно чутлива інформація, така як мнемонічні ключі або паролі, не повинна дозволятися копіювати в буфер обміну (або принаймні видаляти її з буфера обміну через кілька секунд), оскільки тоді процеси, що моніторять буфер обміну, зможуть їх отримати.

Завантаження розширення в браузері

  1. Завантажте Розширення Браузера та розпакуйте його.
  2. Перейдіть до chrome://extensions/ і увімкніть Режим розробника.
  3. Натисніть кнопку Завантажити розпаковане.

У Firefox перейдіть до about:debugging#/runtime/this-firefox і натисніть кнопку Завантажити тимчасове доповнення.

Отримання вихідного коду з магазину

Вихідний код розширення Chrome можна отримати різними способами. Нижче наведені детальні пояснення та інструкції для кожного варіанту.

Завантаження розширення як ZIP через командний рядок

Вихідний код розширення Chrome можна завантажити як ZIP-файл, використовуючи командний рядок. Це передбачає використання curl для отримання ZIP-файлу з певного URL, а потім витягнення вмісту ZIP-файлу в каталог. Ось кроки:

  1. Замініть "extension_id" на фактичний ID розширення.
  2. Виконайте наступні команди:
bash
extension_id=your_extension_id   # Replace with the actual extension ID
curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc"
unzip -d "$extension_id-source" "$extension_id.zip"

Використання сайту CRX Viewer

https://robwu.nl/crxviewer/

Використання розширення CRX Viewer

Ще один зручний метод - це використання Chrome Extension Source Viewer, який є проектом з відкритим кодом. Його можна встановити з Chrome Web Store. Код джерела переглядача доступний у його GitHub репозиторії.

Перегляд коду локально встановленого розширення

Розширення Chrome, встановлені локально, також можна перевірити. Ось як:

  1. Доступ до вашого локального профілю Chrome, відвідавши chrome://version/ і знайдіть поле "Profile Path".
  2. Перейдіть до підпапки Extensions/ у каталозі профілю.
  3. Ця папка містить всі встановлені розширення, зазвичай з їхнім кодом джерела у читабельному форматі.

Щоб ідентифікувати розширення, ви можете зіставити їхні ID з іменами:

  • Увімкніть режим розробника на сторінці about:extensions, щоб побачити ID кожного розширення.
  • У кожній папці розширення файл manifest.json містить читабельне поле name, що допомагає вам ідентифікувати розширення.

Використання архіватора або декомпресора

Перейдіть до Chrome Web Store і завантажте розширення. Файл матиме розширення .crx. Змініть розширення файлу з .crx на .zip. Використовуйте будь-який архіватор (наприклад, WinRAR, 7-Zip тощо), щоб витягти вміст ZIP-файлу.

Використання режиму розробника в Chrome

Відкрийте Chrome і перейдіть до chrome://extensions/. Увімкніть "Режим розробника" у верхньому правому куті. Натисніть "Завантажити розпаковане розширення...". Перейдіть до каталогу вашого розширення. Це не завантажує код джерела, але корисно для перегляду та модифікації коду вже завантаженого або розробленого розширення.

Набір даних маніфестів розширень Chrome

Щоб спробувати виявити вразливі розширення браузера, ви можете використовувати https://github.com/palant/chrome-extension-manifests-dataset і перевірити їхні файли маніфестів на потенційно вразливі ознаки. Наприклад, щоб перевірити розширення з більш ніж 25000 користувачів, content_scripts та дозволом nativeMessaing:

bash
# 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 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.

Посилання

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Підтримайте HackTricks