T1176

Software Extensions

Persistence Last updated:

Adversaries may abuse software extensions to establish persistent access to victim systems. Software extensions are modular components that enhance or customize the functionality of software applications, including web browsers, Integrated Development Environments (IDEs), and other platforms. Extensions are typically installed via official marketplaces or manually loaded, and they often inherit the permissions and access levels of the host application. Malicious extensions can be introduced through social engineering, compromised marketplaces, or direct installation by adversaries who have already gained system access. Detection is challenging due to the inherent trust placed in extensions and their ability to blend into normal application workflows.

What is T1176 Software Extensions?

Software Extensions (T1176) maps to the Persistence tactic — the adversary is trying to maintain their foothold in MITRE ATT&CK.

This page provides production-ready detection logic for Software Extensions, covering the data sources and telemetry it touches: File: File Creation, Windows Registry: Windows Registry Key Modification, Process: Process Creation, Command: Command Execution, Microsoft Defender for Endpoint. The queries below are rated medium severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Persistence
Technique
T1176 Software Extensions
Canonical reference
https://attack.mitre.org/techniques/T1176/
Microsoft Sentinel / Defender
kusto
let BrowserExtPaths = dynamic([
  "\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Extensions\\",
  "\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default\\Extensions\\",
  "\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\",
  "\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Default\\Extensions\\"
]);
let IDEExtPaths = dynamic([
  "\\.vscode\\extensions\\",
  "\\AppData\\Roaming\\Code\\extensions\\",
  "\\.vscode-server\\extensions\\"
]);
let SuspiciousExtCommands = dynamic([
  "--load-extension",
  "--packed-extension",
  "--allow-outdated-plugins",
  "code --install-extension",
  "code-insiders --install-extension",
  ".crx",
  ".xpi",
  ".vsix"
]);
let LegitBrowserProcs = dynamic(["chrome.exe", "msedge.exe", "firefox.exe", "brave.exe", "opera.exe", "iexplore.exe"]);
let LegitIDEProcs = dynamic(["Code.exe", "code", "Code - Insiders.exe", "idea64.exe", "pycharm64.exe"]);
// Branch 1: Suspicious file writes into browser or IDE extension directories
let ExtFileCreation = DeviceFileEvents
| where Timestamp > ago(24h)
| where (FolderPath has_any (BrowserExtPaths) or FolderPath has_any (IDEExtPaths))
| where FileName endswith ".crx" or FileName endswith ".xpi" or FileName endswith ".vsix"
    or FileName =~ "manifest.json" or FileName endswith ".js" or FileName endswith ".dll"
| where InitiatingProcessFileName !in~ (LegitBrowserProcs)
    and InitiatingProcessFileName !in~ (LegitIDEProcs)
    and InitiatingProcessFileName !in~ ("chrome_updater.exe", "MicrosoftEdgeUpdate.exe", "GoogleUpdate.exe")
| extend DetectionType = "SuspiciousExtensionFileWrite"
| project Timestamp, DeviceName, AccountName, FolderPath, FileName,
          InitiatingProcessFileName, InitiatingProcessCommandLine, DetectionType;
// Branch 2: Registry-based forced extension installation
let ExtRegistryMod = DeviceRegistryEvents
| where Timestamp > ago(24h)
| where RegistryKey has "ExtensionInstallForcelist"
    or RegistryKey has "ExtensionInstallAllowlist"
    or (RegistryKey has "\\Extensions\\" and RegistryKey has_any ("\\Chrome\\", "\\Edge\\", "\\Chromium\\"))
    or RegistryKey has "ExtensionInstallBlacklist"
| extend DetectionType = "ExtensionRegistryForceInstall"
| project Timestamp, DeviceName, AccountName, RegistryKey, RegistryValueName, RegistryValueData,
          InitiatingProcessFileName, InitiatingProcessCommandLine, DetectionType;
// Branch 3: Command-line extension installation or loading
let ExtCmdInstall = DeviceProcessEvents
| where Timestamp > ago(24h)
| where ProcessCommandLine has_any (SuspiciousExtCommands)
    or (ProcessCommandLine has "--load-extension" and InitiatingProcessFileName !in~ (LegitBrowserProcs))
    or (ProcessCommandLine has ".vsix" and ProcessCommandLine has_any ("install", "--install-extension"))
