Jastes 2022. 6. 20. 22:50


Mitigation: Same Origin Policy

SOP์— ๋Œ€ํ•˜์—ฌ

์ด์ „๊นŒ์ง€์˜ ์ฟ ํ‚ค์™€ ์„ธ์…˜์— ๊ด€ํ•œ ๋‚ด์šฉ์€ ๊ธฐ๋ณธ์ ์ด๋ผ์„œ ์ €์˜ ์ •๋ฆฌ๋ณด๋‹จ ์ง์ ‘ ๋ฐฐ์šฐ๋ฉด์„œ ํ•˜๋Š”๊ฒŒ ์ข‹์•„๋ณด์—ฌ์„œ..
์‚ฌ์‹ค ๊ท€์ฐฎ์•„์„œ๊ฐ€ ์ œ์ผ ํฐ๋ฐ ใ…‹ใ…‹

 

์›น์˜ ์ดํ•ด์™€ HTTP

๐Ÿ’กํ•ด๋‹น ๋‚ด์šฉ์€ pentestqym์˜ ๋‚ด์šฉ์„ ๋‹ค์‹œ ํ•œ ๋ฒˆ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ด๋ฉฐ, ๋ชจ๋“  ์ €์ž‘๊ถŒ์€ ํ•ด๋‹น ์‚ฌ์ดํŠธ์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค. ์›น(Web)์ด๋ž€? ์›น์€ World Wide Web์˜ ์•ฝ์ž๋กœ, ์ธํ„ฐ๋„ท, ํ•˜์ดํผ๋งํฌ ๋“ฑ์„ ํ†ตํ•ด ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๊ณ 

dystopia050119.tistory.com

 

 

์ฟ ํ‚ค์™€ ์„ธ์…˜

๐Ÿ’กํ•ด๋‹น ๋‚ด์šฉ์€ pentestqym์˜ ๋‚ด์šฉ์„ ๋‹ค์‹œ ํ•œ ๋ฒˆ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ด๋ฉฐ, ๋ชจ๋“  ์ €์ž‘๊ถŒ์€ ํ•ด๋‹น ์‚ฌ์ดํŠธ์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฟ ํ‚ค(Cookie)๋ž€? ์ฟ ํ‚ค๋Š” ์›น ์„œ๋ฒ„๊ฐ€ ์ƒ์„ฑํ•˜์—ฌ ์›น ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „์†กํ•˜๋Š” ์ž‘์€ ์ •๋ณด ํŒŒ์ผ์ž…๋‹ˆ

dystopia050119.tistory.com

์—ฌ๊ธฐ ๋งํฌ๋ฅผ ํ†ตํ•ด ๊ผญ ํ•™์Šตํ•ด๋ด…์‹œ๋‹ค! ์•„๋ž˜ ๋งํฌ ๋“ค์–ด๊ฐ€์„œ ๋ฌธ์ œ๋„ ํ•˜์‹œ๊ณ 
์ฟ ํ‚ค & ์„ธ์…˜

 

๋ฐ”๋กœ SOP์— ๋Œ€ํ•˜์—ฌ ๋ฐฐ์›Œ๋ด…์‹œ๋‹ค.


์ฟ ํ‚ค์—๋Š” ์ธ์ฆ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฏผ๊ฐํ•œ ์ •๋ณด๊ฐ€ ๋ณด๊ด€๋˜๋ฉฐ, ๋ธŒ๋ผ์šฐ์ € ๋‚ด๋ถ€์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์›น ์„œ๋น„์Šค์— ์ ‘์† ์‹œ ์ž๋™์œผ๋กœ ์ฟ ํ‚ค๋ฅผ ํ—ค๋”์— ํฌํ•จํ•ด ์š”์ฒญ์„ ๋ณด๋‚ด์ฃ 

 

