Skip to content

Latest commit

 

History

History

README.md

Browser Extension Supply-Chain Attacks

Manifest V3 capability analysis, lab malicious extension catalog, update-channel hijack simulation, and defender-side tooling. Each extension demonstrates a distinct capability retained by MV3 — cookie theft, form grabbing, traffic redirection, session interception — paired with Sigma detection rules.

Containment: All extensions hard-check LAB_MODE = true and refuse to exfiltrate to anything other than 127.0.0.1. All Python tools require EXPLOIT_LAB_ACTIVE=1 and ContainmentGuard. These extensions are never submitted to the Chrome Web Store.

Why Browser Extensions, Why Now

The Chrome Manifest V3 migration was positioned as a security improvement. MV3 removed remote code evaluation, replaced persistent background pages with service workers, and restricted blocking webRequest. Despite these changes, MV3 extensions retain sufficient capability for full session cookie theft, credential harvesting, and silent traffic redirection — without any exploit.

The primary threat vector moved up the stack: from in-extension code capability to publisher account compromise and silent update delivery. The Cyberhaven incident of December 2024 demonstrated the operational template: steal a developer's Chrome Web Store OAuth token, publish a malicious update to the existing extension ID, and Chrome's auto-update delivers it to hundreds of thousands of users within hours — silently, without any user action required.

See docs/analysis/manifest-v3-capabilities.md for the full technical analysis.

Cyberhaven Incident (December 2024)

The Cyberhaven Chrome extension (~400,000 users) was compromised:

  1. Developer receives spear-phishing email posing as Chrome Web Store policy alert
  2. Developer authenticates to Google; attacker captures OAuth token for Developer API
  3. Attacker publishes malicious update v24.10.4 targeting Facebook Business cookies
  4. Chrome auto-update delivers the extension to 400k users
  5. Malicious version active for ~31 hours before takedown
  6. No zero-day, no CVE, no exploit — just stolen developer credentials

This repo's update-hijack/ module simulates this pattern in a contained lab.

Extension Catalog

cookie-theft/chrome.cookies API Exfil

Key finding: chrome.cookies.getAll({}) with <all_urls> host permissions bypasses HttpOnly — the cookie attribute that protects session tokens from XSS. An extension can steal all session cookies without any exploit.

  • MV3 manifest with cookies permission and service worker background
  • Background service worker calls chrome.cookies.getAll({}) on alarm schedule
  • Sends to 127.0.0.1:9999/exfil (LAB_MODE enforced)
  • Detection: Sigma rules for cookie exfil patterns

Pairs with: tools/rust/cookie-theft/ (Rust tool for local decryption of stored cookies — different threat model; extension captures live session cookies including session-only cookies never written to disk).

session-hijack/webRequest Header Observation

Key finding: MV3 removed blocking webRequest but observation remains fully available. onSendHeaders with extraHeaders exposes the Authorization header (normally segregated). All session material visible at the HTTP layer is capturable.

  • Hooks onSendHeaders and onHeadersReceived for all URLs
  • Buffers captured Authorization/Cookie/Set-Cookie header events
  • Drains to 127.0.0.1:9999/exfil every 30 seconds
  • Detection: Sigma rules for webRequest exfil patterns

form-grab/ — Content Script Credential Harvesting

Key finding: Content scripts are functionally unchanged between MV2 and MV3. A content script with <all_urls> and all_frames: true runs in every frame on every page including SSO login iframes, with full DOM access and form event interception capability.

  • Content script hooks form.submit events and password field input events
  • MutationObserver covers dynamically-generated React/Vue/Angular login forms
  • Detection: Sigma rules for form grab exfil patterns

dnr-redirect/ — DeclarativeNetRequest Traffic Redirection

Key finding: declarativeNetRequest was MV3's "safer" replacement for blocking webRequest, but it includes a redirect action type. Static redirect rules are reviewed at submission time; dynamic rules added via updateDynamicRules() are not subject to re-review.

  • Static rules target *.corp-lab.local domains
  • Service worker polls simulated C2 at 127.0.0.1:9997/rules for new redirects
  • Phishing page at 127.0.0.1:9998/phish receives redirected users
  • Detection: Sigma rules for DNR abuse patterns

update-hijack/ — Publisher Account Compromise Simulation

End-to-end simulation of the Cyberhaven attack pattern:

  • benign_ext/ — v1.0 Tab Counter (tabs permission only)
  • malicious_update/ — v1.1 Tab Counter (adds cookies + <all_urls> silently)
  • mock_webstore/server.py — Flask mock Chrome Web Store update endpoint with admin toggle between benign and malicious modes
  • update_client.py — Simulates Chrome update check with permission diff
  • permission_differ.py — Standalone permission comparison tool (exits non-zero on expansion — suitable for CI/CD pipeline integration)
  • Detection: Sigma rules for permission expansion events

eval/ — Defender-Side Tooling

  • manifest_analyzer.py — Static manifest risk scorer (0-10 scale, CI/CD integration via --threshold flag)
  • runtime_monitor.py — CDP-based runtime monitoring of extension network activity and console output via Chrome remote debugging port

Lab Architecture

Chrome with loaded extensions
    |
    |-- cookie-theft ext --> 127.0.0.1:9999/exfil (lab_attacker_server.py)
    |-- session-hijack ext -> 127.0.0.1:9999/exfil
    |-- form-grab ext -----> 127.0.0.1:9999/exfil
    |-- dnr-redirect ext --> 127.0.0.1:9997/rules (C2 mode)
                             127.0.0.1:9998/phish  (phishing page)

Mock Web Store (update-hijack): 127.0.0.1:9800
CDP Debug Port (eval):          127.0.0.1:9222

Quick Start

1. Start the lab attacker server

EXPLOIT_LAB_ACTIVE=1 python lab_attacker_server.py --port 9999

2. Load extensions in Chrome

Open chrome://extensions, enable Developer Mode, click "Load unpacked", and select the desired extension directory from this catalog.

3. Monitor received data

curl http://127.0.0.1:9999/status
curl http://127.0.0.1:9999/events/latest?n=5

4. Analyze extension manifests

python eval/manifest_analyzer.py cookie-theft/manifest.json
python eval/manifest_analyzer.py update-hijack/malicious_update/manifest.json

5. Run permission diff

python update-hijack/permission_differ.py \
  --before update-hijack/benign_ext/manifest.json \
  --after update-hijack/malicious_update/manifest.json

Loading Extensions in Chrome / Chromium

# Start Chromium with debug port (for runtime_monitor.py)
chromium --remote-debugging-port=9222 \
         --user-data-dir=/tmp/lab-chrome-profile \
         --no-sandbox \
         --disable-web-security

Then:

  1. Navigate to chrome://extensions
  2. Toggle "Developer mode" on
  3. Click "Load unpacked"
  4. Select the extension subdirectory (e.g., cookie-theft/)

Important: Each lab extension will be assigned a local extension ID by Chrome. This ID is not registered with the Chrome Web Store. Do not submit these extensions to the Web Store.

Documentation

Topic Location
MV3 capability analysis docs/analysis/manifest-v3-capabilities.md
Defender methodology docs/methodology/browser-extension-supply-chain.md
Cookie theft (Rust) tools/rust/cookie-theft/
Detection rules Each extension/detection/ directory