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

Скрипти контенту
Кожен скрипт контенту має прямий доступ до DOM однієї веб-сторінки і, таким чином, піддається потенційно шкідливому вводу. Однак скрипт контенту не має жодних дозволів, окрім можливості надсилати повідомлення до ядра розширення.
Ядро розширення
Ядро розширення містить більшість привілеїв/доступу розширення, але ядро розширення може взаємодіяти з веб-контентом лише через XMLHttpRequest та скрипти контенту. Крім того, ядро розширення не має прямого доступу до хост-машини.
Рідний бінарний файл
Розширення дозволяє рідний бінарний файл, який може доступатися до хост-машини з повними привілеями користувача. Рідний бінарний файл взаємодіє з ядром розширення через стандартний Інтерфейс програмування додатків плагінів Netscape (NPAPI), який використовується Flash та іншими плагінами браузера.
Межі
Caution
Щоб отримати повні привілеї користувача, зловмисник повинен переконати розширення передати шкідливий ввід від скрипта контенту до ядра розширення і від ядра розширення до рідного бінарного файлу.
Кожен компонент розширення відокремлений один від одного сильними захисними межами. Кожен компонент працює в окремому процесі операційної системи. Скрипти контенту та ядра розширення працюють у пісочницях, недоступних для більшості служб операційної системи.
Більше того, скрипти контенту відокремлені від своїх асоційованих веб-сторінок, працюючи в окремій купі JavaScript. Скрипт контенту та веб-сторінка мають доступ до одного й того ж базового DOM, але двоє ніколи не обмінюються вказівниками JavaScript, що запобігає витоку функціональності JavaScript.
manifest.json
Розширення Chrome - це просто ZIP-папка з .crx file extension. Ядро розширення - це manifest.json
файл у корені папки, який вказує макет, дозволи та інші параметри конфігурації.
Приклад:
{
"manifest_version": 2,
"name": "My extension",
"version": "1.0",
"permissions": ["storage"],
"content_scripts": [
{
"js": ["script.js"],
"matches": ["https://example.com/*", "https://www.example.com/*"],
"exclude_matches": ["*://*/*business*"]
}
],
"background": {
"scripts": ["background.js"]
},
"options_ui": {
"page": "options.html"
}
}
content_scripts
Скрипти контенту завантажуються щоразу, коли користувач переміщується на відповідну сторінку, у нашому випадку на будь-яку сторінку, що відповідає виразу https://example.com/*
і не відповідає регулярному виразу *://*/*/business*
. Вони виконуються як власні скрипти сторінки і мають довільний доступ до 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
. Це насправді забезпечує більше докладних контролів.
Для програмного впровадження скрипта контенту розширення повинно мати дозволи хоста для сторінки, на яку потрібно впровадити скрипти. Ці дозволи можуть бути отримані або запитуючи їх у маніфесті розширення, або на тимчасовій основі через 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
У публічних розширеннях extension-id доступний:

Однак, якщо параметр manifest.json
use_dynamic_url
використовується, цей id може бути динамічним.
Tip
Зверніть увагу, що навіть якщо сторінка згадується тут, вона може бути захищена від ClickJacking завдяки Content Security Policy. Тому вам також потрібно перевірити це (розділ frame-ancestors) перед підтвердженням можливості атаки ClickJacking.
Доступ до цих сторінок робить їх потенційно вразливими до ClickJacking:
{{#ref}} browext-clickjacking.md {{#endref}}
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"]
, тільки ці програми можуть підключатися. - Якщо вказані збіги, ці веб-додатки зможуть підключатися:
"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 })
</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)
}
)
Веб ↔︎ Комунікація скриптів контенту
Середовища, в яких працюють скрипти контенту, і де існують хост-сторінки, відокремлені одне від одного, що забезпечує ізоляцію. Незважаючи на цю ізоляцію, обидві сторони мають можливість взаємодіяти з Моделлю об'єктів документа (DOM) сторінки, спільним ресурсом. Щоб хост-сторінка могла взаємодіяти з скриптом контенту або непрямо з розширенням через скрипт контенту, необхідно використовувати DOM, доступний обом сторонам, як канал комунікації.
Повідомлення
// 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) і пошукати цю інформацію.
Отже, пам'ять Розширення Браузера не повинна вважатися безпечною, і чутливу інформацію, таку як облікові дані або мнемонічні фрази, не слід зберігати.
Звичайно, не слід вставляти чутливу інформацію в код, оскільки вона буде публічною.
Щоб вивантажити пам'ять з браузера, ви можете вивантажити пам'ять процесу або перейти до налаштувань розширення браузера, натиснувши Перевірити спливаюче вікно
-> У розділі Пам'ять
-> Зробити знімок
і 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}}