์ด ๋•๋ถ„์— ์šฐ๋ฆฌ๋Š” ์›น ์„œ๋น„์Šค์— ํ•œ ๋ฒˆ ๋กœ๊ทธ์ธ ํ›„ ์ผ์ • ๊ธฐ๊ฐ„์€ ๋กœ๊ทธ์ธ ์—†์ด ๋ฐ”๋กœ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๊ฑฐ์ฃ 
๊ทธ๋Ÿฌ๋‚˜ ๋งŒ์•ฝ ์ด์šฉ์ž๊ฐ€ ์•…์˜์ ์ธ ๋ชฉ์ ์œผ๋กœ ์•…์˜์ ์ธ ํŽ˜์ด์ง€๋ฅผ ์ ‘์† ์‹œ ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

SOP(Same Origin Policy) ํƒ„์ƒ ๋ฐฐ๊ฒฝ
์•…์˜์ ์ธ ํŽ˜์ด์ง€ ์ ‘์† → ๋งŒ์•ฝ JS ์ด์šฉ ์ด์šฉ์ž์˜ SNS ์›น ์„œ๋น„์Šค๋กœ ์š”์ฒญ ์‹œ..
→ ๋ธŒ๋ผ์šฐ์ €๋Š” ์š”์ฒญ ๋ณด๋‚ผ ๋•Œ ํ•ด๋”์— ํ•ด๋‹น ์›น ์„œ๋น„์Šค ์ฟ ํ‚ค๋ฅผ ํฌํ•จ์‹œํ‚ด..


 ๋”ฐ๋ผ์„œ JS๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ํŽ˜์ด์ง€๋Š” ๋กœ๊ทธ์ธ ๋œ ์ด์šฉ์ž์˜ SNS ์‘๋‹ต์„ ๋ฐ›์Œ
๊ทธ๋ž˜์„œ ์„ธ์…˜ ํ•˜์ด์ œํ‚น ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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


Same Origin Policy (SOP)

์„œ๋ก ์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ธ์ฆ ์ •๋ณด๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ์ฟ ํ‚ค๋ฅผ ๋ธŒ๋ผ์šฐ์ € ๋‚ด๋ถ€์— ๋ณด๊ด€ํ•˜๋ฉฐ ๋˜ํ•œ
์ด์šฉ์ž๊ฐ€ ์›น ์„œ๋น„์Šค ์ ‘์† ์‹œ, ๋ธŒ๋ผ์šฐ์ €๋Š” ํ•ด๋‹น ์›น ์„œ๋น„์Šค์— ์‚ฌ์šฉ๋˜๋Š” ์ธ์ฆ ์ •๋ณด ์ฟ ํ‚ค๋ฅผ http์š”์ฒญ ํฌํ•จ

 

์ด ํŠน์ง•์€ ์‚ฌ์ดํŠธ์— ์ง์ ‘ ์ ‘์†ํ•˜๋Š” ๊ฒƒ์—๋งŒ ํ•œ์ • X
๋ธŒ๋ผ์šฐ์ €๋Š” ์›น ๋ฆฌ์†Œ์Šค๋ฅผ ํ†ตํ•ด ๊ฐ„์ ‘์ ์œผ๋กœ ํƒ€ ์‚ฌ์ดํŠธ์— ์ ‘๊ทผ ์‹œ์—๋„ ์ธ์ฆ ์ •๋ณด ์ฟ ํ‚ค๋ฅผ ํ•จ๊ป˜ ์ „์†กํ•จ

์ด ํŠน์ง• ๋•œ์— ์•…์˜์  ํŽ˜์ด์ง€๊ฐ€ ํด๋ผ์ด์–ธํŠธ์˜ ๊ถŒํ•œ์„ ์ด์šฉํ•ด
๋Œ€์ƒ ์‚ฌ์ดํŠธ์— ํ•ด๋” ์š”์ฒญ์„ ๋ณด๋‚ด
์‘๋‹ต ์ •๋ณด๋ฅผ ํš๋“ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰

