๋ธŒ๋ผ์šฐ์ € ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ Pentesting ๋ฐฉ๋ฒ•๋ก 

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 ์ง€์›ํ•˜๊ธฐ

๊ธฐ๋ณธ ์ •๋ณด

๋ธŒ๋ผ์šฐ์ € ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์€ JavaScript๋กœ ์ž‘์„ฑ๋˜๋ฉฐ ๋ธŒ๋ผ์šฐ์ €์— ์˜ํ•ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์€ DOM์„ ๊ฐ€์ง€์ง€๋งŒ ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ๋“ค์˜ DOM๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ๋“ค์˜ ๊ธฐ๋ฐ€์„ฑ(confidentiality), ๋ฌด๊ฒฐ์„ฑ(integrity), ๊ฐ€์šฉ์„ฑ(availability) (CIA)์„ ์นจํ•ดํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ

ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ ˆ์ด์•„์›ƒ์€ ์‹œ๊ฐํ™”ํ–ˆ์„ ๋•Œ ๊ฐ€์žฅ ์ž˜ ์ดํ•ด๋˜๋ฉฐ ์„ธ ๊ฐ€์ง€ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

http://webblaze.cs.berkeley.edu/papers/Extensions.pdf

Content Scripts

๊ฐ content script๋Š” ๋‹จ์ผ ์›น ํŽ˜์ด์ง€์˜ DOM์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ž ์žฌ์ ์œผ๋กœ ์•…์˜์ ์ธ ์ž…๋ ฅ์— ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ content script๋Š” ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ์ฝ”์–ด์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ ์™ธ์—๋Š” ๊ถŒํ•œ์„ ๊ฐ€์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Extension Core

extension core๋Š” ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ๋Œ€๋ถ€๋ถ„ ๊ถŒํ•œ/์ ‘๊ทผ์„ ํฌํ•จํ•˜์ง€๋งŒ, extension core๋Š” ์›น ์ปจํ…์ธ ์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ๋•Œ XMLHttpRequest์™€ content scripts๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ extension core๋Š” ํ˜ธ์ŠคํŠธ ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ์ง์ ‘์ ์ธ ์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.

Native Binary

ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์€ ์‚ฌ์šฉ์ž์˜ ์ „์ฒด ๊ถŒํ•œ์œผ๋กœ ํ˜ธ์ŠคํŠธ ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” native binary๋ฅผ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. native binary๋Š” Flash ๋ฐ ๊ธฐํƒ€ ๋ธŒ๋ผ์šฐ์ € ํ”Œ๋Ÿฌ๊ทธ์ธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ‘œ์ค€ Netscape Plugin Application Programming Interface (NPAPI)๋ฅผ ํ†ตํ•ด extension core์™€ ์ƒํ˜ธ์ž‘์šฉํ•ฉ๋‹ˆ๋‹ค.

Boundaries

Caution

์‚ฌ์šฉ์ž์˜ ์ „์ฒด ๊ถŒํ•œ์„ ์–ป๊ธฐ ์œ„ํ•ด, ๊ณต๊ฒฉ์ž๋Š” content script์—์„œ extension์˜ core๋กœ ์•…์„ฑ ์ž…๋ ฅ์„ ์ „๋‹ฌํ•˜๊ณ  extension์˜ core์—์„œ native binary๋กœ ์ „๋‹ฌํ•˜๋„๋ก ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ์†์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์„œ๋กœ ๊ฐ•๋ ฅํ•œ ๋ณดํ˜ธ ๊ฒฝ๊ณ„๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋ณ„๋„์˜ ์šด์˜ ์ฒด์ œ ํ”„๋กœ์„ธ์Šค์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. Content scripts์™€ extension cores๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์šด์˜ ์ฒด์ œ ์„œ๋น„์Šค์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” sandbox ํ”„๋กœ์„ธ์Šค์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ content scripts๋Š” ๋ณ„๋„์˜ JavaScript ํž™์—์„œ ์‹คํ–‰๋จ์œผ๋กœ์จ ๊ด€๋ จ ์›น ํŽ˜์ด์ง€์™€ ๋ถ„๋ฆฌ๋ฉ๋‹ˆ๋‹ค. content script์™€ ์›น ํŽ˜์ด์ง€๋Š” ๊ฐ™์€ ๊ธฐ๋ณธ DOM์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‘ ๊ฐ์ฒด๋Š” JavaScript ํฌ์ธํ„ฐ๋ฅผ ์ ˆ๋Œ€ ๊ตํ™˜ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ JavaScript ๊ธฐ๋Šฅ์˜ leak๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

manifest.json

Chrome ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์€ ๋‹จ์ง€ .crx file extension์„ ๊ฐ€์ง„ ZIP ํด๋”์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ํ•ต์‹ฌ์€ ํด๋” ๋ฃจํŠธ์— ์žˆ๋Š” manifest.json ํŒŒ์ผ๋กœ, ๋ ˆ์ด์•„์›ƒ, ๊ถŒํ•œ ๋ฐ ๊ธฐํƒ€ ๊ตฌ์„ฑ ์˜ต์…˜์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

Example:

{
"manifest_version": 2,
"name": "My extension",
"version": "1.0",
"permissions": ["storage"],
"content_scripts": [
{
"js": ["script.js"],
"matches": ["https://example.com/*", "https://www.example.com/*"],
"exclude_matches": ["*://*/*business*"]
}
],
"background": {
"scripts": ["background.js"]
},
"options_ui": {
"page": "options.html"
}
}

content_scripts

Content scripts๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ผ์น˜ํ•˜๋Š” ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ๋•Œ๋งˆ๋‹ค ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค, ์ด ๊ฒฝ์šฐ https://example.com/* ํ‘œํ˜„์‹๊ณผ ์ผ์น˜ํ•˜๊ณ  *://*/*/business* ์ •๊ทœ์‹๊ณผ๋Š” ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€๊ฐ€ ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ด๋“ค์€ ํŽ˜์ด์ง€ ์ž์ฒด์˜ ์Šคํฌ๋ฆฝํŠธ์ฒ˜๋Ÿผ ์‹คํ–‰๋˜๋ฉฐ ํŽ˜์ด์ง€์˜ Document Object Model (DOM)์— ์ž„์˜๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],

๋” ๋งŽ์€ URL์„ ํฌํ•จํ•˜๊ฑฐ๋‚˜ ์ œ์™ธํ•˜๋ ค๋ฉด **include_globs**์™€ **exclude_globs**๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ the storage API๋ฅผ ์‚ฌ์šฉํ•ด ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ์ €์žฅ์†Œ์—์„œ message ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ ํŽ˜์ด์ง€์— explain ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•˜๋Š” ์˜ˆ์‹œ content script์ž…๋‹ˆ๋‹ค.

