아래는 "스프링 시큐리티" 책의 9장에 포함될 "CSRF(Cross-Site Request Forgery) 방어", "XSS(Cross-Site Scripting)와 콘텐츠 보안 정책", 그리고 "보안 헤더 추가"에 대한 내용입니다. 각 보안 위협의 개념과 스프링부트에서의 대응 방법을 실습 가능하도록 설명했습니다. --- ### 9장. 보안 강화 기법 #### 9.1 CSRF(Cross-Site Request Forgery) 방어 **CSRF(Cross-Site Request Forgery)**는 사용자가 의도하지 않은 요청을 악의적인 웹사이트를 통해 서버로 전송하게 만드는 공격입니다. 예를 들어, 사용자가 로그인한 상태에서 악성 사이트의 링크를 클릭하면, 사용자의 인증 쿠키를 활용해 은행 계좌 이체 같은 요청이 실행될 수 있습니다. ##### CSRF 동작 원리 - 공격자는 피해자가 로그인한 상태를 가정. - 피해자가 공격자의 사이트에서 숨겨진 폼(예: `
``` ###### CSRF 비활성화 Stateless 인증(JWT 등)을 사용할 때는 CSRF 보호가 필요 없을 수 있습니다: ```java http .csrf(csrf -> csrf.disable()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); ``` ##### 방어 팁 - **GET 요청 제한**: 상태 변경은 POST로만 처리. - **토큰 확인**: 모든 변경 요청에 CSRF 토큰 포함. - **SameSite 쿠키**: 세션 쿠키에 `SameSite=Strict` 설정 추가(아래 보안 헤더 참조). #### 9.2 XSS(Cross-Site Scripting)와 콘텐츠 보안 정책 **XSS(Cross-Site Scripting)**는 공격자가 웹 페이지에 악성 스크립트를 삽입해 사용자의 브라우저에서 실행시키는 공격입니다. 이를 통해 세션 쿠키를 탈취하거나 페이지를 조작할 수 있습니다. ##### XSS 유형 - **Reflected XSS**: 악성 스크립트가 URL 파라미터 등으로 전달되어 즉시 실행. - **Stored XSS**: 악성 스크립트가 데이터베이스에 저장되어 모든 사용자에게 노출. - **DOM-based XSS**: 클라이언트 측 스크립트가 조작됨. ##### 스프링에서의 XSS 방어 1. **입력 검증**: 사용자 입력을 철저히 검증하고 sanitization 적용. - `HtmlUtils.htmlEscape()`로 HTML 이스케이프: ```java import org.springframework.web.util.HtmlUtils; String safeInput = HtmlUtils.htmlEscape(userInput); ``` 2. **템플릿 엔진**: Thymeleaf는 기본적으로 출력값을 이스케이프해 XSS 방어. ```html ``` ##### 콘텐츠 보안 정책 (CSP) **CSP(Content Security Policy)**는 브라우저가 허용된 소스에서만 리소스를 로드하도록 제한해 XSS를 방어합니다. HTTP 헤더로 설정합니다. ###### CSP 설정 ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.header.writers.StaticHeadersWriter; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .headers(headers -> headers .addHeaderWriter(new StaticHeadersWriter("Content-Security-Policy", "default-src 'self'; script-src 'self' https://trusted.cdn.com;")) ) .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .formLogin(); return http.build(); } } ``` - `default-src 'self'`: 기본적으로 같은 출처에서만 리소스 로드. - `script-src 'self' https://trusted.cdn.com`: 스크립트는 자체 및 신뢰된 CDN에서만 허용. ##### 방어 팁 - **출력 이스케이프**: 모든 동적 콘텐츠를 이스케이프 처리. - **CSP 강화**: 외부 리소스 최소화 및 엄격한 정책 적용. - **입력 제한**: 허용된 문자만 허용(예: 정규식 사용). #### 9.3 보안 헤더 추가 보안 헤더는 브라우저의 기본 보안 기능을 강화해 다양한 공격을 방지합니다. 스프링 시큐리티는 이를 쉽게 추가할 수 있는 설정을 제공합니다. ##### 주요 보안 헤더 1. **X-Content-Type-Options**: - `nosniff`: MIME 타입 스니핑 방지. - 설정: ```java http.headers(headers -> headers.contentTypeOptions()); ``` 2. **X-Frame-Options**: - `DENY` 또는 `SAMEORIGIN`: 클릭재킹(Clickjacking) 방지. - 설정: ```java http.headers(headers -> headers.frameOptions(frame -> frame.sameOrigin())); ``` 3. **X-XSS-Protection**: - `1; mode=block`: 브라우저의 XSS 필터 활성화(구형 브라우저 지원). - 설정: ```java http.headers(headers -> headers.xssProtection()); ``` 4. **Strict-Transport-Security (HSTS)**: - HTTPS 강제 적용 및 중간자 공격 방지. - 설정: ```java http.headers(headers -> headers.httpStrictTransportSecurity(hsts -> hsts.maxAgeInSeconds(31536000))); ``` 5. **Content-Security-Policy**: 위 CSP 섹션 참조. 6. **Referrer-Policy**: - 참조 정보 제한(예: `no-referrer-when-downgrade`). - 설정: ```java http.headers(headers -> headers.referrerPolicy(referrer -> referrer.policy(ReferrerPolicy.NO_REFERRER_WHEN_DOWNGRADE))); ``` ##### 종합 설정 예제 ```java @Configuration public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .headers(headers -> headers .contentTypeOptions() .frameOptions(frame -> frame.deny()) .xssProtection() .httpStrictTransportSecurity(hsts -> hsts.maxAgeInSeconds(31536000).includeSubDomains(true)) .addHeaderWriter(new StaticHeadersWriter("Referrer-Policy", "strict-origin-when-cross-origin")) .addHeaderWriter(new StaticHeadersWriter("Content-Security-Policy", "default-src 'self'")) ) .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .formLogin(); return http.build(); } } ``` ##### SameSite 쿠키 설정 CSRF 방어를 강화하려면 세션 쿠키에 `SameSite` 속성 추가: ```properties # application.properties server.servlet.session.cookie.same-site=strict ``` - `Strict`: 타사 사이트에서 쿠키 전송 차단. - `Lax`: GET 요청은 허용, POST 등은 차단. ##### 실습 예제 1. CSRF 토큰 없이 POST 요청 시 403 확인. 2. XSS 공격 시도(예: ``) 후 이스케이프 동작 확인. 3. 브라우저 개발자 도구에서 보안 헤더 적용 여부 점검. --- 위 내용은 CSRF, XSS, 보안 헤더의 개념과 스프링 시큐리티에서의 방어 방법을 실습 가능하도록 설명했습니다. 추가적인 예제나 세부 사항이 필요하면 말씀해 주세요!