์ด๋Š” ์ •๋ณด ์œ ์ถœ๊ณผ ๊ฐ™์€ ๋ณด์•ˆ ์ด์Šˆ๋กœ ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์•…์˜์  ํŽ˜์ด์ง€๊ฐ€
๋ชป ์ฝ๊ฒŒ ํ•ด์•ผ๊ฒ ์ฃ  ๊ทธ๋ž˜์„œ ๋‚˜์˜จ ๋ธŒ๋ผ์šฐ์ €์˜ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ธ SOP์ž…๋‹ˆ๋‹ค.


Same Origin Policy์˜ Origin ๊ตฌ๋ถ„ ๋ฐฉ๋ฒ•

์ด์ œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ฐ€์ ธ์˜จ ์ •๋ณด์ธ ์˜ค๋ฆฌ์ง„(Origin)์„ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ถ„ํ• ๊นŒ์š”?
๋จผ์ € ์˜ค๋ฆฌ์ง„์€ ํ”„๋กœํ† ์ฝœ(Protocol, Scheme), ํฌํŠธ(Port), ํ˜ธ์ŠคํŠธ(Host)๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

 

๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ชจ๋‘ ์ผ์น˜ํ•ด์•ผ ๋™์ผํ•œ ์˜ค๋ฆฌ์ง„์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
https://same-origin.com/ ๋ผ๋Š” ์˜ค๋ฆฌ์ง„๊ณผ ์•„๋ž˜ URL์„ ๋น„๊ตํ–ˆ์„ ๋•Œ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.


์œ„์™€ ๊ฐ™์ด ๋น„๊ตํ•ด์„œ ํ™•์ธํ•œ๋‹ต๋‹ˆ๋‹ค!


Same Origin Policy ์‹ค์Šต

SOP๋Š” Cross Origin์ด ์•„๋‹Œ Same Origin์ผ ๋•Œ๋งŒ ์ •๋ณด๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค.
์˜ˆ์‹œ๋กœ ์•„๋ž˜ ์ด๋ฏธ์ง€๊ฐ€ ์žˆ์œผ๋ฉฐ JavaScript์˜ ์ด์šฉํ•ด SOP๋ฅผ ํ…Œ์ŠคํŠธ ํ•˜๋„ค์š”

 

์—ฌ๊ธฐ์„œ window.open์€ ์ƒˆ ์ฐฝ ๋„์šฐ๋Š” ํ•จ์ˆ˜, object.location.href๋Š” ๊ฐ์ฒด๊ฐ€ ๊ฐ€๋ฅดํ‚จ URL ์ฃผ์†Œ ์ฝ๋Š” ์ฝ”๋“œ

์ด์ œ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋ฅผ ์ผœ์„œ ์‹ค์Šตํ•ด๋ณด์„ธ์š” ํ•ด๋‹น ๊ฒฐ๊ณผ์ฐฝ์€ ์ง์ ‘ํ•ด๋ณด์‹œ๋ฉด์„œ ํ™•์ธํ•ด๋ณด์„ธ์š”
๊ทธ๋Ÿฌ์‹œ๋ฉด ์™ค์ผ€ ์„ฑ์˜๊ฐ€ ์—†๋ƒ.. ๋ผ๊ณ  ํ•˜๋ฉด ์ด๊ฑด ๋ถ€์ „๊ณต์ด๊ธฐ์— ์ƒ์„ธํžˆ ์„ธ๋ฐ€ํ•˜๊ฒŒ ํ•˜๊ธด.. ํž˜๋“ค์–ด์„œ์š” ใ… 


Same Origin Policy(SOP) ๋ฐ๋ชจ

์ง€๊ธˆ๊นŒ์ง€ SOP๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ดค๊ณ  ๊ตฌ๋ถ„๊นŒ์ง€ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.
์ด์ œ ๋‹ค์Œ ๋ชจ๋“ˆ ๊ตฌ์„ฑ์œผ๋กœ ์‹ค์Šตํ•ด๋ณด๊ธฐ ์ „์— ์‚ดํŽด๋ด…์‹œ๋‹ค.