chrome.storage.local.get("message", (result) => {
let div = document.createElement("div")
div.innerHTML = result.message + " <button>Explain</button>"
div.querySelector("button").addEventListener("click", () => {
chrome.runtime.sendMessage("explain")
})
document.body.appendChild(div)
})

์ด ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ๊ฐ€ runtime.sendMessage() API๋ฅผ ์‚ฌ์šฉํ•ด ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ํŽ˜์ด์ง€๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋Œ€๋ถ€๋ถ„์˜ API์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋ฉฐ, storage ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ์˜ˆ์™ธ๋งŒ ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜ˆ์™ธ๋ฅผ ๋ฒ—์–ด๋‚œ ๊ธฐ๋Šฅ์€ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ํŽ˜์ด์ง€๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ , ์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํ•ด๋‹น ํŽ˜์ด์ง€์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค.

Warning

๋ธŒ๋ผ์šฐ์ €์— ๋”ฐ๋ผ ์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ์˜ ๊ธฐ๋Šฅ์ด ์•ฝ๊ฐ„ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Chromium ๊ธฐ๋ฐ˜ ๋ธŒ๋ผ์šฐ์ €์˜ ๊ธฐ๋Šฅ ๋ชฉ๋ก์€ Chrome Developers documentation์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ , Firefox์˜ ๊ฒฝ์šฐ ์ฃผ์š” ์ถœ์ฒ˜๋Š” MDN์ž…๋‹ˆ๋‹ค.
๋˜ํ•œ ์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ๋Š” background ์Šคํฌ๋ฆฝํŠธ์™€ ํ†ต์‹ ํ•˜์—ฌ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‘๋‹ต์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ๋„ ์ฃผ๋ชฉํ•  ๋งŒํ•ฉ๋‹ˆ๋‹ค.

Chrome์—์„œ ์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ณด๊ณ  ๋””๋ฒ„๊น…ํ•˜๋ ค๋ฉด Chrome ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ๋ฉ”๋‰ด๋ฅผ Options > More tools > Developer tools์—์„œ ์—ด๊ฑฐ๋‚˜ Ctrl + Shift + I๋ฅผ ๋ˆ„๋ฅด์„ธ์š”.

๊ฐœ๋ฐœ์ž ๋„๊ตฌ๊ฐ€ ํ‘œ์‹œ๋˜๋ฉด Source tab์„ ํด๋ฆญํ•œ ๋‹ค์Œ Content Scripts ํƒญ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹ค์–‘ํ•œ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์‹คํ–‰ ์ค‘์ธ ์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ด€์ฐฐํ•˜๊ณ  ์‹คํ–‰ ํ๋ฆ„์„ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•ด ๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Injected content scripts

Tip

Note that Content Scripts arenโ€™t mandatory โ€” ์›น ํŽ˜์ด์ง€์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋™์ ์œผ๋กœ(inject) ์ฃผ์ž…ํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ฃผ์ž…ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋ฉฐ, **tabs.executeScript**๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ณด๋‹ค ์„ธ๋ฐ€ํ•œ ์ œ์–ด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ฃผ์ž…ํ•˜๋ ค๋ฉด, ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ฃผ์ž…ํ•  ํŽ˜์ด์ง€์— ๋Œ€ํ•œ [host permissions]๊ฐ€ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ถŒํ•œ์€ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ๋งค๋‹ˆํŽ˜์ŠคํŠธ์—์„œ ์š”์ฒญ(requesting them) ํ•˜๊ฑฐ๋‚˜ ์ผ์‹œ์ ์œผ๋กœ activeTab๋ฅผ ํ†ตํ•ด ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

activeTab ๊ธฐ๋ฐ˜ ํ™•์žฅ ์˜ˆ์ œ

{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
  • ํด๋ฆญ ์‹œ JS ํŒŒ์ผ์„ ์ฃผ์ž…:
// content-script.js
document.body.style.backgroundColor = "orange"

//service-worker.js - Inject the JS file
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"],
})
})
  • ํด๋ฆญ ์‹œ ํ•จ์ˆ˜ ์ฃผ์ž…:
//service-worker.js - Inject a function
function injectedFunction() {
document.body.style.backgroundColor = "orange"
}

chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: injectedFunction,
})
})

์Šคํฌ๋ฆฝํŒ… ๊ถŒํ•œ์ด ์žˆ๋Š” ์˜ˆ์ œ

// service-workser.js
chrome.scripting.registerContentScripts([
{
id: "test",
matches: ["https://*.example.com/*"],
excludeMatches: ["*://*/*business*"],
js: ["contentScript.js"],
},
])

// Another example
chrome.tabs.executeScript(tabId, { file: "content_script.js" })

In order to include or exclude more URLs itโ€™s also possible to use include_globs and exclude_globs.

์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ run_at

The run_at field controls ์–ธ์ œ JavaScript ํŒŒ์ผ์ด ์›น ํŽ˜์ด์ง€์— ์ฃผ์ž…๋˜๋Š”์ง€. The preferred and default value is "document_idle".

The possible values are:

  • document_idle: ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๋งˆ๋‹ค
  • document_start: css์˜ ํŒŒ์ผ๋“ค์ด ์ ์šฉ๋œ ํ›„์ด์ง€๋งŒ ๋‹ค๋ฅธ DOM์ด ๊ตฌ์„ฑ๋˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์—.
  • document_end: DOM์ด ์™„๋ฃŒ๋œ ์งํ›„์ด์ง€๋งŒ ์ด๋ฏธ์ง€๋‚˜ ํ”„๋ ˆ์ž„ ๊ฐ™์€ ํ•˜์œ„ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋กœ๋“œ๋˜๊ธฐ ์ „.

Via manifest.json

{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}

**service-worker.js**๋ฅผ ํ†ตํ•ด

chrome.scripting.registerContentScripts([
{
id: "test",
matches: ["https://*.example.com/*"],
runAt: "document_idle",
js: ["contentScript.js"],
},
])

background

