์ฟ ํค
์ฟ ํค๋ stateless ๋ฐฉ์์ผ๋ก ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์ ์งํ ๋ ์ฌ์ฉํฉ๋๋ค.
โถ ํน์ง
- ์ฟ ํค๋ ๋ณด์์ด ์ทจ์ฝํ๋ค
์ฟ ํค๋ F12 ์ Network ํญ์ผ๋ก๋ ์ฝ๊ฒ ์กฐ์์ด ๊ฐ๋ฅํ๊ณ , ๋ณผ ์ ์๋ ๋งํผ ๋ณด์์ ์ทจ์ฝํฉ๋๋ค.
๊ทธ๋ ๊ธฐ์ ์ฟ ํค ๋จ๋ ์ผ๋ก ์ฐ์ง ์๊ณ ์ฟ ํค์ ๋ฌด๊ฒฐ์ฑ์ ์ํด ์ธ์ /JWT์ ํจ๊ป ์ฐ์ ๋๋ค.
- ํด๋ผ์ด์ธํธ์ธก์์ ๊ด๋ฆฌํ๋ฉฐ, ์ด๋ฅผ stateless ๋ฐฉ์์ด๋ผ ํฉ๋๋ค.
-๋ธ๋ผ์ฐ์ ์ ์ ์ฅ๋ ์ฟ ํค๋ ๋ชจ๋ ์์ฒญ์ ํฌํจ๋์ด ์๋ฒ์ ์ ์ก๋ฉ๋๋ค.
์ด๋ ์ฟ ํค๊ฐ ํ์์๋ ์์ฒญ์ ๋ํด์๋ ๋คํธ์ํฌ ํธ๋ํฝ์ ์ถ๊ฐ๋ก ์ ๋ฐํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ ๊ธฐ์ ์ฟ ํค๋ฅผ ์ฌ์ฉํ ๋๋ ๋คํธ์ํฌ ํธ๋ํฝ์ ์ค์ด๊ธฐ ์ํด ์ต์ํ์ ์ ๋ณด๋ง ํฌํจ๋์ด์ผ ํฉ๋๋ค.
๋ํ, ์ฟ ํค๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ํน์ง์ ์ ์ฉํ CSRF ๊ณต๊ฒฉ์ ๋ ธ์ถ๋๊ธฐ ์ฝ์ต๋๋ค.
์ธ์
์ธ์ ์ stateful ๋ฐฉ์์ผ๋ก ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์ ์งํ ๋ ์ฌ์ฉํฉ๋๋ค.
โถ ํน์ง
์๋ฒ์ธก์์ ๊ด๋ฆฌํ๋ฉฐ, ์ด๋ฅผ stateful ๋ฐฉ์์ด๋ผ ํฉ๋๋ค.
์ฅ์ ์ผ๋ก๋ ์ฌ์ฉ์์ ์ํ๋ฅผ ์๋ฒ๊ฐ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋, ๋จ์ ์ผ๋ก๋ ์ธ์ ์ด ๋ง์์ง ๊ฒฝ์ฐ, ์๋ฒ ๋ถํ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
๋, ์๋ฒ๊ฐ ํ์ฅ๋ ๊ฒฝ์ฐ ๊ฐ ์๋ฒ์ ์ธ์ ์ ๋ณด๋ฅผ ๋๊ธฐํ ํด์ผํฉ๋๋ค.
ํ ํฐ
ํ ํฐ์ stateless ๋ฐฉ์์ผ๋ก ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์ ์งํ ๋ ์ฌ์ฉํฉ๋๋ค.
โถ ํน์ง
- ํ ํฐ์๋ ์๋ฒ๊ฐ ๊ฐ์ธํค๋ก ๋ง๋ ์๋ช ์ด ๋ด๊ฒจ ์์ผ๋ฉฐ, ์๋ฒ๋ ํ ํฐ์ ์๋ช ์ ๊ณต๊ฐํค๋ก ๊ฒ์ฆํ ์ ์์ต๋๋ค.
- ํ ํฐ์ stateless ๋ฐฉ์์ ๋๋ค.
์๋ฒ๊ฐ ํ ํฐ์ ๊ด๋ฆฌํ์ง ์๊ธฐ ๋๋ฌธ์ ์๋ฒ ๋ถํ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๊ณ , ์๋ฒ ํ์ฅ ์ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
๊ทธ๋ฌ๋, ์ฌ์ฉ์์ ์ํ๋ฅผ ์ ์ดํ ์๊ฐ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ํ ํฐ์ด ํ์ทจ๋์ด ๋น์ ์ ์์ฒญ์ด ๋ค์ด์ค๋๋ผ๋ ์ฌ์ฉ์๋ฅผ ๊ฐ์ ๋ก๊ทธ์์ ์ํฌ ์ ์์ต๋๋ค.
๋จ 1๊ฐ์ ๊ธฐ๊ธฐ์์๋ง ๋ก๊ทธ์ธ์ ์ ์งํ๊ณ ์ถ์ ์๋น์ค์ผ ๊ฒฝ์ฐ, ํ ํฐ์ด ์๋ ์ธ์ ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
JWT
JWT ๋ ํด๋ผ์ด์ธํธ-์๋ฒ, ์๋น์ค-์๋น์ค ๊ฐ ์ธ๊ฐ๋ฅผ ์ํด ์ฌ์ฉํ๋ ํ ํฐ์ ๋๋ค.
โถ ๊ตฌ์กฐ
- ๋ฌธ์์ด๋ก ๊ตฌ์ฑ๋์ด ์๊ธฐ ๋๋ฌธ์ URL, HTTP ํค๋ ๋ฑ ์ด๋์ ์์นํ ์ ์์ต๋๋ค.
- JWT๋ Header.Payload.Signature(ํค๋.ํ์ด๋ก๋.์๋ช ์ผ๋ก ์ด๋ฃจ์ด์ง๋ฉฐ, ์ (.)์ผ๋ก ๊ตฌ๋ถ๋ฉ๋๋ค)).
1. Header(ํค๋)
ํค๋๋ JWT๋ฅผ ์ด๋ป๊ฒ ๊ฒ์ฆํ๋์ง๋ฅผ ๋ํ๋ ๋๋ค.
{
"alg": "ES256",
"kid": "Key ID"
}
alg ๋ ์๋ช ์ ์ฌ์ฉํ๋ ์๊ณ ๋ฆฌ์ฆ, kid ๋ ์๋ช ์ด ์ฌ์ฉํ๋ ํค(Public/Private Key) ๋ฅผ ์๋ณํ๋ ๊ฐ์ ๋๋ค.
ํด๋น JSON ๊ฐ์ฒด๋ฅผ ๋ฌธ์์ด๋ก ๋ง๋ค๊ณ UTF-8 ๊ณผ Base64 URL-Safe ๋ก ์ธ์ฝ๋ฉํ๋ฉด ์๋์ ๊ฐ์ ํค๋๋ฅผ ์์ฑํฉ๋๋ค.
์ธ์ฝ๋ฉ ๊ณผ์ -> Base64URLSafe(UTF-8('{"alg": "ES256","kid": "Key ID"}'))
๊ฒฐ๊ณผ -> eyJhbGciOiJFUzI1NiIsImtpZCI6IktleSBJRCJ9
* Base64 URL-Safe : ์ธ์ฝ๋ฉ ๊ฒฐ๊ณผ๋ฅผ URL๊ณผ ํ์ผ ๊ฒฝ๋ก์์ ์์ ํ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํด ๊ณ ์๋์ต๋๋ค.
+ ๊ธฐํธ๋ฅผ -(ํ์ดํ)์ผ๋ก ๋์ฒด
/ ๊ธฐํธ๋ฅผ _(์ธ๋์ค์ฝ์ด)๋ก ๋์ฒด
= ๊ธฐํธ๋ ํ์์ ๋ฐ๋ผ ์ ๊ฑฐ
2. Payload(ํ์ด๋ก๋)
ํ์ด๋ก๋๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ ์ฃผ๊ณ ๋ฐ๊ธฐ๋ก ํ ๊ฐ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
{
"iss": "jinho.shin",
"iat": "1586364327"
}
์ธ์ฝ๋ฉ ๊ณผ์ -> Base64URLSafe('{"iss": "jinho.shin","iat": "1586364327"}')
๊ฒฐ๊ณผ -> eyJpYXQiOjE1ODYzNjQzMjcsImlzcyI6ImppbmhvLnNoaW4ifQ
3. Signature(์๋ช )
์ (.)์ ๊ตฌ๋ถ์๋กํด์ ํค๋์ ํ์ด๋ก๋๋ฅผ ํฉ์น ๋ฌธ์์ด์ ์๋ช ํ ๊ฐ์ ๋๋ค.
์๋ช ์ ํค๋์ alg ์ ์ ์๋ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋น๋ฐ ํค๋ฅผ ์ฌ์ฉํด ์์ฑํ๊ณ ์ธ์ฝ๋ฉํฉ๋๋ค.
์ธ์ฝ๋ฉ ๊ณผ์ -> Base64URLSafe(Sign('ES256', '${PRIVATE_KEY}',
'eyJhbGciOiJFUzI1NiIsImtpZCI6IktleSBJRCJ9.eyJpYXQiOjE1ODYzNjQzMjcsImlzcyI6ImppbmhvLnNoaW4ifQ')))
๊ฒฐ๊ณผ -> MEQCIBSOVBBsCeZ_8vHulOvspJVFU3GADhyCHyzMiBFVyS3qAiB7Tm_MEXi2kLusOBpanIrcs2NVq24uuVDgH71M_fIQGg
* ์๋ช vs ์ํธํ
์๋ช ์ ๋ฐ์ดํฐ๊ฐ ๋ณ์กฐ๋์ง ์์์์ ํ์ธํ๋ ๋ฌด๊ฒฐ์ฑ์ ์ฆ๋ช ํ์ง๋ง ์ํธํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณดํธํ์ฌ ํ๊ฐ๋ ์ฌ๋๋ง ์ฝ์ ์ ์๊ฒ ํ๋ ๊ณผ์ ์ ๋๋ค. ํ ํฐ์ ํ์ทจ ๋นํด์ ํ ํฐ์ ๊ฐ์ ๋๊ตฌ๋ ์ฝ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ํธํ๋ผ๊ณ ์ค๋ช ํ๋ ๊ฒ์ ๋ถ์ ์ ํฉ๋๋ค.
XSS ์ CSRF
ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ์ฟ ํค/์ธ์ /ํ ํฐ์ ๋ณด์ ๋ฐฉ๋ฒ์ ๋ํด ์๊ฐํ๊ฒ ์ต๋๋ค.
์ด๋ป๊ฒ ๋ณด์ํ ์ง๋ฅผ ์๋ ค๋ฉด XSS์ CSRF ์ ๋ํด ๋จผ์ ์์์ผ ํฉ๋๋ค.
โถ XSS ( Cross-Site Scripting )
XSS๋ ๊ณต๊ฒฉ์๊ฐ ์ฌ์ฉ์(์ผ๋ฐ ๊ณ ๊ฐ)์ ๋ธ๋ผ์ฐ์ ์ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๊ฒ ํจ์ผ๋ก์จ ์ธ์ ์ ๊ฐ๋ก์ฑ๊ฑฐ๋, ์น์ฌ์ดํธ ๋ณ์กฐ, ์ ์์ ์ฝํ ์ธ ์ฝ์ , ํผ์ฑ ๊ณต๊ฒฉ์ ํฉ๋๋ค.
์ถ๊ฐ๋ก, XSS ๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ฌ์ฉ๋๋ <, >, ', " ์ ๊ฐ์ ํน์๋ฌธ์๋ฅผ < , > ๋ฑ์ HTML entity ๋ก ์นํํ์ฌ ์ ๋ ฅํ๋๋ก ํ๊ณ , HTMLํ๊ทธ ์ฌ์ฉ์ด ํ์ํ ๊ฒฝ์ฐ, ์ฌ์ฉ ํ๊ทธ๋ฅผ ์ง์ ํ์ฌ ํด๋น ํ๊ทธ๋ง ํ์ฉํ๋๋ก ํ ์ ์์ต๋๋ค.
โถ CSRF ( Cross-Site Request Forgery )
CSRF( cross site request forgery attack ) ๋ ์ฌ์ฉ์๊ฐ ์ธ์ฆํ ์ธ์ ์์ ์๋ฒ๊ฐ ์ ์์ ์ธ ์์ฒญ๊ณผ ๋น์ ์์ ์ธ ์์ฒญ์ ๊ตฌ๋ถํ์ง ๋ชปํ๋ค๋ ์ ์ ์ ์ฉํ ๋ฐฉ์์ ๋๋ค. ์ฌ์ฉ์ ์์ฒญ์ด ์ค์ ์ฌ์ฉ์๊ฐ ์ ์กํ ๊ฒ์ธ์ง ํ์ธํ์ง ์๋ ๊ฒฝ์ฐ์ ๋ฐ์ํฉ๋๋ค.
์ฆ, XSS ๋ ์ฌ์ฉ์ PC์์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํด ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ํ์ทจํ์ง๋ง, CSRF๋ ์์ฒญ์ ์์กฐํจ์ผ๋ก์จ ์ฌ์ฉ์ ๋ชฐ๋ ์ก๊ธ๊ณผ ์ ํ ๊ตฌ์ ๋ฑ ํน์ ํ์๋ฅผ ์ํํฉ๋๋ค.
์ฟ ํค ์ฌ์ฉ ์ ๋ณด์ ๋ฐฉ๋ฒ
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ธ์ ๊ณผ ํ ํฐ์ด ๋ก์ปฌ/์ธ์ ์คํ ๋ฆฌ์ง์ ์ ์ฅ์ด ๋ ๊ฒฝ์ฐ, XSS ๊ณต๊ฒฉ์ผ๋ก๋ถํฐ ์์ ๋ก์ธ ์ ์์ต๋๋ค(๋ธ๋ผ์ฐ์ ์์ ์คํฌ๋ฆฝํธ๋ก ์ธํด ํ์ทจ๋ ๊ฐ๋ฅ์ฑ์ด ์๊ธฐ ๋๋ฌธ)
๊ทธ๋์, ์ฟ ํค๋ ๋ณด์๊ด๋ จ ์์ฑ๋ค์ ์ ๊ณตํฉ๋๋ค.
- HttpOnly
HttpOnly ์์ฑ์ ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ฟ ํค์ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅ ํ๊ฒ ํจ์ผ๋ก์จ XSS ๊ณต๊ฒฉ์ ๋ฐฉ์งํฉ๋๋ค.
- Secure
์ฟ ํค๋ http, https ๋ฅผ ๊ตฌ๋ถํ์ง ์๊ณ ์ ์ก๋๊ธฐ ๋๋ฌธ์ https ์ธ ๊ฒฝ์ฐ๋ง ์ ์ก์ด ๋๊ฒ ํ๋ Secure ์์ฑ์ ์ ๊ณตํฉ๋๋ค.
- SameSite=Strict
๋ชจ๋ ์์ฒญ์ ์ฟ ํค๋ฅผ ๋ฃ์ด์ ๋ณด๋ด๋ ๋ธ๋ผ์ฐ์ ์ ํน์ฑ์ ์ ์ฉํ CSRF ๋ฅผ ๋ง๊ธฐ์ํด ์ฟ ํค๋ SameSite=Strict ์์ฑ์ ์ง์ํฉ๋๋ค.
SameSite=Strict ์์ฑ์ ๋ธ๋ผ์ฐ์ ๋ก ํ์ฌ๊ธ ์์ฒญ ๋๋ฉ์ธ๊ณผ ์ฟ ํค์ ์ค์ ๋ ๋๋ฉ์ธ์ด ๊ฐ์ ๊ฒฝ์ฐ์๋ง ์ฟ ํค๋ฅผ ์ ์กํ๊ฒ ํฉ๋๋ค.
๋ง์ฝ, ์ฟ ํค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ธ์ ๊ณผ ํ ํฐ์ ์คํ ๋ฆฌ์ง์ ์ ์ฅ์ ํ๋ฉด CSRF ๋ก ๋ถํฐ ์กฐ๊ธ์ ์์ ๋ก์์ง ์ ์์ง๋ง XSS ๊ณต๊ฒฉ์ผ๋ก๋ถํฐ ์์ ๋กญ์ง ๋ชปํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋์, ์ฟ ํค๋ฅผ ์ฌ์ฉํ ๋๋ HttpOnly + Secure + SameSite=Strict ์กฐํฉ์ ์ฌ์ฉํ์ฌ XSS ์ CSRF ๊ณต๊ฒฉ์ผ๋ก ๋ถํฐ ์๋ฐฉํด์ผ ํฉ๋๋ค.
๊ทธ๋ฌ๋, ์๋ฒฝํ ์๋ฐฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ์ ์ธ ์์ ์ ์๊ตฌํฉ๋๋ค.
ํด๋ผ์ด์ธํธ๋ XSS ๊ณต๊ฒฉ์ ๋ง๊ธฐ ์ํด ์คํฌ๋ฆฝํธ์ ์ฌ์ฉ๋๋ <, >, ‘, “ ๋ฑ์ ํน์๋ฌธ์๋ฅผ < , > ๋ฑ์ HTML entity๋ก ์นํํ์ฌ ์ ๋ ฅํ๊ฑฐ๋ HTML ํ๊ทธ ์ฌ์ฉ์ด ํ์ํ ๊ฒฝ์ฐ, ์ฌ์ฉํ ํ๊ทธ๋ฅผ ์ง์ ํ์ฌ ํด๋น ํ๊ทธ๋ง ํ์ฉํฉ๋๋ค.
์๋ฒ๋ ์ถ๊ฐ์ ์ผ๋ก CSRF Token, Synchroniza token pattern, double-submit cookie, client-side secure ๋ฑ ์ถ๊ฐ์ ์ธ ์์ ์ด ํ์ํ๋ค๊ณ ํฉ๋๋ค. ํด๋น ๋ด์ฉ๋ค์ Wikipedia ์ CSRF ์์ ๊ฐ์ ธ์์ผ๋ฉฐ, ๋ณด์๋ณด๋ค๋ ๊ฐ๋ฐ์ ํฅ๋ฏธ๊ฐ ์๋ ์ ๋ก์จ๋ ์ฌ๊ธฐ์ ๊ธ์ ๋ง๋ฌด๋ฆฌ ํ ๊น ํฉ๋๋ค. ๊ธ ์ฝ์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
์ถ์ฒ
- MDN
- StackOverflow
Does this JWT implementation prevent XSS and CSRF attacks while still giving me access to payloads?
- StackExchange: Security
Do I need CSRF token if I'm using Bearer JWT?
Should I use CSRF protection on Rest API endpoints?
Securely using JWTs with CSRF protection and refresh tokens
- blog
Store JWT in cookie or localstorage ?
Do SameSite Cookies Solve CSRF?
- ๊น์ํ๋์ HTTP ๊ฐ์
- JSCODE ์ JWT
'Network' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
TCP & UDP์ ์ฐจ์ด์ 3,4 way handshake ์์๋ณด๊ธฐ (0) | 2024.09.06 |
---|---|
ARQ์ TCP ์ ์ฐจ์ด์ , ๊ทธ๋ฆฌ๊ณ TCP Reno (1) | 2024.09.05 |
TLS 1.2 Handshake ๋์ ๊ณผ์ + HTTPS ๊ฐ์ (0) | 2024.08.22 |
HTTP/1.0 โ HTTP/1.1 โ HTTP/2.0 โ HTTP/3.0 ๋ฒ์ ๋ณ ์ฐจ์ด๋ฅผ ์ดํดํ๊ธฐ (1) | 2024.08.22 |
TCP/IP์ 'ํจํท ๊ตํ ๋ฐฉ์' ์ฐ๋จน ํ๊ธฐ (0) | 2024.08.15 |