<!-- iframe ๊ฐ์ฒด ์ƒ์„ฑ -->
<iframe src="" id="my-frame"></iframe>
 
<!-- Javascript ์‹œ์ž‘ -->
<script>
/* 2๋ฒˆ์งธ ์ค„์˜ iframe ๊ฐ์ฒด๋ฅผ myFrame ๋ณ€์ˆ˜์— ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. */
let myFrame = document.getElementById('my-frame')
 
/* iframe ๊ฐ์ฒด์— ์ฃผ์†Œ๊ฐ€ ๋กœ๋“œ๋˜๋Š” ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. */
myFrame.onload = () => {
    /* try ... catch ๋Š” ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง ์ž…๋‹ˆ๋‹ค. */
    try {
        /* ๋กœ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด, secret-element ๊ฐ์ฒด์˜ ๋‚ด์šฉ์„ ์ฝ˜์†”์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. */
        let secretValue = myFrame.contentWindow.document.getElementById('secret-element').innerText;
        console.log({ secretValue });
    } catch(error) {
        /* ์˜ค๋ฅ˜ ๋ฐœ์ƒ์‹œ ์ฝ˜์†”์— ์˜ค๋ฅ˜ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. */
        console.log({ error });
    }
}
 
/* iframe๊ฐ์ฒด์— Same Origin, Cross Origin ์ฃผ์†Œ๋ฅผ ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜ ์ž…๋‹ˆ๋‹ค. */
const loadSameOrigin = () => { myFrame.src = 'https://same-origin.com/frame.html'; }
const loadCrossOrigin = () => { myFrame.src = 'https://cross-origin.com/frame.html'; }
</script>
 
<!--
๋ฒ„ํŠผ 2๊ฐœ ์ƒ์„ฑ (Same Origin ๋ฒ„ํŠผ, Cross Origin ๋ฒ„ํŠผ)
-->
<button onclick=loadSameOrigin()>Same Origin</button><br>
<button onclick=loadCrossOrigin()>Cross Origin</button>
 
<!--
frame.html์˜ ์ฝ”๋“œ๊ฐ€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
secret-element๋ผ๋Š” id๋ฅผ ๊ฐ€์ง„ div ๊ฐ์ฒด ์•ˆ์— treasure๋ผ๊ณ  ํ•˜๋Š” ๋น„๋ฐ€ ๊ฐ’์„ ๋„ฃ์–ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค.
-->
 
<div id="secret-element">treasure</div>

์ฝ”๋“œ ๋™์ž‘ ์„ค๋ช…

  1.  ๋‘๋ฒˆ ์ค„์˜ iframe ํ˜„์žฌ ์›น ํŽ˜์ด์ง€ ์•ˆ์— ๋˜ ๋‹ค๋ฅธ ์›น ํŽ˜์ด์ง€ ์‚ฝ์ž…ํ•˜๋Š” HTML ํƒœ๊ทธ
    src ์š”์†Œ๋ฅผ ์„ค์ •ํ•จ์œผ๋กœ์จ ์‚ฝ์ž…ํ•  ์›น ํŽ˜์ด์ง€์˜ ์ฃผ์†Œ๊ฐ€ ๊ฒฐ์ •๋จ!

  2.  ์—ด๋ฒˆ์งธ ์ค„์˜ onload ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ, ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ์„ฑ๊ณต์  ๋กœ๋“œ ์‹œ ๋™์ž‘
    ๋ณธ ์˜ˆ์‹œ์—” 10-24๋ฒˆ ์ค„์ด iframe ๊ฐ์ฒด์˜ ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ ์‹œ ๋™์ž‘๋˜๋Š” ์ฝ”๋“œ!

  3.  14-15๋ฒˆ์งธ ์ค„์€ ๋กœ๋“œ ์™„๋ฃŒ ์‹œ iframe ๋‚ด์— ์‚ฝ์ž…๋œ ์ฃผ์†Œ secret-element ๊ฐ์ฒด์˜ ๊ฐ’์ธ
    treasure๋ฅผ ์ฝ์–ด์™€ ์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๋Š” ๋™์ž‘ ์ˆ˜ํ–‰!