content scripts๊ฐ€ ๋ณด๋‚ธ ๋ฉ”์‹œ์ง€๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์ด์ง€์—์„œ ์ˆ˜์‹ ๋˜๋ฉฐ, ์ด๋Š” ํ™•์žฅ(extension) ๊ตฌ์„ฑ ์š”์†Œ๋“ค์„ ์กฐ์ •ํ•˜๋Š” ์ค‘์•™ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์ด์ง€๋Š” ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ์ˆ˜๋ช… ๋™์•ˆ ์ง€์†์ ์œผ๋กœ ์กด์žฌํ•˜๋ฉฐ, ์‚ฌ์šฉ์ž์˜ ์ง์ ‘์ ์ธ ์ƒํ˜ธ์ž‘์šฉ ์—†์ด ์€๋ฐ€ํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ž์ฒด Document Object Model (DOM)์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ๋ณต์žกํ•œ ์ƒํ˜ธ์ž‘์šฉ๊ณผ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ํฌ์ธํŠธ:

  • ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์ด์ง€ ์—ญํ• : ํ™•์žฅ์˜ ์‹ ๊ฒฝ์ค‘์ถ”๋กœ์„œ ํ™•์žฅ์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„ ๊ฐ„ ํ†ต์‹ ๊ณผ ์กฐ์ •์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ์ง€์†์„ฑ: ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ๋ณด์ด์ง€ ์•Š์ง€๋งŒ ํ™•์žฅ์˜ ๊ธฐ๋Šฅ์— ํ•„์ˆ˜์ ์ธ ํ•ญ์ƒ ์กด์žฌํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ์ž…๋‹ˆ๋‹ค.
  • ์ž๋™ ์ƒ์„ฑ: ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ž๋™์œผ๋กœ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž๋™ ์ƒ์„ฑ๋œ ํŽ˜์ด์ง€์—๋Š” ํ™•์žฅ manifest์— ๋ช…์‹œ๋œ ๋ชจ๋“  background scripts๊ฐ€ ํฌํ•จ๋˜์–ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…์ด ์›ํ™œํžˆ ์ˆ˜ํ–‰๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

Tip

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์ด์ง€๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด ์ฃผ๋Š” ํŽธ์˜์„ฑ(๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ)์€ ํ•„์š”ํ•œ ๋ชจ๋“  background scripts๊ฐ€ ํ†ตํ•ฉ๋˜์–ด ๋™์ž‘ํ•˜๋„๋ก ํ•˜์—ฌ ํ™•์žฅ ์„ค์ • ๊ณผ์ •์„ ๊ฐ„์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šคํฌ๋ฆฝํŠธ:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request == "explain") {
chrome.tabs.create({ url: "https://example.net/explanation" })
}
})

It uses runtime.onMessage API to listen to messages. When an โ€œexplainโ€ message is received, it uses tabs API to open a page in a new tab.

๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋””๋ฒ„๊ทธํ•˜๋ ค๋ฉด extension details and inspect the service worker, ๋กœ ์ด๋™ํ•˜๋ฉด ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๊ฐ€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šคํฌ๋ฆฝํŠธ์™€ ํ•จ๊ป˜ ์—ด๋ฆฝ๋‹ˆ๋‹ค:

Options pages and other

Browser extensions can contain various kinds of pages:

  • Action pages are displayed in a drop-down when the extension icon is clicked.
  • ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์ด ์ƒˆ ํƒญ์—์„œ ๋กœ๋“œํ•  ํŽ˜์ด์ง€.
  • Option Pages: ์ด ํŽ˜์ด์ง€๋Š” ํด๋ฆญํ•˜๋ฉด ํ™•์žฅ ์œ„์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ด์ „ manifest์—์„œ ์ œ ๊ฒฝ์šฐ ์ด ํŽ˜์ด์ง€์— chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค ๋˜๋Š” ํด๋ฆญํ•˜๋ฉด:

์ด๋Ÿฌํ•œ ํŽ˜์ด์ง€๋“ค์€ ํ•„์š”์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์ด์ง€์ฒ˜๋Ÿผ ํ•ญ์ƒ ์ง€์†๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์ด๋“ค์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์ด์ง€์™€ ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค:

  • Content Scripts์™€์˜ ํ†ต์‹ : ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์ด์ง€์™€ ์œ ์‚ฌํ•˜๊ฒŒ, ์ด๋Ÿฌํ•œ ํŽ˜์ด์ง€๋“ค์€ content scripts๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด ํ™•์žฅ ๋‚ด ์ƒํ˜ธ์ž‘์šฉ์„ ์ด‰์ง„ํ•ฉ๋‹ˆ๋‹ค.
  • ํ™•์žฅ ์ „์šฉ API์— ๋Œ€ํ•œ ์ ‘๊ทผ: ์ด๋Ÿฌํ•œ ํŽ˜์ด์ง€๋“ค์€ ํ™•์žฅ์— ์ •์˜๋œ ๊ถŒํ•œ์— ๋”ฐ๋ผ ํ™•์žฅ ์ „์šฉ API์— ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

permissions & host_permissions

**permissions**์™€ **host_permissions**๋Š” manifest.json์˜ ํ•ญ๋ชฉ์œผ๋กœ, ๋ธŒ๋ผ์šฐ์ € ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์ด (storage, locationโ€ฆ) ์–ด๋–ค ๊ถŒํ•œ์„ ๊ฐ–๊ณ  ์žˆ๋Š”์ง€์™€ ์–ด๋–ค ์›น ํŽ˜์ด์ง€์—์„œ ๋™์ž‘ํ•˜๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ € ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์€ ๋งค์šฐ ๊ถŒํ•œ์ด ๊ฐ•๋ ฅํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์•…์„ฑ ํ™•์žฅ์ด๋‚˜ ์นจํ•ด๋œ ํ™•์žฅ์€ ๊ณต๊ฒฉ์ž์—๊ฒŒ ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ํ›”์น˜๊ณ  ๊ฐ์‹œํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ์ˆ˜๋‹จ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Check how these settings work and how they could get abused in:

BrowExt - permissions & host_permissions

content_security_policy

A content security policy can be declared also inside the manifest.json. If there is one defined, it could be vulnerable.

The default setting for browser extension pages is rather restrictive:

script-src 'self'; object-src 'self';

CSP์™€ ์ž ์žฌ์  ์šฐํšŒ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์„ ํ™•์ธํ•˜์„ธ์š”:

Content Security Policy (CSP) Bypass

web_accessible_resources

์›นํŽ˜์ด์ง€๊ฐ€ Browser Extension์˜ ํŽ˜์ด์ง€(์˜ˆ: .html ํŽ˜์ด์ง€)์— ์ ‘๊ทผํ•˜๋ ค๋ฉด, ํ•ด๋‹น ํŽ˜์ด์ง€๋Š” manifest.json์˜ web_accessible_resources ํ•„๋“œ์— ๋ช…์‹œ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์˜ˆ์‹œ:

{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}

