์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ํ ์ฝํ ์ธ ๋ณด์ ์ ์ฑ (CSP) ๊ตฌํ์ ๋ํ ์ข ํฉ ๊ฐ์ด๋๋ก, ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ณดํธ๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก์ ๋ณด์ ์ง์นจ์ ์ค์ ์ ๋ก๋๋ค.
์น ๋ณด์ ์ ์ฑ ๊ตฌํ: ์๋ฐ์คํฌ๋ฆฝํธ ์ฝํ ์ธ ๋ณด์ ๊ฐ์ด๋๋ผ์ธ
์ค๋๋ ์ํธ ์ฐ๊ฒฐ๋ ๋์งํธ ํ๊ฒฝ์์ ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ณด์์ ๊ฐ์ฅ ์ค์ํฉ๋๋ค. ์ฌ์ดํธ ๊ฐ ์คํฌ๋ฆฝํ (XSS) ๊ณต๊ฒฉ ๋ฐ ๊ธฐํ ์ฝ๋ ์ฃผ์ ์ทจ์ฝ์ ์ ์ํํ๋ ๊ฐ์ฅ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ ์ค ํ๋๋ ์ฝํ ์ธ ๋ณด์ ์ ์ฑ (CSP)์ ๊ตฌํํ๋ ๊ฒ์ ๋๋ค. ์ด ์ข ํฉ ๊ฐ์ด๋๋ ํนํ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝํ ์ธ ๋ณด์ ๊ฐ์ด๋๋ผ์ธ์ ์ด์ ์ ๋ง์ถฐ CSP์ ๋ณต์ก์ฑ์ ์์ธํ ์ค๋ช ํฉ๋๋ค.
์ฝํ ์ธ ๋ณด์ ์ ์ฑ (CSP)์ด๋ ๋ฌด์์ธ๊ฐ?
์ฝํ ์ธ ๋ณด์ ์ ์ฑ (CSP)์ ์น์ฌ์ดํธ ๊ด๋ฆฌ์๊ฐ ํน์ ํ์ด์ง์ ๋ํด ์ฌ์ฉ์ ์์ด์ ํธ๊ฐ ๋ก๋ํ ์ ์๋ ๋ฆฌ์์ค๋ฅผ ์ ์ดํ ์ ์๋๋ก ํ๋ HTTP ์๋ต ํค๋์ ๋๋ค. ์ด๋ ๋ณธ์ง์ ์ผ๋ก ์คํฌ๋ฆฝํธ, ์คํ์ผ์ํธ, ์ด๋ฏธ์ง, ๊ธ๊ผด ๋ฐ ๊ธฐํ ๋ฆฌ์์ค์ ์ถ์ฒ๋ฅผ ์ง์ ํ๋ ํ์ดํธ๋ฆฌ์คํธ์ ๋๋ค. CSP๋ฅผ ์ ์ํจ์ผ๋ก์จ ๋ธ๋ผ์ฐ์ ๊ฐ ๊ณต๊ฒฉ์์ ์ํด ์ฃผ์ ๋ ์ ์ฑ ์ฝ๋๋ฅผ ์คํํ๋ ๊ฒ์ ๋ฐฉ์งํ์ฌ XSS ๊ณต๊ฒฉ์ ์ํ์ ํฌ๊ฒ ์ค์ผ ์ ์์ต๋๋ค.
CSP๋ '๊ธฐ๋ณธ ๊ฑฐ๋ถ(default deny)' ์์น์ ๋ฐ๋ผ ์๋ํฉ๋๋ค. ์ฆ, ๊ธฐ๋ณธ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ ์ ์ฑ ์์ ๋ช ์์ ์ผ๋ก ํ์ฉ๋์ง ์์ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ์ฐจ๋จํฉ๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ๊ณต๊ฒฉ ํ๋ฉด์ ํจ๊ณผ์ ์ผ๋ก ์ ํํ๊ณ ๋ค์ํ ์ํ์ผ๋ก๋ถํฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณดํธํฉ๋๋ค.
์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ณด์์ CSP๊ฐ ์ค์ํ๊ฐ?
์๋ฐ์คํฌ๋ฆฝํธ๋ ํด๋ผ์ด์ธํธ ์ธก ์คํฌ๋ฆฝํ ์ธ์ด์ด๋ฏ๋ก ์ ์ฑ ์ฝ๋๋ฅผ ์ฃผ์ ํ๋ ค๋ ๊ณต๊ฒฉ์๋ค์ ์ฃผ์ ํ์ ์ด ๋ฉ๋๋ค. ๊ณต๊ฒฉ์๊ฐ ๋ค๋ฅธ ์ฌ์ฉ์๊ฐ ๋ณด๋ ์น์ฌ์ดํธ์ ์ ์ฑ ์คํฌ๋ฆฝํธ๋ฅผ ์ฃผ์ ํ๋ XSS ๊ณต๊ฒฉ์ ์ผ๋ฐ์ ์ธ ์ํ์ ๋๋ค. CSP๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ์คํ๋ ์ ์๋ ์ถ์ฒ๋ฅผ ์ ์ดํจ์ผ๋ก์จ XSS ๊ณต๊ฒฉ์ ์ํํ๋ ๋ฐ ํนํ ํจ๊ณผ์ ์ ๋๋ค.
CSP๊ฐ ์์ผ๋ฉด ์ฑ๊ณต์ ์ธ XSS ๊ณต๊ฒฉ์ ํตํด ๊ณต๊ฒฉ์๋ ๋ค์์ ์ํํ ์ ์์ต๋๋ค:
- ์ฌ์ฉ์ ์ฟ ํค ๋ฐ ์ธ์ ํ ํฐ ํ์ทจ.
- ์น์ฌ์ดํธ ๋ณ์กฐ.
- ์ฌ์ฉ์๋ฅผ ์ ์ฑ ์น์ฌ์ดํธ๋ก ๋ฆฌ๋๋ ์ .
- ์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ์ ๋งฌ์จ์ด ์ฃผ์ .
- ๋ฏผ๊ฐํ ๋ฐ์ดํฐ์ ๋ํ ๋ฌด๋จ ์ ๊ทผ ํ๋.
CSP๋ฅผ ๊ตฌํํจ์ผ๋ก์จ ๋ธ๋ผ์ฐ์ ๊ฐ ์น์ธ๋์ง ์์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์คํํ๋ ๊ฒ์ ๋ฐฉ์งํ์ฌ ์ด๋ฌํ ๊ณต๊ฒฉ์ ์ํ์ ํฌ๊ฒ ์ค์ผ ์ ์์ต๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๋ณด์์ ์ํ ์ฃผ์ CSP ์ง์๋ฌธ
CSP ์ง์๋ฌธ์ ํ์ฉ๋ ๋ฆฌ์์ค ์์ค๋ฅผ ์ ์ํ๋ ๊ท์น์ ๋๋ค. ํนํ ์๋ฐ์คํฌ๋ฆฝํธ ๋ณด์๊ณผ ๊ด๋ จ๋ ๋ช ๊ฐ์ง ์ง์๋ฌธ์ด ์์ต๋๋ค:
script-src
script-src ์ง์๋ฌธ์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ๋ก๋ํ ์ ์๋ ์์น๋ฅผ ์ ์ดํฉ๋๋ค. ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ณด์์ ์์ด ์๋ง๋ ๊ฐ์ฅ ์ค์ํ ์ง์๋ฌธ์ผ ๊ฒ์
๋๋ค. ๋ค์์ ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ๊ฐ์
๋๋ค:
'self': ๋ฌธ์์ ๋์ผํ ์ถ์ฒ์ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ข์ ์์์ ์ ๋๋ค.'none': ๋ชจ๋ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ์ง ์์ต๋๋ค. ํ์ด์ง์ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ํ์ํ์ง ์์ ๊ฒฝ์ฐ ์ฌ์ฉํฉ๋๋ค.'unsafe-inline': ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ(<script>ํ๊ทธ ๋ด ์คํฌ๋ฆฝํธ) ๋ฐ ์ด๋ฒคํธ ํธ๋ค๋ฌ(์:onclick)๋ฅผ ํ์ฉํฉ๋๋ค. CSP๋ฅผ ํฌ๊ฒ ์ฝํ์ํค๋ฏ๋ก ๊ทน๋์ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ฌ ์ฌ์ฉํด์ผ ํฉ๋๋ค.'unsafe-eval':eval()๋ฐFunction()๊ณผ ๊ฐ์ ๊ด๋ จ ํจ์์ ์ฌ์ฉ์ ํ์ฉํฉ๋๋ค. ๋ณด์์์ ์ํฅ์ผ๋ก ์ธํด ๊ฐ๋ฅํ ํ ํผํด์ผ ํฉ๋๋ค.https://example.com: ํน์ ๋๋ฉ์ธ์ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํฉ๋๋ค. ์ ํํ๊ฒ ์ง์ ํ๊ณ ์ ๋ขฐํ ์ ์๋ ๋๋ฉ์ธ๋ง ํ์ฉํ์ญ์์ค.'nonce-value': ํน์ ์ํธํ nonce ์์ฑ์ด ์๋ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํฉ๋๋ค. ์ด๋'unsafe-inline'์ ๋ํ ๋ ์์ ํ ๋์์ ๋๋ค.'sha256-hash': ํน์ SHA256 ํด์๊ฐ ์๋ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํฉ๋๋ค. ์ด๋'unsafe-inline'์ ๋ํ ๋ ๋ค๋ฅธ ๋ ์์ ํ ๋์์ ๋๋ค.
์์:
script-src 'self' https://cdn.example.com;
์ด ์ ์ฑ
์ ๋์ผํ ์ถ์ฒ์ https://cdn.example.com์ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํฉ๋๋ค.
default-src
default-src ์ง์๋ฌธ์ ๋ค๋ฅธ fetch ์ง์๋ฌธ์ ๋ํ ๋์ฒด(fallback) ์ญํ ์ ํฉ๋๋ค. ํน์ ์ง์๋ฌธ(์: script-src, img-src)์ด ์ ์๋์ง ์์ ๊ฒฝ์ฐ default-src ์ ์ฑ
์ด ์ ์ฉ๋ฉ๋๋ค. ์์์น ๋ชปํ ๋ฆฌ์์ค ๋ก๋ฉ ์ํ์ ์ต์ํํ๊ธฐ ์ํด ์ ํ์ ์ธ default-src๋ฅผ ์ค์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์์:
default-src 'self';
์ด ์ ์ฑ ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋์ผํ ์ถ์ฒ์ ๋ฆฌ์์ค๋ฅผ ํ์ฉํฉ๋๋ค. ๋ค๋ฅธ ๋ฆฌ์์ค ์ ํ์ ๋ ๊ตฌ์ฒด์ ์ธ ์ง์๋ฌธ์ด ํ์ฉํ์ง ์๋ ํ ์ฐจ๋จ๋ฉ๋๋ค.
style-src
์ฃผ๋ก CSS ์์ค๋ฅผ ์ ์ดํ๊ธฐ ์ํ ๊ฒ์ด์ง๋ง, style-src ์ง์๋ฌธ์ CSS์ ํํ์์ด ํฌํจ๋๊ฑฐ๋ ์
์ฉ๋ ์ ์๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์๋ฐ์คํฌ๋ฆฝํธ ๋ณด์์ ๊ฐ์ ์ ์ผ๋ก ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค. script-src์ ๋ง์ฐฌ๊ฐ์ง๋ก ์คํ์ผ์ํธ์ ์์ค๋ฅผ ์ ํํด์ผ ํฉ๋๋ค.
์์:
style-src 'self' https://fonts.googleapis.com;
์ด ์ ์ฑ ์ ๋์ผํ ์ถ์ฒ์ Google Fonts์ ์คํ์ผ์ํธ๋ฅผ ํ์ฉํฉ๋๋ค.
object-src
object-src ์ง์๋ฌธ์ Flash์ ๊ฐ์ ํ๋ฌ๊ทธ์ธ์ ์์ค๋ฅผ ์ ์ดํฉ๋๋ค. Flash๋ ์ ์ ๋ ์ฌ์ฉ๋๊ณ ์์ง๋ง, ์
์ฑ ์ฝํ
์ธ ๊ฐ ๋ก๋๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ํ๋ฌ๊ทธ์ธ ์์ค๋ฅผ ์ ํํ๋ ๊ฒ์ ์ฌ์ ํ ์ค์ํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ํ๋ฌ๊ทธ์ธ์ ๋ํ ํน์ ์๊ตฌ ์ฌํญ์ด ์๋ ํ ์ด ๊ฐ์ 'none'์ผ๋ก ์ค์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์์:
object-src 'none';
์ด ์ ์ฑ ์ ๋ชจ๋ ํ๋ฌ๊ทธ์ธ์ ํ์ฉํ์ง ์์ต๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ก CSP๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
CSP๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํ๋ ค๋ฉด ์ ์คํ ๊ณํ๊ณผ ๊ณ ๋ ค๊ฐ ํ์ํฉ๋๋ค. ๋ค์์ ๋ฐ๋ผ์ผ ํ ๋ช ๊ฐ์ง ๋ชจ๋ฒ ์ฌ๋ก์ ๋๋ค:
1. ๋ณด๊ณ ์ ์ ์ฉ(Report-Only) ์ ์ฑ ์ผ๋ก ์์ํ๊ธฐ
CSP๋ฅผ ์ํํ๊ธฐ ์ ์ ๋ณด๊ณ ์ ์ ์ฉ ์ ์ฑ
์ผ๋ก ์์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ฅผ ํตํด ์ค์ ๋ก ๋ฆฌ์์ค๋ฅผ ์ฐจ๋จํ์ง ์๊ณ ์ ์ฑ
์ ํจ๊ณผ๋ฅผ ๋ชจ๋ํฐ๋งํ ์ ์์ต๋๋ค. Content-Security-Policy-Report-Only ํค๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ณด๊ณ ์ ์ ์ฉ ์ ์ฑ
์ ์ ์ํ ์ ์์ต๋๋ค. ์ ์ฑ
์๋ฐ์ report-uri ์ง์๋ฌธ์ ์ฌ์ฉํ์ฌ ์ง์ ๋ URI๋ก ๋ณด๊ณ ๋ฉ๋๋ค.
์์:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint;
์ด ์ ์ฑ
์ ๋ฆฌ์์ค๋ฅผ ์ฐจ๋จํ์ง ์๊ณ /csp-report-endpoint๋ก ์๋ฐ ์ฌํญ์ ๋ณด๊ณ ํฉ๋๋ค.
2. 'unsafe-inline' ๋ฐ 'unsafe-eval' ํผํ๊ธฐ
์์ ์ธ๊ธํ๋ฏ์ด 'unsafe-inline'๊ณผ 'unsafe-eval'์ CSP๋ฅผ ํฌ๊ฒ ์ฝํ์ํค๋ฏ๋ก ๊ฐ๋ฅํ ํ ํผํด์ผ ํฉ๋๋ค. ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ์ eval()์ XSS ๊ณต๊ฒฉ์ ์ผ๋ฐ์ ์ธ ํ์ ์
๋๋ค. ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ nonce๋ ํด์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
3. ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ์ Nonce ๋๋ ํด์ ์ฌ์ฉํ๊ธฐ
Nonce์ ํด์๋ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ๋ ๋ ์์ ํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. Nonce๋ <script> ํ๊ทธ์ ์ถ๊ฐ๋๊ณ CSP ํค๋์ ํฌํจ๋๋ ์์์ ์ผํ์ฉ ๋ฌธ์์ด์
๋๋ค. ํด์๋ ์คํฌ๋ฆฝํธ ์ฝํ
์ธ ์ ์ํธํ ํด์๋ก, ์ด ๋ํ CSP ํค๋์ ํฌํจ๋ฉ๋๋ค.
Nonce ์ฌ์ฉ ์์:
HTML:
<script nonce="randomNonceValue">console.log('Inline script');</script>
CSP ํค๋:
script-src 'self' 'nonce-randomNonceValue';
ํด์ ์ฌ์ฉ ์์:
HTML:
<script>console.log('Inline script');</script>
CSP ํค๋:
script-src 'self' 'sha256-uniqueHashValue'; (`uniqueHashValue`๋ฅผ ์คํฌ๋ฆฝํธ ๋ด์ฉ์ ์ค์ SHA256 ํด์๋ก ๋์ฒด)
์ฐธ๊ณ : ์คํฌ๋ฆฝํธ์ ๋ํ ์ฌ๋ฐ๋ฅธ ํด์ ์์ฑ์ ๋น๋ ๋๊ตฌ๋ ์๋ฒ ์ธก ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ ์๋ํํ ์ ์์ต๋๋ค. ๋ํ ์คํฌ๋ฆฝํธ ๋ด์ฉ์ด ๋ณ๊ฒฝ๋๋ฉด ํด์๋ฅผ ๋ค์ ๊ณ์ฐํ๊ณ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค.
4. ์ถ์ฒ๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ์ง์ ํ๊ธฐ
CSP ์ง์๋ฌธ์์ ์์ผ๋์นด๋ ๋ฌธ์(*) ์ฌ์ฉ์ ํผํ์ญ์์ค. ๋์ ํ์ฉํ๋ ค๋ ์ ํํ ์ถ์ฒ๋ฅผ ์ง์ ํ์ญ์์ค. ์ด๋ ๊ฒ ํ๋ฉด ์ ๋ขฐํ ์ ์๋ ์์ค๋ฅผ ์ค์๋ก ํ์ฉํ ์ํ์ ์ต์ํํ ์ ์์ต๋๋ค.
์์:
๋ค์ ๋์ :
script-src *; (๋งค์ฐ ๊ถ์ฅํ์ง ์์)
๋ค์์ ์ฌ์ฉ:
script-src 'self' https://cdn.example.com https://api.example.com;
5. ์ ๊ธฐ์ ์ผ๋ก CSP ๊ฒํ ๋ฐ ์ ๋ฐ์ดํธํ๊ธฐ
CSP๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณ๊ฒฝ ์ฌํญ๊ณผ ์งํํ๋ ์ํ ํ๊ฒฝ์ ๋ฐ์ํ๊ธฐ ์ํด ์ ๊ธฐ์ ์ผ๋ก ๊ฒํ ํ๊ณ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค. ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ฑฐ๋ ์๋ก์ด ์๋น์ค์ ํตํฉํ ๋ ํ์ํ ๋ฆฌ์์ค๋ฅผ ํ์ฉํ๋๋ก CSP๋ฅผ ์กฐ์ ํด์ผ ํ ์ ์์ต๋๋ค.
6. CSP ์์ฑ๊ธฐ ๋๋ ๊ด๋ฆฌ ๋๊ตฌ ์ฌ์ฉํ๊ธฐ
CSP๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ ๋ฐ ๋์์ด ๋๋ ์ฌ๋ฌ ์จ๋ผ์ธ ๋๊ตฌ์ ๋ธ๋ผ์ฐ์ ํ์ฅ ํ๋ก๊ทธ๋จ์ด ์์ต๋๋ค. ์ด๋ฌํ ๋๊ตฌ๋ ๊ฐ๋ ฅํ CSP๋ฅผ ๋ง๋ค๊ณ ์ ์ง ๊ด๋ฆฌํ๋ ๊ณผ์ ์ ๋จ์ํํ ์ ์์ต๋๋ค.
7. CSP๋ฅผ ์ฒ ์ ํ ํ ์คํธํ๊ธฐ
CSP๋ฅผ ๊ตฌํํ๊ฑฐ๋ ์ ๋ฐ์ดํธํ ํ์๋ ๋ชจ๋ ๋ฆฌ์์ค๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ก๋๋๊ณ ๊ธฐ๋ฅ์ด ์์๋์ง ์์๋์ง ํ์ธํ๊ธฐ ์ํด ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒ ์ ํ ํ ์คํธํ์ญ์์ค. ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ CSP ์๋ฐ ์ฌํญ์ ์๋ณํ๊ณ ๊ทธ์ ๋ฐ๋ผ ์ ์ฑ ์ ์กฐ์ ํ์ญ์์ค.
CSP ๊ตฌํ์ ์ค์ ์์
๋ค์ํ ์๋๋ฆฌ์ค์ ๋ํ CSP ๊ตฌํ์ ์ค์ ์์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
์์ 1: CDN์ ์ฌ์ฉํ๋ ๊ธฐ๋ณธ ์น์ฌ์ดํธ
์๋ฐ์คํฌ๋ฆฝํธ ๋ฐ CSS ํ์ผ์ CDN์ ์ฌ์ฉํ๋ ๊ธฐ๋ณธ ์น์ฌ์ดํธ:
CSP ํค๋:
default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' https://cdn.example.com; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com;
์ด ์ ์ฑ ์ ๋ค์์ ํ์ฉํฉ๋๋ค:
- ๋์ผํ ์ถ์ฒ์ ๋ฆฌ์์ค.
https://cdn.example.com์ ์คํฌ๋ฆฝํธ ๋ฐ ์คํ์ผ์ํธ.- ๋์ผํ ์ถ์ฒ ๋ฐ ๋ฐ์ดํฐ URI์ ์ด๋ฏธ์ง.
- ๋์ผํ ์ถ์ฒ ๋ฐ Google Fonts(
https://fonts.gstatic.com)์ ๊ธ๊ผด.
์์ 2: ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ ๋ฐ ์คํ์ผ์ด ์๋ ์น์ฌ์ดํธ
nonce๋ฅผ ์ฌ์ฉํ์ฌ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ ๋ฐ ์คํ์ผ์ ์ฌ์ฉํ๋ ์น์ฌ์ดํธ:
HTML:
<script nonce="uniqueNonce123">console.log('Inline script');</script>
<style nonce="uniqueNonce456">body { background-color: #f0f0f0; }</style>
CSP ํค๋:
default-src 'self'; script-src 'self' 'nonce-uniqueNonce123'; style-src 'self' 'nonce-uniqueNonce456'; img-src 'self' data:;
์ด ์ ์ฑ ์ ๋ค์์ ํ์ฉํฉ๋๋ค:
- ๋์ผํ ์ถ์ฒ์ ๋ฆฌ์์ค.
- nonce๊ฐ "uniqueNonce123"์ธ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ.
- nonce๊ฐ "uniqueNonce456"์ธ ์ธ๋ผ์ธ ์คํ์ผ.
- ๋์ผํ ์ถ์ฒ ๋ฐ ๋ฐ์ดํฐ URI์ ์ด๋ฏธ์ง.
์์ 3: ์๊ฒฉํ CSP๋ฅผ ์ฌ์ฉํ๋ ์น์ฌ์ดํธ
๋งค์ฐ ์๊ฒฉํ CSP๋ฅผ ๋ชฉํ๋ก ํ๋ ์น์ฌ์ดํธ:
CSP ํค๋:
default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; base-uri 'self'; form-action 'self';
์ด ์ ์ฑ ์ ๋ค์์ ํ์ฉํฉ๋๋ค:
- ๋์ผํ ์ถ์ฒ์ ๋ฆฌ์์ค๋ง ํ์ฉํ๋ฉฐ, ํน๋ณํ ํ์ฉ๋์ง ์๋ ํ ๋ค๋ฅธ ๋ชจ๋ ์ ํ์ ๋ฆฌ์์ค๋ฅผ ๋ช ์์ ์ผ๋ก ๋นํ์ฑํํฉ๋๋ค.
- ๋ํ ๊ธฐ๋ณธ URI ๋ฐ ์์ ์์ ์ ๋์ผํ ์ถ์ฒ๋ก ์ ํํ๋ ๋ฑ ์ถ๊ฐ์ ์ธ ๋ณด์ ์กฐ์น๋ฅผ ์ํํฉ๋๋ค.
CSP์ ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ ์์ํฌ(React, Angular, Vue.js)
React, Angular ๋๋ Vue.js์ ๊ฐ์ ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ ๋ CSP ๊ตฌํ์๋ ํน๋ณํ ์ฃผ์๊ฐ ํ์ํฉ๋๋ค. ์ด๋ฌํ ํ๋ ์์ํฌ๋ ์ข
์ข
์ธ๋ผ์ธ ์คํ์ผ, ๋์ ์ฝ๋ ์์ฑ ๋ฐ eval()๊ณผ ๊ฐ์ ๊ธฐ์ ์ ์ฌ์ฉํ๋ฉฐ, ์ด๋ CSP์ ๋ฌธ์ ๊ฐ ๋ ์ ์์ต๋๋ค.
React
React๋ ์ผ๋ฐ์ ์ผ๋ก ์ปดํฌ๋ํธ ์คํ์ผ๋ง์ ์ํด ์ธ๋ผ์ธ ์คํ์ผ์ ์ฌ์ฉํฉ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด nonce๋ ํด์๋ฅผ ์ง์ํ๋ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์คํ์ผ์ CSS ํ์ผ๋ก ์ธ๋ถํํ ์ ์์ต๋๋ค.
Angular
Angular์ JIT(Just-In-Time) ์ปดํ์ผ์ eval()์ ์์กดํ๋ฏ๋ก ์๊ฒฉํ CSP์ ํธํ๋์ง ์์ต๋๋ค. ์ด๋ฅผ ๊ทน๋ณตํ๋ ค๋ฉด ๋น๋ ๊ณผ์ ์์ ์ ํ๋ฆฌ์ผ์ด์
์ ์ปดํ์ผํ๊ณ ๋ฐํ์์ eval()์ ํ์์ฑ์ ์ ๊ฑฐํ๋ AOT(Ahead-Of-Time) ์ปดํ์ผ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
Vue.js
Vue.js๋ ์ธ๋ผ์ธ ์คํ์ผ๊ณผ ๋์ ์ฝ๋ ์์ฑ์ ์ฌ์ฉํฉ๋๋ค. React์ ์ ์ฌํ๊ฒ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์คํ์ผ์ ์ธ๋ถํํ ์ ์์ต๋๋ค. ๋์ ์ฝ๋ ์์ฑ์ ์ํด ๋น๋ ๊ณผ์ ์์ Vue.js์ ํ ํ๋ฆฟ ์ปดํ์ผ๋ฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
CSP ๋ณด๊ณ
CSP ๋ณด๊ณ ๋ ๊ตฌํ ๊ณผ์ ์ ํ์์ ์ธ ๋ถ๋ถ์
๋๋ค. report-uri ๋๋ report-to ์ง์๋ฌธ์ ๊ตฌ์ฑํ์ฌ CSP ์๋ฐ์ ๋ํ ๋ณด๊ณ ์๋ฅผ ๋ฐ์ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ณด๊ณ ์๋ ์ ์ฑ
์ ๋ฌธ์ ๋ฅผ ์๋ณํ๊ณ ์์ ํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
report-uri ์ง์๋ฌธ์ ๋ธ๋ผ์ฐ์ ๊ฐ CSP ์๋ฐ ๋ณด๊ณ ์๋ฅผ JSON ํ์ด๋ก๋๋ก ์ ์กํด์ผ ํ๋ URL์ ์ง์ ํฉ๋๋ค. ์ด ์ง์๋ฌธ์ report-to๋ฅผ ์ํด ๋ ์ด์ ์ฌ์ฉ๋์ง ์๊ณ ์์ต๋๋ค.
report-to ์ง์๋ฌธ์ Report-To ํค๋์ ์ ์๋ ๊ทธ๋ฃน ์ด๋ฆ์ ์ง์ ํฉ๋๋ค. ์ด ํค๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์ํ ๋ณด๊ณ ์๋ํฌ์ธํธ๋ฅผ ๊ตฌ์ฑํ๊ณ ์ฐ์ ์์๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค.
report-uri ์ฌ์ฉ ์์:
Content-Security-Policy: default-src 'self'; report-uri /csp-report-endpoint;
report-to ์ฌ์ฉ ์์:
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"/csp-report-endpoint"}]}
Content-Security-Policy: default-src 'self'; report-to csp-endpoint;
๋๊ตฌ ๋ฐ ๋ฆฌ์์ค
CSP๋ฅผ ๊ตฌํํ๊ณ ๊ด๋ฆฌํ๋ ๋ฐ ๋์์ด ๋๋ ๋ช ๊ฐ์ง ๋๊ตฌ์ ๋ฆฌ์์ค๊ฐ ์์ต๋๋ค:
- CSP Evaluator: CSP๋ฅผ ๋ถ์ํ๊ณ ํ๊ฐํ๊ธฐ ์ํ ๋๊ตฌ.
- CSP Generator: CSP ํค๋๋ฅผ ์์ฑํ๊ธฐ ์ํ ๋๊ตฌ.
- ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ: ๋๋ถ๋ถ์ ๋ธ๋ผ์ฐ์ ์๋ CSP ์๋ฐ์ ์๋ณํ๋ ๋ฐ ๋์์ด ๋๋ ๋ด์ฅ ๊ฐ๋ฐ์ ๋๊ตฌ๊ฐ ์์ต๋๋ค.
- Mozilla Observatory: CSP๋ฅผ ํฌํจํ์ฌ ์น์ฌ์ดํธ์ ๋ํ ๋ณด์ ๊ถ์ฅ ์ฌํญ์ ์ ๊ณตํ๋ ์น์ฌ์ดํธ.
์ผ๋ฐ์ ์ธ ํจ์ ๊ณผ ์ด๋ฅผ ํผํ๋ ๋ฐฉ๋ฒ
CSP ๊ตฌํ์ ์ด๋ ค์ธ ์ ์์ผ๋ฉฐ, ํผํด์ผ ํ ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ํจ์ ์ด ์์ต๋๋ค:
- ์ง๋์น๊ฒ ๊ด๋ํ ์ ์ฑ
: ์ ๋์ ์ผ๋ก ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฉด ์์ผ๋์นด๋ ๋ฌธ์๋
'unsafe-inline'๋ฐ'unsafe-eval'์ฌ์ฉ์ ํผํ์ญ์์ค. - ์๋ชป๋ Nonce/ํด์ ์์ฑ: nonce๊ฐ ์์์ ์ด๊ณ ๊ณ ์ ํ์ง, ํด์๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๊ณ์ฐ๋์๋์ง ํ์ธํ์ญ์์ค.
- ์ฒ ์ ํ์ง ์์ ํ ์คํธ: CSP๋ฅผ ๊ตฌํํ๊ฑฐ๋ ์ ๋ฐ์ดํธํ ํ์๋ ํญ์ ํ ์คํธํ์ฌ ๋ชจ๋ ๋ฆฌ์์ค๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ก๋๋๋์ง ํ์ธํ์ญ์์ค.
- CSP ๋ณด๊ณ ์ ๋ฌด์: ์ ๊ธฐ์ ์ผ๋ก CSP ๋ณด๊ณ ์๋ฅผ ๊ฒํ ํ๊ณ ๋ถ์ํ์ฌ ๋ฌธ์ ๋ฅผ ์๋ณํ๊ณ ์์ ํ์ญ์์ค.
- ํ๋ ์์ํฌ ํน์ฑ์ ๊ณ ๋ คํ์ง ์์: ์ฌ์ฉ ์ค์ธ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ ์์ํฌ์ ํน์ ์๊ตฌ ์ฌํญ๊ณผ ์ ํ ์ฌํญ์ ๊ณ ๋ คํ์ญ์์ค.
๊ฒฐ๋ก
์ฝํ
์ธ ๋ณด์ ์ ์ฑ
(CSP)์ ์น ์ ํ๋ฆฌ์ผ์ด์
๋ณด์์ ๊ฐํํ๊ณ XSS ๊ณต๊ฒฉ์ ์ํํ๋ ๊ฐ๋ ฅํ ๋๊ตฌ์
๋๋ค. CSP๋ฅผ ์ ์คํ๊ฒ ์ ์ํ๊ณ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ์ฝ๋ ์ฃผ์
์ทจ์ฝ์ ์ ์ํ์ ํฌ๊ฒ ์ค์ด๊ณ ์ฌ์ฉ์๋ฅผ ์
์ฑ ์ฝํ
์ธ ๋ก๋ถํฐ ๋ณดํธํ ์ ์์ต๋๋ค. ๋ณด๊ณ ์ ์ ์ฉ ์ ์ฑ
์ผ๋ก ์์ํ๊ณ , 'unsafe-inline' ๋ฐ 'unsafe-eval'์ ํผํ๊ณ , ์ถ์ฒ๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ์ง์ ํ๋ฉฐ, ์ ๊ธฐ์ ์ผ๋ก CSP๋ฅผ ๊ฒํ ํ๊ณ ์
๋ฐ์ดํธํ๋ ๊ฒ์ ๊ธฐ์ตํ์ญ์์ค. CSP๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํจ์ผ๋ก์จ ์ฌ์ฉ์๋ฅผ ์ํ ๋ ์์ ํ๊ณ ์ ๋ขฐํ ์ ์๋ ์น ํ๊ฒฝ์ ๋ง๋ค ์ ์์ต๋๋ค.
์ด ๊ฐ์ด๋๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ํ CSP ๊ตฌํ์ ๋ํ ํฌ๊ด์ ์ธ ๊ฐ์๋ฅผ ์ ๊ณตํ์ต๋๋ค. ์น ๋ณด์์ ๋์์์ด ์งํํ๋ ๋ถ์ผ์ด๋ฏ๋ก ์ต์ ๋ชจ๋ฒ ์ฌ๋ก์ ๋ณด์ ์ง์นจ์ ๋ํ ์ ๋ณด๋ฅผ ๊ณ์ ์ ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๊ฐ๋ ฅํ CSP๋ฅผ ๊ตฌํํ์ฌ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณดํธํ๊ณ ์ ์ฌ์ ์ธ ์ํ์ผ๋ก๋ถํฐ ์ฌ์ฉ์๋ฅผ ๋ณดํธํ์ญ์์ค.