๊ทผ๋ฐ ์‚ฌ์‹ค ์œ„ ์ฝ”๋“œ์˜ ๋‚ด์šฉ์€ Dreamhack ๋กœ๋“œ๋งต์—์„œ ์‹ค์Šต ์›น ํŽ˜์ด์ง€์˜ ์ฝ”๋“œ๋ผ์„œ.. ๋”ฑํžˆ
์„ฑ๊ณต๊ณผ ์‹คํŒจ์˜ ๋ชจ์Šต๋งŒ ์ด๋ฏธ์ง€๋กœ ๋ณด์—ฌ๋“œ๋ฆด๊ป˜์š” ใ… 

์™ผ์ชฝ์€ ์„ฑ๊ณต ์˜ค๋ฅธ์ชฝ์€ ์‹คํŒจ

์œ„ ์›น์€ SOP์—์„œ iframe์— Same Origin์ด ์•„๋‹Œ Cross Origin์„ ๋„ฃ์œผ๋ฉด
์„ธ๋ฒˆ์งธ ๋™์ž‘ ๊ณผ์ •์ด ์‹คํŒจ๋กœ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ์œ„์— ์ฝ”๋“œ ๋ณด์‹œ๋ฉด ๋˜๊ฒ ์ฃ ?


Same Origin Policy ์ œ์•ˆ ์™„ํ™”

SOP๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ์›น ๋ณด์•ˆ์—์„œ ์ค‘์š”ํ•œ ์š”์†Œ์ž…๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด๋Ÿฌํ•œ SOP์— ๊ตฌ์•  ๋ฐ›์ง€ ์•Š๊ณ  ์™ธ๋ถ€ ์ถœ์ฒ˜์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์ฃ 

 

์˜ˆ๋ฅผ ๋“ค๋ฉด, ์ด๋ฏธ์ง€๋‚˜ JS, CSS ๋“ฑ์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” <img>, <style>, <script> ๋“ฑ์˜ ํƒœ๊ทธ๊ฐ€ ์žˆ์ฃ 

 

์œ„ ๊ฒฝ์šฐ๋“ค ์™ธ์—๋„ ์›น ์„œ๋น„์Šค์— SOP๋ฅผ ์™„ํ™”ํ•˜์—ฌ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌ ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋กœ ํŠน์ • ํฌํ„ธ ์‚ฌ์ดํŠธ ์นดํŽ˜, ๋ธ”๋กœ๊ทธ ๋“ฑ์˜ ์ฃผ์†Œ๋กœ ์šด์˜ ์‹œ ๊ฐ ์„œ๋น„์Šค Host๊ฐ€ ๋‹ค๋ฅด๋‹ˆ๊นŒ ์˜ค๋ฆฌ์ง„์ด ๋‹ค๋ฅด๊ฒ ์ฃ ?

์œ„๋Š” Theori์˜ ํšŒ์‚ฌ์ธก์—์„œ.. ์Œ Dreamhack ๋ถ€์† ์‚ฌ์ดํŠธ๋“ค์˜ ์˜ˆ์ œ์ธ๋“ฏ ์‹ถ๋„ค์š” ์จ‹๋“ 

 

์ด๋Ÿฌํ•œ ํ™˜๊ฒฝ์—์„œ, ์ด์šฉ์ž๊ฐ€ ์ˆ˜์‹ ํ•œ ๋ฉ”์ผ์˜ ๊ฐœ์ˆ˜๋ฅผ ๋ฉ”์ธ ํŽ˜์ด์ง€์— ์ถœ๋ ฅํ• ๋ ค๋ฉด SOP๋ฅผ ํ—ˆ๋ฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด ๋•Œ, ๋‘ ์‚ฌ์ดํŠธ๋Š” ์˜ค๋ฆฌ์ง„์ด ๋‹ค๋ฅด๋ฏ€๋กœ SOP๋ฅผ ์ ์šฉ๋ฐ›์ง€ ์•Š๊ณ  ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณต์œ ํ•  ๋ฐฉ๋ฒ•์ด ์š”๊ตฌ๋จ!

 