์ด ํŽ˜์ด์ง€๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ URL์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

chrome-extension://<extension-id>/message.html

In public extensions the extension-id is accesible:

Although, if the manifest.json parameter use_dynamic_url is used, this id can be dynamic.

Tip

Note that even if a page is mentioned here, it might be protected against ClickJacking thanks to the Content Security Policy. So you also need to check it (frame-ancestors section) before confirming a ClickJacking attack is possible.

Being allowed to access these pages make these pages potentially vulnerable ClickJacking:

BrowExt - ClickJacking

Tip

Allowing these pages to be loaded only by the extension and not by random URLs could prevent ClickJacking attacks.

Caution

Note that the pages from web_accessible_resources and other pages of the extension are also capable of contacting background scripts. So if one of these pages is vulnerable to XSS it could open a bigger vulnerability.

Moreover, note that you can only open pages indicated in web_accessible_resources inside iframes, but from a new tab itโ€™s possible to access any page in the extension knowing the extension ID. Therefore, if an XSS is found abusing same parameters, it could be abused even if the page isnโ€™t configured in web_accessible_resources.

externally_connectable

A per the docs, The "externally_connectable" manifest property declares which extensions and web pages can connect to your extension via runtime.connect and runtime.sendMessage.

  • If the externally_connectable key is not declared in your extensionโ€™s manifest or itโ€™s declared as "ids": ["*"], all extensions can connect, but no web pages can connect.
  • If specific IDs are specified, like in "ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], only those applications can connect.
  • If matches are specified, those web apps will be able to connect:
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
  • If itโ€™s specified as empty: "externally_connectable": {}, no app or web will be able to connect.

์—ฌ๊ธฐ์—์„œ ์ง€์ •๋œ extensions ๋ฐ URLs๊ฐ€ ์ ์„์ˆ˜๋ก ๊ณต๊ฒฉ ํ‘œ๋ฉด(attack surface) ์ด ์ž‘์•„์ง‘๋‹ˆ๋‹ค.

Caution

If a web page vulnerable to XSS or takeover is indicated in externally_connectable, an attacker will be able to send messages directly to the background script, completely bypassing the Content Script and its CSP.

Therefore, this is a very powerful bypass.

Moreover, if the client installs a rouge extension, even if it isnโ€™t allowed to communicate with the vulnerable extension, it could inject XSS data in an allowed web page or abuse WebRequest or DeclarativeNetRequest APIs to manipulate requests on a targeted domain altering a pageโ€™s request for a JavaScript file. (Note that CSP on the targeted page could prevent these attacks). This idea comes from this writeup.

ํ†ต์‹  ์š”์•ฝ

Extension <โ€“> WebApp

content script์™€ ์›น ํŽ˜์ด์ง€ ๊ฐ„ ํ†ต์‹ ์—๋Š” ๋ณดํ†ต post messages๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋ณดํ†ต window.postMessage ํ˜ธ์ถœ์„, content script ์ชฝ์—์„œ๋Š” window.addEventListener ๊ฐ™์€ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ extension์ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— Post Message๋ฅผ ๋ณด๋‚ด ํ†ต์‹ ํ•  ์ˆ˜๋„(๋”ฐ๋ผ์„œ ์›น ์ชฝ์—์„œ ์ด๋ฅผ ๋Œ€๋น„ํ•ด์•ผ ํ•จ) ์žˆ๊ณ , ๋‹จ์ˆœํžˆ ์›น์ด ์ƒˆ๋กœ์šด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™•์žฅ ๋‚ด๋ถ€

๋ณดํ†ต ํ™•์žฅ ๋‚ด๋ถ€์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด chrome.runtime.sendMessage ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ(๋Œ€๊ฐœ background script์—์„œ ์ฒ˜๋ฆฌ) ์ด๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด **chrome.runtime.onMessage.addListener**๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฆฌ์Šค๋„ˆ๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

๋‹จ๋ฐœ์„ฑ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ๋Œ€์‹  ์ง€์†์ ์ธ ์—ฐ๊ฒฐ์„ ์œ„ํ•ด **chrome.runtime.connect()**๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ, ๋‹ค์Œ ์˜ˆ์™€ ๊ฐ™์ด ์ด๋ฅผ ์ด์šฉํ•ด messages๋ฅผ send ๋ฐ receive ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

chrome.runtime.connect() example ```javascript var port = chrome.runtime.connect()

// Listen for messages from the web page window.addEventListener( โ€œmessageโ€, (event) => { // Only accept messages from the same window if (event.source !== window) { return }

// Check if the message type is โ€œFROM_PAGEโ€ if (event.data.type && event.data.type === โ€œFROM_PAGEโ€) { console.log(โ€œContent script received: โ€œ + event.data.text) // Forward the message to the background script port.postMessage({ type: โ€œFROM_PAGEโ€, text: event.data.text }) } }, false )

// Listen for messages from the background script port.onMessage.addListener(function (msg) { console.log(โ€œContent script received message from background script:โ€, msg) // Handle the response message from the background script })

</details>

๋˜ํ•œ background script์—์„œ ํŠน์ • ํƒญ์— ์œ„์น˜ํ•œ content script๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด **`chrome.tabs.sendMessage`**๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋•Œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ **ํƒญ์˜ ID**๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

### ํ—ˆ์šฉ๋œ `externally_connectable`์—์„œ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ

**ํ—ˆ์šฉ๋œ Web apps ๋ฐ ์™ธ๋ถ€ ๋ธŒ๋ผ์šฐ์ € ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ**๋Š” `externally_connectable` ๊ตฌ์„ฑ์—์„œ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค :
```javascript
chrome.runtime.sendMessage(extensionId, ...

ํ•„์š”ํ•œ ๊ณณ์—์„œ๋Š” extension ID๋ฅผ ์–ธ๊ธ‰ํ•˜์„ธ์š”.

Native Messaging

๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹œ์Šคํ…œ ๋‚ด๋ถ€์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด ํ†ต์‹ ์ด ์ ์ ˆํžˆ ๋ณดํ˜ธ๋˜์ง€ ์•Š์œผ๋ฉด RCEs์™€ ๊ฐ™์€ ์น˜๋ช…์ ์ธ ์ทจ์•ฝ์ ์— ์ทจ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. More on this later.

chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)

์›น โ†”๏ธŽ Content Script Communication

