
CSRF๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ณด์ ์ทจ์ฝ์ ์ค ํ๋๋ก, ์ฌ์ฉ์๊ฐ ์ ๋ขฐํ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ณต๊ฒฉ์๊ฐ ์๋ํ์ง ์์ ์์ฒญ์ ๋ณด๋ด๊ฒ ๋ง๋๋ ๊ณต๊ฒฉ์ ๋๋ค. ์ด๋ฅผ ํตํด ๊ณต๊ฒฉ์๋ ํผํด์์ ๊ถํ์ผ๋ก ์ ์์ ์ธ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
Cross-Site Request Forgery (CSRF)๋ ์ฌ์ฉ์๊ฐ ์ธ์ฆ๋ ์ธ์ ์ํ์์ ์คํํ ์ ์๋ ์์ฒญ์ ๊ณต๊ฒฉ์๊ฐ ์์กฐํ์ฌ, ์ฌ์ฉ์์ ์์ง์ ์๊ด์์ด ๊ณต๊ฒฉ์๊ฐ ์ํ๋ ์์ ์ ์คํํ๊ฒ ๋ง๋๋ ๊ณต๊ฒฉ์ ๋๋ค.
CSRF ๊ณต๊ฒฉ์ ์ฌ์ฉ์์ ์ธ์ฆ ์ํ์ ๋ธ๋ผ์ฐ์ ์ ์ ๋ขฐ์ฑ์ ์ ์ฉํฉ๋๋ค.
๐ ์ธ์ฆ๋ ์ธ์
์
์ฉ
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ์ํ์์ ์ฟ ํค๊ฐ ๋ธ๋ผ์ฐ์ ์ ์ ์ฅ๋์ด ์๋ ๊ฒฝ์ฐ, ๋ธ๋ผ์ฐ์ ๋ ๋์ผํ ๋๋ฉ์ธ์ ์์ฒญ์ ๋ณด๋ผ ๋ ์๋์ผ๋ก ์ฟ ํค๋ฅผ ์ฒจ๋ถํฉ๋๋ค.
๐ฉ ์์กฐ๋ ์์ฒญ ์ ์ก
๊ณต๊ฒฉ์๊ฐ ์์กฐ๋ ์์ฒญ์ ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ์คํํ๊ฒ ๋ง๋ญ๋๋ค.
example.com์ ๋ก๊ทธ์ธํฉ๋๋ค. ๋ก๊ทธ์ธ ํ ์ธ์
์ฟ ํค๊ฐ ๋ธ๋ผ์ฐ์ ์ ์ ์ฅ๋ฉ๋๋ค.malicious.com์ ๋ง๋ค๊ณ , CSRF ๊ณต๊ฒฉ ์ฝ๋๋ฅผ ํฌํจํ HTML์ ์ฝ์
ํฉ๋๋ค.<img src="https://example.com/transfer?amount=1000&to=attacker_account">malicious.com์ ๋ฐฉ๋ฌธํ๋ฉด, ๋ธ๋ผ์ฐ์ ๋ ์๋์ผ๋ก example.com์ ์ฟ ํค๋ฅผ ํฌํจํ์ฌ ์์ฒญ์ ๋ณด๋
๋๋ค. ๊ทธ ์ด์ ๋ ์ด๋ฏธ์ง์ src๋ฅผ ํตํด example.com ํ์ด์ง์ ์ ๊ทผ์ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.example.com ์๋ฒ๋ ์์ฒญ์ ์ ๋นํ ์ฌ์ฉ์๋ก๋ถํฐ ์จ ๊ฒ์ผ๋ก ์ฒ๋ฆฌํ๊ณ , ๊ณต๊ฒฉ์๊ฐ ์ํ๋ ์์
์ด ์ํ๋ฉ๋๋ค.Spring Security ๊ตฌํ ์์:
1. HTML์ CSRF ํ ํฐ ์ฝ์
:
<input type="hidden" name="_csrf" value="ํ ํฐ๊ฐ">
Referer ๋๋ Origin ๊ฐ์ ํ์ธํ์ฌ ์ ๋ขฐํ ์ ์๋ ์ถ์ฒ์์ ์จ ์์ฒญ์ธ์ง ๊ฒ์ฆํฉ๋๋ค.if (!request.getHeader("Referer").startsWith("https://example.com")) {
throw new SecurityException("CSRF detected!");
}Referer๋ฅผ ์ ๊ฑฐํ๋ ๊ฒฝ์ฐ๊ฐ ์์ด ์ ๋ขฐ์ฑ์ด ๋ฎ์ ์ ์์.SameSite ์์ฑ์ ์ค์ ํ์ฌ, ๋์ผํ ์ฌ์ดํธ์์ ๋ฐ์ํ ์์ฒญ์์๋ง ์ฟ ํค๋ฅผ ์ ์กํ๋๋ก ์ ํํฉ๋๋ค.Set-Cookie: sessionId=abc123; SameSite=Strict;| ๊ตฌ๋ถ | CSRF | XSS |
|---|---|---|
| ๊ณต๊ฒฉ ๋ฐฉ์ | ํผํด์์ ๊ถํ์ ์ ์ฉํด ์๋ฒ์ ์ ์์ ์์ฒญ์ ๋ณด๋ | ํผํด์ ๋ธ๋ผ์ฐ์ ์์ ์ ์์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํ |
| ๋์ | ์๋ฒ | ํด๋ผ์ด์ธํธ |
| ์๊ตฌ ์กฐ๊ฑด | ํผํด์๊ฐ ์ธ์ฆ๋ ์ํ๋ก ์์ฒญํด์ผ ํจ | ๋ณ๋์ ์ธ์ฆ์ด ํ์ํ์ง ์์ |
Spring Security๋ ๊ธฐ๋ณธ์ ์ผ๋ก CSRF ๋ณดํธ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
๊ธฐ๋ณธ ์ค์ :
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().enable();
}
}
์ปค์คํฐ๋ง์ด์ง:
ํน์ ์์ฒญ์ ๋ํด CSRF ๋ณดํธ๋ฅผ ๋นํ์ฑํํ ์ ์์ต๋๋ค.
http.csrf().ignoringAntMatchers("/api/**");
CSRF๋ ์ฌ์ฉ์์ ์ ๋ขฐ๋ฅผ ์ ์ฉํ์ฌ ์๋ฒ๋ฅผ ๊ณต๊ฒฉํ๋ ๋งค์ฐ ์ํํ ๊ธฐ๋ฒ์ด์ง๋ง, CSRF ํ ํฐ, SameSite ์ฟ ํค ์ค์ , ์ถ๊ฐ ์ธ์ฆ ๋ฑ์ ๋ฐฉ๋ฒ์ผ๋ก ๋ฐฉ์ดํ ์ ์์ต๋๋ค. CSRF ๋ฐฉ์ด๋ฅผ ์ฒ ์ ํ ๊ตฌํํ์ฌ, ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณด์์ ๊ฐํํด์ผ ํฉ๋๋ค.
๐ ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ณด์์ ์ํด CSRF ๋ฐฉ์ด๋ ํ์!