๊ทธ๋ž˜์„œ ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (Cross Origin Resource Sharing; CORS)๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
๊ณต์œ  ๋ฐฉ๋ฒ•์€ CORS์™€ ๊ด€๋ จ๋œ HTTP ํ•ด๋”๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ „์†กํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๊ทธ ์™ธ์—๋„ JSON with Padding(JSONP) ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค


Cross Origin Resource Sharing(CORS)

CORS๋Š” HTTP ํ•ด๋” ๊ธฐ๋ฐ˜ Cross Origin ๊ฐ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณต์œ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
๋ฐœ์‹ ์ธก์— CORS ํ•ด๋”๋ฅผ ์„ค์ •ํ•ด ์š”์ฒญ ์‹œ, ์ˆ˜์‹ ์ธก์€ ํ—ค๋”๋ฅผ ๊ตฌ๋ถ„ํ•ด ์ •ํ•ด์ง„ ๊ทœ์น™์— ์˜ํ•ด ๋ฐ์ดํ„ฐ ๊ณต์œ !

 

์•„๋ž˜ ๋‘ ์ด๋ฏธ์ง€๋Š” ๊ฐ๊ฐ ์›น ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๋Š” ๋ฐœ์‹ ์ธก ์ฝ”๋“œ์˜ ์ผ๋ถ€์™€ ๋ฐœ์‹ ์ธก์˜ HTTP์š”์ฒญ์ž…๋‹ˆ๋‹ค.

์›น ๋ฆฌ์†Œ์Šค ์š”์ฒญ ์ฝ”๋“œ
/*
    XMLHttpRequest ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. 
    XMLHttpRequest๋Š” ์›น ๋ธŒ๋ผ์šฐ์ €์™€ ์›น ์„œ๋ฒ„ ๊ฐ„์— ๋ฐ์ดํ„ฐ ์ „์†ก์„
    ๋„์™€์ฃผ๋Š” ๊ฐ์ฒด ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด HTTP ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
*/
 
xhr = new XMLHttpRequest();

/* https://theori.io/whoami ํŽ˜์ด์ง€์— POST ์š”์ฒญ์„ ๋ณด๋‚ด๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. */
xhr.open('POST', 'https://theori.io/whoami');

/* HTTP ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ, ์ฟ ํ‚ค ์ •๋ณด๋„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค. */
xhr.withCredentials = true;

/* HTTP Body๋ฅผ JSON ํ˜•ํƒœ๋กœ ๋ณด๋‚ผ ๊ฒƒ์ด๋ผ๊ณ  ์ˆ˜์‹ ์ธก์— ์•Œ๋ ค์ค๋‹ˆ๋‹ค. */
xhr.setRequestHeader('Content-Type', 'application/json');