content scripts๊ฐ€ ๋™์ž‘ํ•˜๋Š” ํ™˜๊ฒฝ๊ณผ ํ˜ธ์ŠคํŠธ ํŽ˜์ด์ง€๊ฐ€ ์กด์žฌํ•˜๋Š” ํ™˜๊ฒฝ์€ ์„œ๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์–ด ๊ฒฉ๋ฆฌ๊ฐ€ ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฉ๋ฆฌ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์–‘์ธก์€ ๊ณต์šฉ ์ž์›์ธ ํŽ˜์ด์ง€์˜ **Document Object Model (DOM)**๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜ธ์ŠคํŠธ ํŽ˜์ด์ง€๊ฐ€ content script์™€ ํ†ต์‹ ํ•˜๊ฑฐ๋‚˜ content script๋ฅผ ํ†ตํ•ด extension๊ณผ ๊ฐ„์ ‘์ ์œผ๋กœ ํ†ต์‹ ํ•˜๋ ค๋ฉด, ์–‘์ธก์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ DOM์„ ํ†ต์‹  ์ฑ„๋„๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Post Messages

// This is like "chrome.runtime.sendMessage" but to maintain the connection
var port = chrome.runtime.connect()

window.addEventListener(
"message",
(event) => {
// We only accept messages from ourselves
if (event.source !== window) {
return
}

if (event.data.type && event.data.type === "FROM_PAGE") {
console.log("Content script received: " + event.data.text)
// Forward the message to the background script
port.postMessage(event.data.text)
}
},
false
)
document.getElementById("theButton").addEventListener(
"click",
() => {
window.postMessage(
{ type: "FROM_PAGE", text: "Hello from the webpage!" },
"*"
)
},
false
)

A secure Post Message communication should check the authenticity of the received message, this can be done checking:

  • event.isTrusted: ์ด ๊ฐ’์€ ์ด๋ฒคํŠธ๊ฐ€ ์‚ฌ์šฉ์ž์˜ ๋™์ž‘์— ์˜ํ•ด ํŠธ๋ฆฌ๊ฑฐ๋œ ๊ฒฝ์šฐ์—๋งŒ True์ž…๋‹ˆ๋‹ค
  • Content Script๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ๋•Œ์—๋งŒ ๋ฉ”์‹œ์ง€๋ฅผ ๊ธฐ๋Œ€ํ•˜๋„๋ก ์„ค๊ณ„๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
  • origin domain: ํŠน์ • ๋„๋ฉ”์ธ๋“ค์˜ allowlist(ํ—ˆ์šฉ ๋ชฉ๋ก)์—๋งŒ ๋ฉ”์‹œ์ง€๋ฅผ ํ—ˆ์šฉํ•˜๋„๋ก ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • If a regex is used, be very careful
  • Source: received_message.source !== window ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฉ”์‹œ์ง€๊ฐ€ Content Script๊ฐ€ ๋ฆฌ์Šค๋‹ ์ค‘์ธ ๋™์ผํ•œ ์ฐฝ์—์„œ ์˜จ ๊ฒƒ์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

The previous checks, even if performed, could be vulnerable, so check in the following page potential Post Message bypasses:

PostMessage Vulnerabilities

Iframe

Another possible way of communication might be through Iframe URLs, you can find an example in:

BrowExt - XSS Example

DOM

This isnโ€™t โ€œexactlyโ€ a communication way, but the web and the content script will have access to the web DOM. So, if the content script is reading some information from it, trusting the web DOM, the web could modify this data (because the web shouldnโ€™t be trusted, or because the web is vulnerable to XSS) and compromise the Content Script.

You can also find an example of a DOM based XSS to compromise a browser extension in:

BrowExt - XSS Example

Content Script โ†”๏ธŽ Background Script Communication

A Content Script can use the functions runtime.sendMessage() or tabs.sendMessage() to send a one-time JSON-serializable message.

To handle the response, use the returned Promise. Although, for backward compatibility, you can still pass a callback as the last argument.

Sending a request from a content script looks like this:

;(async () => {
const response = await chrome.runtime.sendMessage({ greeting: "hello" })
// do something with response here, not outside the function
console.log(response)
})()

extension (๋ณดํ†ต background script)์—์„œ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์„ ํƒ๋œ ํƒญ์˜ content script๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ์˜ˆ:

// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
;(async () => {
const [tab] = await chrome.tabs.query({
active: true,
lastFocusedWindow: true,
})
const response = await chrome.tabs.sendMessage(tab.id, { greeting: "hello" })
// do something with response here, not outside the function
console.log(response)
})()

์ˆ˜์‹  ์ธก์—์„œ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด runtime.onMessage ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋™์ž‘์€ content script๋‚˜ extension page์—์„œ ๋™์ผํ•˜๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค.

// From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
console.log(
sender.tab
? "from a content script:" + sender.tab.url
: "from the extension"
)
if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
})

์œ„ ์˜ˆ์ œ์—์„œ๋Š” **sendResponse()**๊ฐ€ ๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. sendResponse()๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋„๋ก onMessage ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๋ฉด return true;๋ฅผ ๋ฐ˜๋“œ์‹œ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๊ฐ€ onMessage ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๋„๋ก ์„ค์ •๋œ ์ƒํ™ฉ์—์„œ๋Š”, ํŠน์ • ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ๊ฐ€์žฅ ๋จผ์ € sendResponse()๋ฅผ ์‹คํ–‰ํ•œ ํŽ˜์ด์ง€๋งŒ ์‘๋‹ต์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์ดํ›„์˜ ์‘๋‹ต์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

์ƒˆ ํ™•์žฅ ๊ธฐ๋Šฅ์„ ์ž‘์„ฑํ•  ๋•Œ๋Š” promises๋ณด๋‹ค callbacks๋ณด๋‹ค promises๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค. callbacks๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ sendResponse()๋Š” ๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ์ง์ ‘ ์‹คํ–‰๋˜์—ˆ๊ฑฐ๋‚˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ return true;๋กœ ๋น„๋™๊ธฐ ์ž‘์—…์ž„์„ ํ‘œ์‹œํ•œ ๊ฒฝ์šฐ์—๋งŒ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ํ•ธ๋“ค๋Ÿฌ๋„ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ sendResponse()๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ(garbage-collected)๋˜๋ฉด, sendMessage()์— ์ „๋‹ฌ๋œ ์ฝœ๋ฐฑ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

Native Messaging

Browser extensions also allow to communicate with binaries in the system via stdin. The application must install a json indicating so in a json like:

{
"name": "com.my_company.my_application",
"description": "My Application",
"path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
"type": "stdio",
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
}

Where the name is the string passed to runtime.connectNative() or runtime.sendNativeMessage() to communicate with the application from the background scripts of the browser extension. The path is the path to the binary, there is only 1 valid type which is stdio (use stdin and stdout) and the allowed_origins indicate the extensions that can access it (and canโ€™t have wildcard).