| extend DetectionType = "ExtensionCLIInstall"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine, DetectionType;
ExtFileCreation
| union ExtRegistryMod
| union ExtCmdInstall
| sort by Timestamp desc

Detects suspicious software extension installation and modification across browsers and IDEs using Microsoft Defender for Endpoint tables. Three detection branches: (1) DeviceFileEvents monitors file writes to browser and IDE extension directories by non-browser processes, targeting .crx, .xpi, .vsix, manifest.json, and .js files; (2) DeviceRegistryEvents monitors policy-based forced extension installation via ExtensionInstallForcelist and related registry keys; (3) DeviceProcessEvents monitors command-line extension loading via --load-extension, --packed-extension, and CLI install flags. Legitimate browser/updater processes are excluded to reduce noise.

medium severity medium confidence

Data Sources

File: File Creation Windows Registry: Windows Registry Key Modification Process: Process Creation Command: Command Execution Microsoft Defender for Endpoint

Required Tables

DeviceFileEvents DeviceRegistryEvents DeviceProcessEvents

False Positives

  • Enterprise IT software packaging tools (SCCM, Intune) that deploy browser extensions as part of managed device configuration
  • Developer workstations where engineers legitimately install unpacked or sideloaded extensions using --load-extension for development and testing purposes
  • Security tools or browser management platforms (e.g., Ivanti, Workspace ONE) that configure forced extension installs via Group Policy or registry for enterprise DLP or SSO extensions
  • Automated build pipelines that install VSCode extensions as part of developer environment bootstrapping scripts
  • Legitimate extension marketplace update mechanisms that briefly trigger file writes to extension directories under unusual parent processes during background update checks

Sigma rule & cross-platform mapping

The detection logic for Software Extensions (T1176) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: process_creation
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 5 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Sideload Unpacked Chrome Extension via Command Line

    Expected signal: Sysmon Event ID 1 (ProcessCreate): Image=chrome.exe, CommandLine containing '--load-extension' and '%TEMP%\malext'. Sysmon Event ID 11 (FileCreate): TargetFilename targeting the malext directory with manifest.json created by cmd.exe. DeviceProcessEvents in MDE will show the Chrome launch with --load-extension flag. DeviceFileEvents will show manifest.json creation by cmd.exe.

  2. Test 2Force Install Browser Extension via Registry Policy

    Expected signal: Sysmon Event ID 13 (RegistryValueSet): TargetObject=HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist\1, Details containing the extension ID. Image=reg.exe. DeviceRegistryEvents in MDE: RegistryKey containing 'ExtensionInstallForcelist', RegistryValueData containing the extension ID and update URL. Security Event ID 4657 (Registry value modified) if object access auditing is enabled.

  3. Test 3Install Malicious VSCode Extension from .vsix Package

    Expected signal: Sysmon Event ID 1 (ProcessCreate): Image=code.exe (or Code.exe), CommandLine containing '--install-extension' and '.vsix'. Sysmon Event ID 11 (FileCreate): Multiple file writes to %USERPROFILE%\.vscode\extensions\test.test-ext-0.0.1\ directory. DeviceProcessEvents and DeviceFileEvents in MDE will show VSCode CLI invocation and extension directory population.

  4. Test 4Drop Extension Files Directly into Browser Extension Directory

    Expected signal: Sysmon Event ID 11 (FileCreate): TargetFilename targeting Chrome Extensions directory with manifest.json and background.js, Image=cmd.exe (not chrome.exe). DeviceFileEvents in MDE: FolderPath containing 'Chrome\User Data\Default\Extensions', FileName=manifest.json and background.js, InitiatingProcessFileName=cmd.exe.

  5. Test 5Enumerate Installed Extensions for Reconnaissance

    Expected signal: Sysmon Event ID 1 (ProcessCreate): Image=powershell.exe, CommandLine referencing Chrome Extensions path and Get-ChildItem/Get-Content operations against manifest.json files. Sysmon Event ID 11 may be absent (read-only operation). DeviceProcessEvents in MDE shows PowerShell reading extension manifests. No file modification events, distinguishing this from installation activity.


Response Playbook