/* xhr ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด HTTP ์š”์ฒญ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. */
xhr.send("{'data':'WhoAmI'}");
๋ฐœ์‹ ์ธก์˜ HTTP ์š”์ฒญ
OPTIONS /whoami HTTP/1.1
Host: theori.io
Connection: keep-alive
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: https://dreamhack.io
Accept: */*
Referer: https://dreamhack.io/

๊ทธ๋Ÿผ ์ž…๋ ฅ๋ฐ›์€ ํ•ด๋”์˜ ๋Œ€ํ•œ ์ •๋ณด์— ๋Œ€ํ•˜์—ฌ ์•Œ์•„๊ฐ€๋ณด๋ฉฐ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค.

 

ํ‘œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, ๋ฐœ์‹ ์ธก์—์„œ POST๋ฐฉ์‹์œผ๋กœ HTTP ์š”์ฒญ์„ ๋ณด๋ƒˆ์œผ๋‚˜,
OPTIONS ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์ง„ HTTP ์š”์ฒญ์ด ์ „๋‹ฌ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฅผ CORS preflight๋ผ๊ณ  ํ•˜๋ฉฐ, ์ˆ˜์‹ ์ธก์— ์›น ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•ด๋„ ๋˜๋Š”์ง€ ์งˆ์˜ํ•˜๋Š” ๊ณผ์ •!
๊ทธ๋ฆฌ๊ณ  ์œ„์— 2๋ฒˆ์งธ ์ฝ”๋“œ๋ฅผ ๋ณด์‹œ๋ฉด "Access-Control-Request"๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ—ค๋”๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค

 

ํ•ด๋‹น ํ—ค๋” ๋’ค์— ๋”ฐ๋ผ์˜ค๋Š” Method์™€ Headers๋Š” ๊ฐ ๋ฉ”์†Œ๋“œ์™€ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์งˆ์˜ํ•จ!
๋˜ํ•œ ์œ„์ฒ˜๋Ÿผ ์งˆ์˜ ์‹œ ์„œ๋ฒ„๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์‘๋‹ตํ•˜๋ฉฐ, ๋‹ค์Œ์€ ์‘๋‹ต ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์„ค๋ช…์ž…๋‹ˆ๋‹ค.

์„œ๋ฒ„์˜ ์‘๋‹ต
OPTIONS /whoami HTTP/1.1
Host: theori.io
Connection: keep-alive
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: https://dreamhack.io
Accept: */*
Referer: https://dreamhack.io/

์ดํ•ด ์ž๋ฃŒ

์œ„ ๊ณผ์ •์„ ๋งˆ์น˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” ์ˆ˜์‹ ์ธก์˜ ์‘๋‹ต์ด ๋ฐœ์‹ ์ธก์˜ ์š”์ฒญ๊ณผ ์ƒ์‘ํ•œ๊ฐ€ ํ™•์ธํ•˜๊ณ ,
๊ทธ๋•Œ์•ผ ๋น„๋กœ์†Œ POST ์š”์ฒญ์„ ๋ณด๋‚ด ์ˆ˜์‹ ์ธก์˜ ์›น ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๋Š” HTTP ์š”์ฒญ์„ ๋ณด๋ƒ„


JSON with Padding(JSONP)

์•„๊นŒ ์ด๋ฏธ์ง€, JS, CSS ๋“ฑ์˜ ๋ฆฌ์†Œ์Šค๋Š” SOP์— ๊ตฌ์•  X, ์™ธ๋ถ€ ์ถœ์ฒ˜ ์ ‘๊ทผ ํ—ˆ์šฉํ•œ๋‹ค๊ณ  ํ–ˆ์ฃ 

 

JSONP ๋ฐฉ์‹์€ ์ด๋Ÿฌํ•œ ํŠน์ง• ํ™œ์šฉ <script> ํƒœ๊ทธ๋กœ Cross Origin์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ˜ธ์ถœ
ํ•˜์ง€๋งŒ <script> ํƒœ๊ทธ ๋‚ด์—” ๋ฐ์ดํ„ฐ๋ฅผ JS ์ฝ”๋“œ๋กœ ์ธ์‹ํ•˜๊ธฐ์— Callback ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

Cross Origin์— ์š”์ฒญ ์‹œ callback ํŒŒ๋ผ๋ฏธํ„ฐ์— ์–ด๋–ค ํ•จ์ˆ˜๋กœ ๋ฐ›์•„์˜ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ•ธ๋“ค๋งํ• ์ง€ ๋„˜๊ฒจ์ฃผ๋ฉด,
๋Œ€์ƒ ์„œ๋ฒ„๋Š” ์ „๋‹ฌ๋œ Callback์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์‹ธ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