Chrome/Chromium will search for this json in some windows registry and some paths in macOS and Linux (more info in the docs).

Tip

The browser extension also needs the nativeMessaing permission declared in order to be able to use this communication.

This is how it looks like some background script code sending messages to a native application:

chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
{ text: "Hello" },
function (response) {
console.log("Received " + response)
}
)

In this blog post, native messages๋ฅผ ์•…์šฉํ•˜๋Š” ์ทจ์•ฝํ•œ ํŒจํ„ด์ด ์ œ์•ˆ๋ฉ๋‹ˆ๋‹ค:

  1. Browser extension has a wildcard pattern for content script.
  2. Content script passes postMessage messages to the background script using sendMessage.
  3. Background script passes the message to native application using sendNativeMessage.
  4. Native application handles the message dangerously, leading to code execution.

๊ทธ๋ฆฌ๊ณ  ์ด ๊ธ€์—๋Š” ์–ด๋–ค ํŽ˜์ด์ง€์—์„œ๋“  browser extension์„ ์•…์šฉํ•ด RCE๋กœ ์ด์–ด์ง€๋Š” ์˜ˆ์ œ๊ฐ€ ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

Sensitive Information in Memory/Code/Clipboard

Browser Extension์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒฝ์šฐ, ํŠนํžˆ Windows ํ™˜๊ฒฝ์—์„œ๋Š” ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ **๋คํ”„(dump)**๋˜์–ด ๊ทธ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ Browser Extension์˜ ๋ฉ”๋ชจ๋ฆฌ๋Š” ์•ˆ์ „ํ•˜๋‹ค๊ณ  ๊ฐ„์ฃผํ•ด์„œ๋Š” ์•ˆ ๋˜๋ฉฐ, ์ž๊ฒฉ ์ฆ๋ช…์ด๋‚˜ ๋‹ˆ๋ชจ๋‹‰ ๋ฌธ๊ตฌ ๊ฐ™์€ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ์ €์žฅํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก , not put sensitive information in the code, ์ด๋Š” **๊ณต๊ฐœ(public)**๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋คํ”„ํ•˜๋ ค๋ฉด ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ๋ฅผ dump the process memoryํ•˜๊ฑฐ๋‚˜ browser extension์˜ settings๋กœ ๊ฐ€์„œ **Inspect pop-up**์„ ํด๋ฆญํ•œ ๋’ค Memory ์„น์…˜์—์„œ **Take a snaphost**๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  **CTRL+F**๋กœ ์Šค๋ƒ…์ƒท ๋‚ด๋ถ€๋ฅผ ๊ฒ€์ƒ‰ํ•˜์—ฌ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ๋‹ˆ๋ชจ๋‹‰ ํ‚ค๋‚˜ ๋น„๋ฐ€๋ฒˆํ˜ธ์ฒ˜๋Ÿผ ๋งค์šฐ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ๋˜์ง€ ์•Š๋„๋ก ํ—ˆ์šฉํ•ด์„œ๋Š” ์•ˆ ๋˜๋ฉฐ(์ ์–ด๋„ ๋ช‡ ์ดˆ ๋‚ด์— ํด๋ฆฝ๋ณด๋“œ์—์„œ ์ œ๊ฑฐํ•ด์•ผ ํ•จ), ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํด๋ฆฝ๋ณด๋“œ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋“ค์ด ์ด๋ฅผ ํš๋“ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Loading an Extension in the Browser

  1. Download the Browser Extension & unzipped
  2. Go to chrome://extensions/ and enable the Developer Mode
  3. Click the Load unpacked button

In Firefox you go to about:debugging#/runtime/this-firefox and click Load Temporary Add-on button.

Getting the source code from the store

Chrome extension์˜ ์†Œ์Šค ์ฝ”๋“œ๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์œผ๋กœ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—๋Š” ๊ฐ ์˜ต์…˜์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…๊ณผ ์ง€์นจ์ด ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค.

Download Extension as ZIP via Command Line

Chrome extension์˜ ์†Œ์Šค ์ฝ”๋“œ๋Š” ์ปค๋งจ๋“œ ๋ผ์ธ์„ ํ†ตํ•ด ZIP ํŒŒ์ผ๋กœ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํŠน์ • URL์—์„œ curl์„ ์‚ฌ์šฉํ•ด ZIP ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ค๊ณ  ZIP ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ถ”์ถœํ•˜๋Š” ๊ณผ์ •์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๋‹จ๊ณ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  1. "extension_id"๋ฅผ ์‹ค์ œ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ID๋กœ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค.
  2. ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:
extension_id=your_extension_id   # Replace with the actual extension ID
curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc"
unzip -d "$extension_id-source" "$extension_id.zip"

CRX Viewer ์›น์‚ฌ์ดํŠธ ์‚ฌ์šฉ

https://robwu.nl/crxviewer/

CRX Viewer ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ์‚ฌ์šฉ

๋˜ ๋‹ค๋ฅธ ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•์€ Chrome Extension Source Viewer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ๋Š” Chrome Web Store์—์„œ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ทฐ์–ด์˜ ์†Œ์Šค ์ฝ”๋“œ๋Š” GitHub repository์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ์ปฌ์— ์„ค์น˜๋œ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ์†Œ์Šค ๋ณด๊ธฐ

Chrome ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ์ปฌ์—์„œ ์„ค์น˜ํ•œ ๊ฒฝ์šฐ์—๋„ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  1. chrome://version/์„ ๋ฐฉ๋ฌธํ•˜์—ฌ Chrome ๋กœ์ปฌ ํ”„๋กœํ•„ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ ‘๊ทผํ•œ ๋‹ค์Œ โ€œProfile Pathโ€ ํ•„๋“œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.
  2. ํ”„๋กœํ•„ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋‚ด์˜ Extensions/ ํ•˜์œ„ ํด๋”๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ด ํด๋”์—๋Š” ์„ค์น˜๋œ ๋ชจ๋“  ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์ด ๋“ค์–ด ์žˆ์œผ๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ํ˜•์‹์œผ๋กœ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ์‹๋ณ„ํ•˜๋ ค๋ฉด ID๋ฅผ ์ด๋ฆ„์— ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • about:extensions ํŽ˜์ด์ง€์—์„œ Developer Mode๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋ฉด ๊ฐ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ID๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ํด๋” ์•ˆ์˜ manifest.json ํŒŒ์ผ์—๋Š” ์ฝ์„ ์ˆ˜ ์žˆ๋Š” name ํ•„๋“œ๊ฐ€ ์žˆ์–ด ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