Triage

  1. Identify the specific extension involved — locate the manifest.json file in the extension directory (e.g., C:\Users\<user>\AppData\Local\Google\Chrome\User Data\Default\Extensions\<extension_id>\<version>\manifest.json) and examine the 'name', 'description', 'permissions', and 'content_scripts' fields. High-risk permissions include 'tabs', 'webRequest', 'webRequestBlocking', 'cookies', '<all_urls>', 'nativeMessaging', and 'clipboardRead'.
  2. Determine the installation method — was the extension installed from an official marketplace (Chrome Web Store, Firefox Add-ons, VS Marketplace), sideloaded via --load-extension, installed via forced registry policy, or dropped directly into the extensions directory by a non-browser process?
  3. Check the extension ID or package name against threat intelligence — search VirusTotal (https://www.virustotal.com) with the extension ID or hash of the .crx/.vsix file. Cross-reference against known malicious extension lists from CheckPoint, Kaspersky, and security researchers.
  4. Examine the initiating process context — what process wrote the extension files or created the registry key? A script interpreter (powershell.exe, wscript.exe, cmd.exe), a document application (winword.exe, excel.exe), or a downloaded binary (unknown_installer.exe) are high-severity indicators.
  5. Review permissions declared in manifest.json — check 'host_permissions' for broad URL patterns (e.g., '<all_urls>', 'http://*/*'), 'background' scripts that persist in memory, 'content_scripts' that inject into all pages, and 'externally_connectable' that allows native messaging.
  6. Enumerate all recently installed extensions on the affected host — for Chrome: check C:\Users\<user>\AppData\Local\Google\Chrome\User Data\Default\Extensions\, enumerate directories by modification date. For VSCode: check %USERPROFILE%\.vscode\extensions\ and compare against expected developer tooling baseline.
  7. Check for network activity associated with the extension — review DeviceNetworkEvents or Sysmon Event ID 3 for outbound connections from chrome.exe, msedge.exe, Code.exe within the time window of extension installation. Flag connections to non-corporate IPs, especially on ports 443, 80, or non-standard ports.

Containment

  1. If a malicious browser extension is confirmed: immediately remove the extension by navigating to browser extension management (chrome://extensions/, about:addons) or by deleting the extension directory under AppData and restarting the browser. Document the extension ID before removal.
  2. If the extension was installed via Group Policy or registry forced-install: locate and remove the corresponding registry key at HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist or HKLM\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallForcelist. If the policy was not authorized, escalate to investigate how the registry was modified.
  3. If a malicious VSCode extension is confirmed: remove it via 'code --uninstall-extension <extension-id>' or delete the directory from %USERPROFILE%\.vscode\extensions\<extension-id>\. Restart VSCode and review workspace .vscode/settings.json for extension recommendations that may reinstall it.
  4. Block network connections from the extension's associated domains/IPs at the perimeter firewall, proxy, and DNS layer if the extension was communicating with external infrastructure.
  5. If the extension appears to have been used for credential harvesting or session token theft: immediately invalidate all active browser sessions, force password reset for the affected user, and revoke OAuth tokens via identity provider admin console.
  6. Preserve the malicious extension package (directory or .crx/.vsix file) in a forensic container before removal for further analysis and threat intelligence sharing.

Evidence Collection

  1. Extension manifest.json — located at <browser_profile>\Extensions\<extension_id>\<version>\manifest.json. Contains declared permissions, content scripts, background scripts, externally connectable origins, and update URL.
  2. Extension source files — all .js, .html, .json files in the extension directory. Malicious logic may be obfuscated in background.js, content.js, or injected via eval() and dynamic script loading.
  3. Browser extension installation log — Chrome writes to <profile>\Local State (JSON), which tracks extension installation timestamps and sources. Edge equivalent at equivalent path under Edge profile.
  4. Windows Registry — HKCU\Software\Google\Chrome\PreferenceMACs and HKCU\Software\Google\Chrome\Preferences contain extension state. HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist for forced installs.
  5. Sysmon Event ID 11 (FileCreate) — captures initial file writes into extension directories with initiating process context and timestamps.
  6. Sysmon Event ID 3 (NetworkConnect) — captures outbound connections from the browser process during the window when the extension was active. Correlate to extension installation timestamp.
  7. Browser history and network logs — review browser history files (Chrome: History SQLite DB at <profile>\History) and proxy logs for POST requests to unusual external domains shortly after extension installation.
  8. VSCode extension audit — for IDE extensions, review <extension_dir>/package.json for 'contributes.commands', 'activationEvents', and any 'scripts' sections. Check for 'postinstall' npm scripts that execute on installation.
  9. Prefetch files — C:\Windows\Prefetch\ for evidence of extension installer executables or package managers (npm.exe, pip3.exe) that may have been used to stage the extension.

Escalation Criteria

  • ! Extension with broad permissions (<all_urls>, webRequestBlocking, cookies, clipboardRead) installed by a non-browser process or via unauthorized registry policy — indicates deliberate backdoor deployment.
  • ! Extension communicating with known C2 infrastructure, tor exit nodes, or domains registered within the past 30 days with no legitimate business association.
  • ! Extension installed on multiple hosts within a short time window without a corresponding change management ticket — possible lateral movement or supply chain compromise.
  • ! Malicious VSCode or IDE extension with 'postinstall' scripts or native binaries that execute on installation, especially if spawning child processes (node.exe, python.exe, cmd.exe) from the IDE process.
  • ! Evidence of session cookie theft or credential harvesting — POST requests from browser to external domains containing cookie or localStorage data, or browser extension accessing password manager fields.
  • ! Extension installed from a non-official source (unpacked, sideloaded .crx from email/web download) on a privileged user workstation (domain admin, service account owner, developer with production access).

Investigation Guide

Forensic Artifacts

  • > Chrome Extension Directory: C:\Users\<user>\AppData\Local\Google\Chrome\User Data\Default\Extensions\<extension_id>\<version>\ — contains manifest.json, background scripts, content scripts, and all extension assets
  • > Chrome Preferences File: C:\Users\<user>\AppData\Local\Google\Chrome\User Data\Default\Preferences — JSON file containing installed extension list with IDs, names, enabled state, and installation timestamps
  • > Chrome Local State: C:\Users\<user>\AppData\Local\Google\Chrome\User Data\Local State — contains extension integrity hashes and installation metadata
  • > Firefox Extensions Directory: C:\Users\<user>\AppData\Roaming\Mozilla\Firefox\Profiles\<profile>\extensions\ — .xpi files for installed extensions
  • > Firefox extensions.json: C:\Users\<user>\AppData\Roaming\Mozilla\Firefox\Profiles\<profile>\extensions.json — metadata for all installed Firefox add-ons including installation source and timestamps
  • > Edge Extension Directory: C:\Users\<user>\AppData\Local\Microsoft\Edge\User Data\Default\Extensions\<extension_id>\
  • > VSCode Extensions Directory: %USERPROFILE%\.vscode\extensions\ — each extension in its own subdirectory with package.json containing metadata, scripts, and activation events
  • > Windows Registry: HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist — Group Policy forced extension list
  • > Windows Registry: HKLM\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallForcelist — Edge forced extension policy
  • > Browser History SQLite DB: C:\Users\<user>\AppData\Local\Google\Chrome\User Data\Default\History — review visits correlating to extension installation timestamp
  • > Network Proxy Logs: HTTP POST requests from browser user-agent to external domains within the extension execution window
  • > npm/yarn cache: %APPDATA%\npm-cache\ or ~/.npm — if IDE extension was installed via package manager, installation artifacts may persist here

Tuning Guidance

Begin by baselining which extension management methods are legitimate in your environment. Common false positive sources: (1) Enterprise MDM tools (Intune, Workspace ONE, Jamf) that deploy browser extensions via ExtensionInstallForcelist registry policy — create allowlists for authorized extension IDs and the management tool process names; (2) Developer workstations where --load-extension is routine — consider excluding specific developer AD groups or machine names for the CLI installation branch while keeping registry and file-drop branches active; (3) Browser update mechanisms — whitelist GoogleUpdate.exe, MicrosoftEdgeUpdate.exe, and the browser binaries themselves for file write events in extension directories. For the file-write detection branch, narrow scope to non-.js files initially (.crx, .xpi, .vsix, manifest.json) to reduce volume, then expand once baseline is established. For the registry branch, focus on modifications made outside of Group Policy refresh cycles (gpupdate.exe, svchost.exe/WMI) as these are higher-fidelity indicators. In VSCode-heavy developer environments, consider building an allowlist of approved extension IDs from your organization's approved extensions list and alerting only on extensions not in that list. Correlate extension installation events with IT helpdesk tickets or change management records — unmatched installations on privileged user workstations warrant immediate investigation regardless of other indicators.


Hunting Queries

Hunt for browsers making outbound connections on non-standard ports to public IPs. Malicious extensions often use non-443 ports for C2 communication or data exfiltration to avoid HTTPS inspection. This is distinct from the main detection which focuses on installation events.

Hunting — KQL
kql
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in~ ("chrome.exe", "msedge.exe", "firefox.exe", "brave.exe")
| where RemoteIPType == "Public"
| where RemotePort !in (80, 443)
| summarize ConnectionCount=count(), UniqueRemoteIPs=dcount(RemoteIP), RemotePorts=make_set(RemotePort), RemoteIPs=make_set(RemoteIP, 10)
    by DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine
| where ConnectionCount > 5 or UniqueRemoteIPs > 3
| sort by ConnectionCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
  (Image="*\\chrome.exe" OR Image="*\\msedge.exe" OR Image="*\\firefox.exe" OR Image="*\\brave.exe")
  NOT (DestinationIp="10.*" OR DestinationIp="172.16.*" OR DestinationIp="192.168.*" OR DestinationIp="127.*")
  NOT (DestinationPort=80 OR DestinationPort=443)
| stats count as ConnectionCount, dc(DestinationIp) as UniqueIPs, values(DestinationPort) as Ports, values(DestinationIp) as IPs
    by host, User, Image
| where ConnectionCount > 5 OR UniqueIPs > 3
| sort - ConnectionCount

Hunt for browsers and IDEs spawning shell interpreters, scripting engines, or system utilities as child processes. Malicious extensions with nativeMessaging capabilities or code execution vulnerabilities may spawn child processes. This identifies post-exploitation activity that begins within the extension runtime rather than at installation time.

Hunting — KQL
kql
DeviceProcessEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in~ ("chrome.exe", "msedge.exe", "Code.exe", "code", "firefox.exe")
| where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "wscript.exe", "cscript.exe",
                       "certutil.exe", "curl.exe", "wget.exe", "mshta.exe", "rundll32.exe",
                       "node.exe", "python.exe", "python3.exe", "sh", "bash")
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId
| sort by Timestamp desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
  (ParentImage="*\\chrome.exe" OR ParentImage="*\\msedge.exe" OR ParentImage="*\\Code.exe"
   OR ParentImage="*\\firefox.exe" OR ParentImage="*\\brave.exe")
  (Image="*\\cmd.exe" OR Image="*\\powershell.exe" OR Image="*\\pwsh.exe"
   OR Image="*\\wscript.exe" OR Image="*\\cscript.exe" OR Image="*\\certutil.exe"
   OR Image="*\\curl.exe" OR Image="*\\node.exe" OR Image="*\\python.exe"
   OR Image="*\\mshta.exe" OR Image="*\\rundll32.exe" OR Image="*\\sh"
   OR Image="*\\bash")
| table _time, host, User, Image, CommandLine, ParentImage, ParentCommandLine
| sort - _time

Hunt for bulk manifest.json writes to extension directories by non-browser processes. Writing multiple extension manifests in a short window may indicate automated deployment of multiple malicious extensions, bulk sideloading as part of a persistence script, or a supply chain compromise that installs multiple backdoored extensions simultaneously.

Hunting — KQL
kql
DeviceFileEvents
| where Timestamp > ago(7d)
| where FolderPath has_any ([
    "\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Extensions\\",
    "\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default\\Extensions\\",
    "\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\"
  ])
| where FileName =~ "manifest.json"
| summarize ExtensionCount=dcount(FolderPath), ExtensionPaths=make_set(FolderPath, 20),
            FirstSeen=min(Timestamp), LastSeen=max(Timestamp)
    by DeviceName, AccountName, InitiatingProcessFileName
| where ExtensionCount > 3 and InitiatingProcessFileName !in~ ("chrome.exe","msedge.exe","firefox.exe","MicrosoftEdgeUpdate.exe","GoogleUpdate.exe")
| sort by ExtensionCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=11
  (TargetFilename="*\\Extensions\\*manifest.json"
   OR TargetFilename="*\\Firefox\\Profiles\\*manifest.json")
  NOT (Image="*\\chrome.exe" OR Image="*\\msedge.exe" OR Image="*\\firefox.exe"
       OR Image="*\\MicrosoftEdgeUpdate.exe" OR Image="*\\GoogleUpdate.exe")
| stats dc(TargetFilename) as ExtensionCount, values(TargetFilename) as ExtensionPaths,
        earliest(_time) as FirstSeen, latest(_time) as LastSeen
    by host, User, Image
| where ExtensionCount > 3
| sort - ExtensionCount

Atomic Red Team Tests

Test 1 Sideload Unpacked Chrome Extension via Command Line
windows

Launches Chrome with the --load-extension flag pointing to a local directory containing a minimal browser extension with broad permissions. This simulates an adversary who has already gained code execution and uses it to silently install a malicious browser extension that persists across browser sessions. The extension directory must contain a valid manifest.json.

Command

powershell
mkdir %TEMP%\malext && echo {"manifest_version":3,"name":"Test Extension","version":"1.0","permissions":["tabs","cookies","<all_urls>"],"background":{"service_worker":"bg.js"}} > %TEMP%\malext\manifest.json && echo console.log('ext loaded'); > %TEMP%\malext\bg.js && "C:\Program Files\Google\Chrome\Application\chrome.exe" --load-extension=%TEMP%\malext --disable-extensions-except=%TEMP%\malext

Cleanup

powershell
rmdir /s /q %TEMP%\malext

Expected Telemetry

Sysmon Event ID 1 (ProcessCreate): Image=chrome.exe, CommandLine containing '--load-extension' and '%TEMP%\malext'. Sysmon Event ID 11 (FileCreate): TargetFilename targeting the malext directory with manifest.json created by cmd.exe. DeviceProcessEvents in MDE will show the Chrome launch with --load-extension flag. DeviceFileEvents will show manifest.json creation by cmd.exe.

Expected Detection

KQL Branch 3 (ExtensionCLIInstall) fires on ProcessCommandLine containing '--load-extension'. SPL EventCode=1 branch fires on CommandLine containing '--load-extension'. Additionally, KQL Branch 1 (ExtensionFileWrite) may fire on manifest.json creation in the temp directory by cmd.exe.

Test 2 Force Install Browser Extension via Registry Policy
windows

Adds a registry entry to Chrome's ExtensionInstallForcelist policy key that will cause Chrome to automatically download and install a specified extension from the Chrome Web Store on next launch. This technique is used by adversaries with local admin rights to silently push extensions to browsers without user consent, persisting even if the user removes the extension manually.

Command

powershell
reg add "HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist" /v 1 /t REG_SZ /d "cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx" /f

Cleanup

powershell
reg delete "HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist" /v 1 /f

Expected Telemetry

Sysmon Event ID 13 (RegistryValueSet): TargetObject=HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist\1, Details containing the extension ID. Image=reg.exe. DeviceRegistryEvents in MDE: RegistryKey containing 'ExtensionInstallForcelist', RegistryValueData containing the extension ID and update URL. Security Event ID 4657 (Registry value modified) if object access auditing is enabled.

Expected Detection

KQL Branch 2 (ExtensionRegistryForceInstall) fires on RegistryKey containing 'ExtensionInstallForcelist'. SPL EventCode=12/13/14 branch fires on TargetObject containing 'ExtensionInstallForcelist'. High-fidelity alert — reg.exe modifying Chrome policy keys outside of Group Policy infrastructure is nearly always suspicious.

Test 3 Install Malicious VSCode Extension from .vsix Package
windows

Installs a locally packaged VSCode extension (.vsix file) using the VSCode CLI. This simulates an adversary who drops a backdoored IDE extension (e.g., a trojanized popular extension or a fake productivity tool) onto a developer workstation and installs it silently. The test uses a benign .vsix created from a minimal extension package.

Command

powershell
mkdir %TEMP%\fakeext && echo {"name":"test-ext","displayName":"Test","version":"0.0.1","publisher":"test","engines":{"vscode":"^1.0.0"}} > %TEMP%\fakeext\package.json && cd %TEMP%\fakeext && npm install -g @vscode/vsce 2>nul & vsce package --allow-missing-repository 2>nul & code --install-extension %TEMP%\fakeext\test-ext-0.0.1.vsix

Cleanup

powershell
code --uninstall-extension test.test-ext & rmdir /s /q %TEMP%\fakeext

Expected Telemetry

Sysmon Event ID 1 (ProcessCreate): Image=code.exe (or Code.exe), CommandLine containing '--install-extension' and '.vsix'. Sysmon Event ID 11 (FileCreate): Multiple file writes to %USERPROFILE%\.vscode\extensions\test.test-ext-0.0.1\ directory. DeviceProcessEvents and DeviceFileEvents in MDE will show VSCode CLI invocation and extension directory population.

Expected Detection

KQL Branch 3 (ExtensionCLIInstall) fires on ProcessCommandLine containing '.vsix' and 'install'. SPL EventCode=1 branch fires on CommandLine containing '.vsix' and 'install'. KQL Branch 1 (ExtensionFileWrite) may also fire on .vsix writes to IDE extension directories.

Test 4 Drop Extension Files Directly into Browser Extension Directory
windows

Simulates an adversary directly writing extension files into Chrome's extension directory without using the browser's official installation mechanism. This technique bypasses browser extension security checks and can be used to install extensions that would be rejected by the Web Store. Creates a minimal extension directory structure with a manifest indicating broad permissions.

Command

powershell
set EXTDIR=%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\1.0_0 && mkdir "%EXTDIR%" && echo {"manifest_version":3,"name":"Injected Extension","version":"1.0","permissions":["tabs","<all_urls>","webRequest","cookies"]} > "%EXTDIR%\manifest.json" && echo console.log('backdoor active'); > "%EXTDIR%\background.js"

Cleanup

powershell
rmdir /s /q "%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

Expected Telemetry

Sysmon Event ID 11 (FileCreate): TargetFilename targeting Chrome Extensions directory with manifest.json and background.js, Image=cmd.exe (not chrome.exe). DeviceFileEvents in MDE: FolderPath containing 'Chrome\User Data\Default\Extensions', FileName=manifest.json and background.js, InitiatingProcessFileName=cmd.exe.

Expected Detection

KQL Branch 1 (SuspiciousExtensionFileWrite) fires because cmd.exe is writing manifest.json and .js files to Chrome's extension directory — a non-browser process writing to extension directories is the core detection signal. SPL EventCode=11 branch fires on TargetFilename in Chrome Extensions directory written by cmd.exe.

Test 5 Enumerate Installed Extensions for Reconnaissance
windows

Uses PowerShell to enumerate all installed Chrome and VSCode extensions on the current user's profile. Adversaries who have established initial access may enumerate installed extensions to identify security tools (EDR browser agents, password managers), valuable targets for credential theft (banking, corporate SSO extensions), or to profile the victim. This simulates the reconnaissance phase of an extension-based attack.

Command

powershell
powershell.exe -Command "$chromePath = "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Extensions"; Get-ChildItem $chromePath -Directory | ForEach-Object { $manifest = Get-Content (Join-Path $_.FullName (Get-ChildItem $_.FullName -Directory | Select-Object -First 1).Name + '\manifest.json') -Raw -ErrorAction SilentlyContinue | ConvertFrom-Json -ErrorAction SilentlyContinue; [PSCustomObject]@{ID=$_.Name; Name=$manifest.name; Permissions=$manifest.permissions -join ','} } | Format-Table -AutoSize"

Expected Telemetry

Sysmon Event ID 1 (ProcessCreate): Image=powershell.exe, CommandLine referencing Chrome Extensions path and Get-ChildItem/Get-Content operations against manifest.json files. Sysmon Event ID 11 may be absent (read-only operation). DeviceProcessEvents in MDE shows PowerShell reading extension manifests. No file modification events, distinguishing this from installation activity.

Expected Detection

This test may not trigger the primary detection (which focuses on writes and CLI installs) but will appear in hunting query results for PowerShell accessing browser profile directories. Analysts investigating a broader compromise should run the hunting query for bulk manifest.json access by non-browser processes.

Related Detections