์›น ๋ฆฌ์†Œ์Šค ์š”์ฒญ ์ฝ”๋“œ
<script>

/* myCallback์ด๋ผ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. */
function myCallback(data){

	/* ์ „๋‹ฌ๋ฐ›์€ ์ธ์ž์—์„œ id๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.*/
    console.log(data.id)

}

</script>

<!--
https://theori.io์˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•˜๋Š” HTML ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
๋‹จ, callback์ด๋ผ๋Š” ์ด๋ฆ„์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ myCallback์œผ๋กœ ์ง€์ •ํ•จ์œผ๋กœ์จ
์ˆ˜์‹ ์ธก์—๊ฒŒ myCallback ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ˆ˜์‹ ๋ฐ›๊ฒ ๋‹ค๊ณ  ์•Œ๋ฆฝ๋‹ˆ๋‹ค.
-->
<script src='http://theori.io/whoami?callback=myCallback'></script>
์›น ๋ฆฌ์†Œ์Šค ์š”์ฒญ์— ๋”ฐ๋ฅธ ์‘๋‹ต ์ฝ”๋“œ
/*
์ˆ˜์‹ ์ธก์€ myCallback ์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์š”์ฒญ์ธก์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ๋Š” ํ˜„์žฌ theori.io์—์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‚ฌ์šฉ ์ค‘์ธ ๊ณ„์ • ์ •๋ณด์ธ
{'id': 'dreamhack'} ์ž…๋‹ˆ๋‹ค. 
*/

myCallback({'id':'dreamhack'});

์œ„์— ์˜ˆ์‹œ ์ฝ”๋“œ๋Š” <script src=.. ๋ถ€๋ถ„์— Cross Origin์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
์ด๋•Œ callback ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ myCallback์„ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜์ฃ 

 

Cross Origin์— ์‘๋‹ตํ•  ๋ฐ์ดํ„ฐ๋ฅผ myCallback ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋„๋ก myCallback์œผ๋กœ ๊ฐ์‹ธ
JavaScript ์ฝ”๋“œ๋กœ ๋ฐ˜ํ™˜, ๋ฐ˜ํ™˜ ์ฝ”๋“œ๋Š” ์š”์ฒญ์ธก์— ์‹คํ–‰๋˜๊ธฐ์— 3-6๋ฒˆ ์ค„์— ์ •์˜๋œ ํ•จ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋œ ๋ฐ์ดํ„ฐ ์ฝ์Œ

 

๋‹ค๋งŒ JSONP๋Š” CORS๊ฐ€ ์ƒ๊ธฐ๊ธฐ์ „์— ์‚ฌ์šฉ๋œ ๊ฑฐ๋ผ ์š”์ฆ˜์€ ์‚ฌ์šฉ ์•ˆํ•ด์š” ใ…Ž


ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ

 

  • Same Origin Policy (SOP): ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…
    - ํ˜„์žฌ ํŽ˜์ด์ง€์˜ ์ถœ์ฒ˜๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ๋ถ€ํ„ฐ ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜
  • Same Origin: ํ˜„์žฌ ํŽ˜์ด์ง€์™€ ๋™์ผํ•œ ์ถœ์ฒ˜
  • Cross Origin: ํ˜„์žฌ ํŽ˜์ด์ง€์™€ ๋‹ค๋ฅธ ์ถœ์ฒ˜
  • Cross Origin Resource Sharing (CORS)๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ 
    - SOP์˜ ์ œํ•œ์„ ๋ฐ›์ง€ ์•Š๊ณ  Cross Origin์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜

์ฐธ๊ณ  ์ž๋ฃŒ

 

Mitigation: Same Origin Policy

์ด ์ฝ”์Šค์—์„œ๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ๋ณด์•ˆ ๋งค์ปค๋‹ˆ์ฆ˜์ธ SOP์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

dreamhack.io

์ฐธ๊ณ  ์ด๋ฏธ์ง€