ํŒŒ์ผ ์••์ถ• ํ•ด์ œ ๋„๊ตฌ ์‚ฌ์šฉ

Chrome Web Store์—์„œ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์šด๋กœ๋“œํ•˜์„ธ์š”. ํŒŒ์ผ์€ .crx ํ™•์žฅ์ž๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ํŒŒ์ผ ํ™•์žฅ์ž๋ฅผ .crx์—์„œ .zip์œผ๋กœ ๋ณ€๊ฒฝํ•œ ํ›„ WinRAR, 7-Zip ๋“ฑ๊ณผ ๊ฐ™์€ ์••์ถ• ํ•ด์ œ ๋„๊ตฌ๋กœ ZIP ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

Chrome์—์„œ Developer Mode ์‚ฌ์šฉ

Chrome์„ ์—ด๊ณ  chrome://extensions/๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ์—์„œ โ€œDeveloper modeโ€œ๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. โ€œLoad unpacked extensionโ€ฆโ€œ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์ด๋ฏธ ๋‹ค์šด๋กœ๋“œํ–ˆ๊ฑฐ๋‚˜ ๊ฐœ๋ฐœ ์ค‘์ธ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๊ธฐ ๋ฐ ์ˆ˜์ •ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

Chrome extension manifest ๋ฐ์ดํ„ฐ์…‹

์ทจ์•ฝํ•œ ๋ธŒ๋ผ์šฐ์ € ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ์ฐพ์•„๋ณด๋ ค๋ฉด thehttps://github.com/palant/chrome-extension-manifests-dataset ์„ ์‚ฌ์šฉํ•˜์—ฌ manifest ํŒŒ์ผ์—์„œ ์ž ์žฌ์  ์ทจ์•ฝ ์ง•ํ›„๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž ์ˆ˜๊ฐ€ 25000๋ช… ์ด์ƒ์ด๊ณ , content_scripts๋ฅผ ํฌํ•จํ•˜๋ฉฐ ๊ถŒํ•œ nativeMessaing์„ ๊ฐ€์ง„ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ํ™•์ธํ•˜๋ ค๋ฉด:

# Query example from https://spaceraccoon.dev/universal-code-execution-browser-extensions/
node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.length > 0 && manifest.permissions?.includes('nativeMessaging')"

Post-exploitation: Forced extension load & persistence (Windows)

์‚ฌ์šฉ์ž๋ณ„ Preferences๋ฅผ ์ง์ ‘ ํŽธ์ง‘ํ•˜๊ณ  ์œ ํšจํ•œ HMACs๋ฅผ ์œ„์กฐํ•˜์—ฌ Chromium์— ๋ฐฑ๋„์–ด๋ฅผ ์‹ฌ๋Š” ์€๋ฐ€ํ•œ ๊ธฐ๋ฒ•์œผ๋กœ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ”„๋กฌํ”„ํŠธ๋‚˜ ํ”Œ๋ž˜๊ทธ ์—†์ด ์ž„์˜์˜ unpacked extension์„ ์ˆ˜๋ฝํ•˜๊ณ  ํ™œ์„ฑํ™”ํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

Forced Extension Load Preferences Mac Forgery Windows

๋ณด์•ˆ ๊ฐ์‚ฌ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

Even though Browser Extensions have a limited attack surface, some of them might contain vulnerabilities or potential hardening improvements. The following ones are the most common ones:

  • ์š”์ฒญ๋œ permissions์„ ๊ฐ€๋Šฅํ•œ ํ•œ ์ œํ•œํ•˜์„ธ์š”.
  • ์š”์ฒญ๋œ **host_permissions**๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ์ œํ•œํ•˜์„ธ์š”.
  • ๊ฐ•๋ ฅํ•œ **content_security_policy**๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • **externally_connectable**๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ์ œํ•œํ•˜์„ธ์š”. ํ•„์š” ์—†๊ณ  ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋‘์ง€ ๋ง๊ณ  **{}**๋กœ ๋ช…์‹œํ•˜์„ธ์š”.
  • ์—ฌ๊ธฐ์—์„œ URL vulnerable to XSS or to takeover๊ฐ€ ์–ธ๊ธ‰๋˜์–ด ์žˆ๋‹ค๋ฉด, ๊ณต๊ฒฉ์ž๋Š” background scripts์— ์ง์ ‘ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋งค์šฐ ๊ฐ•๋ ฅํ•œ ์šฐํšŒ์ž…๋‹ˆ๋‹ค.
  • **web_accessible_resources**๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ์ œํ•œํ•˜์„ธ์š”. ๊ฐ€๋Šฅํ•˜๋ฉด ๋น„์›Œ๋‘์„ธ์š”.
  • **web_accessible_resources**๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด ClickJacking์„ ํ™•์ธํ•˜์„ธ์š”.
  • ํ™•์žฅ์—์„œ ์›น ํŽ˜์ด์ง€๋กœ ์–ด๋–ค communication์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ํ†ต์‹  ๊ณผ์ •์—์„œ ์œ ๋ฐœ๋˜๋Š” XSS vulnerabilities๋ฅผ ํ™•์ธํ•˜์„ธ์š”.
  • Post Messages๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค๋ฉด Post Message vulnerabilities๋ฅผ ํ™•์ธํ•˜์„ธ์š”.
  • Content Script๊ฐ€ DOM ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ ‘๊ทผํ•œ๋‹ค๋ฉด, ์›น์— ์˜ํ•ด modified๋  ๊ฒฝ์šฐ XSS๋ฅผ ๋„์ž…ํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.
  • ์ด ํ†ต์‹ ์ด Content Script -> Background script communication์—๋„ ๊ด€์—ฌ๋˜์–ด ์žˆ๋‹ค๋ฉด ํŠนํžˆ ์ฃผ์˜ํ•˜์„ธ์š”.
  • background script๊ฐ€ native messaging์œผ๋กœ ํ†ต์‹ ํ•œ๋‹ค๋ฉด, ํ†ต์‹ ์ด ์•ˆ์ „ํ•˜๊ณ  ์ž…๋ ฅ์ด ์ ์ ˆํžˆ ์ •์ œ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.
  • Browser Extension์˜ code ๋‚ด๋ถ€์— ๋ฏผ๊ฐํ•œ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
  • Browser Extension์˜ memory ์•ˆ์— ๋ฏผ๊ฐํ•œ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
  • file system unprotected์— ๋ฏผ๊ฐํ•œ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

Browser Extension Risks

  • ์•ฑ https://crxaminer.tech/์€ permissions ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜์—ฌ Browser Extension ์‚ฌ์šฉ์˜ ์œ„ํ—˜ ์ˆ˜์ค€์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Tools

Tarnish

  • ์ œ๊ณต๋œ Chrome webstore ๋งํฌ์—์„œ Chrome extension์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • manifest.json viewer: ํ™•์žฅ์˜ manifest๋ฅผ JSON ํ˜•์‹์œผ๋กœ ๋ณด๊ธฐ ์ข‹๊ฒŒ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  • Fingerprint Analysis: web_accessible_resources๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ž๋™์œผ๋กœ Chrome extension fingerprinting JavaScript๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • Potential Clickjacking Analysis: web_accessible_resources ์ง€์‹œ์–ด๊ฐ€ ์„ค์ •๋œ ํ™•์žฅ HTML ํŽ˜์ด์ง€๋ฅผ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŽ˜์ด์ง€๋“ค์€ ๋ชฉ์ ์— ๋”ฐ๋ผ clickjacking์— ์ทจ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Permission Warning(s) viewer: ํ™•์žฅ ์„ค์น˜ ์‹œ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘œ์‹œ๋˜๋Š” ๋ชจ๋“  Chrome ๊ถŒํ•œ ํ”„๋กฌํ”„ํŠธ ๊ฒฝ๊ณ  ๋ชฉ๋ก์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  • Dangerous Function(s): innerHTML, chrome.tabs.executeScript ๊ฐ™์€ ๊ณต๊ฒฉ์ž๊ฐ€ ์•…์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ„ํ—˜ํ•œ ํ•จ์ˆ˜์˜ ์œ„์น˜๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  • Entry Point(s): ํ™•์žฅ์ด ์‚ฌ์šฉ์ž/์™ธ๋ถ€ ์ž…๋ ฅ์„ ๋ฐ›๋Š” ์œ„์น˜๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ™•์žฅ์˜ ๊ณต๊ฒฉ ํ‘œ๋ฉด์„ ์ดํ•ดํ•˜๊ณ  ์•…์˜์ ์œผ๋กœ ์กฐ์ž‘๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” ์ž ์žฌ ์ง€์ ์„ ์ฐพ๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • Dangerous Function(s) ๋ฐ Entry Point(s) ์Šค์บ๋„ˆ์—์„œ ์ƒ์„ฑ๋œ ๊ฒฝ๊ณ ์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค:
    • ๊ฒฝ๊ณ ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ ๊ด€๋ จ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ๊ณผ ๋ผ์ธ.
    • ๋ฌธ์ œ ์„ค๋ช….
    • ์ „์ฒด ์†Œ์Šค ํŒŒ์ผ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š” โ€œView Fileโ€ ๋ฒ„ํŠผ.
    • ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•œ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ.
    • ํ•ด๋‹น ํŒŒ์ผ์˜ ์ „์ฒด Chrome extension URI.
    • Background Page script, Content Script, Browser Action ๋“ฑ ํŒŒ์ผ ์œ ํ˜•.
    • ์ทจ์•ฝํ•œ ๋ผ์ธ์ด JavaScript ํŒŒ์ผ์ธ ๊ฒฝ์šฐ, ํ•ด๋‹น ํŒŒ์ผ์ด ํฌํ•จ๋œ ๋ชจ๋“  ํŽ˜์ด์ง€์˜ ๊ฒฝ๋กœ์™€ ํŽ˜์ด์ง€ ์œ ํ˜• ๋ฐ web_accessible_resource ์ƒํƒœ.
  • Content Security Policy (CSP) analyzer and bypass checker: ํ™•์žฅ์˜ CSP ์•ฝ์ ์„ ์ง€์ ํ•˜๊ณ , ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ๋œ CDN ๋“ฑ์œผ๋กœ ์ธํ•ด CSP๋ฅผ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์„ ๋ฐํž™๋‹ˆ๋‹ค.
  • Known Vulnerable Libraries: Retire.js๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•Œ๋ ค์ง„ ์ทจ์•ฝ JavaScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์„ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค.
  • ํ™•์žฅ ๋‹ค์šด๋กœ๋“œ ๋ฐ ํฌ๋งคํŒ…๋œ ๋ฒ„์ „ ์ œ๊ณต.
  • ์›๋ณธ ํ™•์žฅ ๋‹ค์šด๋กœ๋“œ.
  • ์˜ˆ์˜๊ฒŒ ์ •๋ฆฌ๋œ(beautified) ํ™•์žฅ ๋ฒ„์ „ ๋‹ค์šด๋กœ๋“œ(์ž๋™์œผ๋กœ prettified๋œ HTML ๋ฐ JavaScript).
  • ์Šค์บ” ๊ฒฐ๊ณผ ์ž๋™ ์บ์‹œ: ์ฒ˜์Œ ์Šค์บ”์€ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ์ง€๋งŒ, ํ™•์žฅ์ด ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๋‘ ๋ฒˆ์งธ ์Šค์บ”์€ ๊ฒฐ๊ณผ๊ฐ€ ์บ์‹œ๋˜์–ด ๊ฑฐ์˜ ์ฆ‰์‹œ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.
  • ๋งํฌ ๊ฐ€๋Šฅํ•œ ๋ฆฌํฌํŠธ URL: tarnish๋กœ ์ƒ์„ฑ๋œ ํ™•์žฅ ๋ฆฌํฌํŠธ๋ฅผ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์—๊ฒŒ ์‰ฝ๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Neto

Project Neto๋Š” Firefox ๋ฐ Chrome๊ณผ ๊ฐ™์€ ์ž˜ ์•Œ๋ ค์ง„ ๋ธŒ๋ผ์šฐ์ €์šฉ ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ํ™•์žฅ์˜ ์ˆจ๊ฒจ์ง„ ๊ธฐ๋Šฅ์„ ๋ถ„์„ํ•˜๊ณ  ์ถ”์ถœํ•˜๋„๋ก ๊ณ ์•ˆ๋œ Python 3 ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค. ํŒจํ‚ค์ง€๋œ ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ ์••์ถ• ํ•ด์ œํ•˜๊ณ  manifest.json, ์ง€์—ญํ™” ํด๋”(localization folders) ๋˜๋Š” Javascript ๋ฐ HTML ์†Œ์Šค ํŒŒ์ผ ๊ฐ™์€ ๊ด€๋ จ ๋ฆฌ์†Œ์Šค์—์„œ ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์„ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

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 ์ง€์›ํ•˜๊ธฐ