Content Security Policy(CSP)는 웹 애플리케이션이 로드할 수 있는 콘텐츠의 출처를 브라우저에게 지시하는 보안 표준. 이를 통해 악성 스크립트나 데이터 주입 공격(예: Cross-Site Scripting, XSS)을 방지할 수 있습니다.
간단히 말해, CSP는 "내 웹사이트는 이 출처에서만 리소스를 로드 할 수 있어"라고 브라우저에 알려주는 규칙 세트입니다.
웹 애플리케이션은 다양한 리소스(스크립트, 스타일시트, 이미지 등)를 외부에서 로드합니다. 하지만 만약 악의적인 사용자가 악성 스크립트를 삽입할 수 있다면, 이는 보안 취약점으로 이어질 수 있습니다. CSP는 다음과 같은 이유로 중요합니다.
CSP는 다양한 지시자를 통해 어떤 리소스를 허용할지 세부적으로 설정할 수 있습니다.
Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.google.com
이 설정은 기본적으로 자신의 도메인('self')에서만 리소스를 로드하고, 스크립트는 자신의 도메인과 http://apis.google.com에서만 로드하도록 허용합니다.
Spring 프레임워크에서는 CSP를 설정하기 위해 Spring Security를 활용할 수 있습니다. Spring Security는 CSP 헤더를 쉽게 추가하고 관리할 수 있는 기능을 제공.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self' https://apis.google.com")
.and()
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
report-uri 지시자를 사용하여 CSP 위반 사항을 모니터링하고, 필요한 경우 정책을 조정할 수 있습니다.취업 준비 중인 신입 Java 및 Spring 백엔드 개발자라면, Content Security Policy (CSP)를 이해하고 실제로 구현해보는 것이 웹 보안에 대한 이해를 높이고 실무 능력을 키우는 데 큰 도움이 될 것입니다. 다음은 CSP를 실습하기 위한 단계별 가이드와 프로젝트 아이디어를 제안드립니다.
컨트롤러 생성:
package com.example.cspdemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home(Model model) {
model.addAttribute("message", "안녕하세요! CSP 실습 페이지입니다.");
return "home";
}
}
템플릿 파일 생성 (src/main/resources/templates/home.html):
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>CSP 실습</title>
<script src="https://apis.google.com/js/api.js"></script>
<script>
// 간단한 스크립트
console.log("CSP 실습 스크립트 로드 완료.");
</script>
</head>
<body>
<h1 th:text="${message}"></h1>
<img src="https://via.placeholder.com/150" alt="샘플 이미지">
</body>
</html>
src/main/java/com/example/cspdemo/config/SecurityConfig.java 파일을 생성하고 다음과 같이 작성합니다:
package com.example.cspdemo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll() // 모든 요청을 허용 (단순화)
.and()
.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self' https://apis.google.com")
.and()
.frameOptions().deny(); // Clickjacking 방지
}
}
설명:
default-src 'self': 기본적으로 자신의 도메인에서만 리소스를 로드하도록 설정.script-src 'self' https://apis.google.com: 스크립트는 자신의 도메인과 Google API에서만 로드 허용.frameOptions().deny(): 프레임을 통한 사이트 내재화를 금지하여 Clickjacking 공격 방지.mvn spring-boot:runhttp://localhost:8080/에 접속합니다.Content-Security-Policy 헤더가 설정되었는지 확인합니다.home.html에 다음과 같은 스크립트를 추가해봅니다:<script>
alert("CSP 테스트: 이 스크립트는 차단되어야 합니다.");
</script>alert 창이 실행되지 않는지 확인합니다.home.html에 Google API에서 제공하는 스크립트를 추가합니다:<script src="https://apis.google.com/js/api.js"></script>
<script>
// Google API 스크립트 사용 예제
gapi.load('client', () => {
console.log("Google API 로드 완료.");
});
</script>CSP 보고 URI 추가:
SecurityConfig 클래스에서 report-uri 지시자를 추가합니다:.contentSecurityPolicy("default-src 'self'; script-src 'self' https://apis.google.com; report-uri /csp-report")보고 수신 엔드포인트 생성:
CSP 위반 사항을 수신할 컨트롤러를 생성합니다:
package com.example.cspdemo.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CSPReportController {
@PostMapping("/csp-report")
public ResponseEntity<Void> handleCspReport(@RequestBody String report) {
System.out.println("CSP Report: " + report);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
CSP 위반 시도 및 로그 확인:
기능 구현:
CSP 적용:
default-src 'self', 필요한 리소스 출처 추가.img-src 지시자에 추가.보안 테스트:
보고 기능 활용:
report-uri 또는 report-to 지시자를 설정하고, 위반 사항을 모니터링하여 정책 개선.Mozilla Developer Network (MDN) - CSP 가이드:
Spring Security 공식 문서:
OWASP - Content Security Policy:
온라인 튜토리얼 및 강좌:
CSP는 웹 애플리케이션 보안의 중요한 요소 중 하나입니다. 신입 개발자로서 CSP를 실습하고 이해하는 것은 실제 프로젝트에서 발생할 수 있는 보안 위협을 예방하는 데 큰 도움이 됩니다. 위의 단계별 가이드를 따라가며 CSP를 직접 구현하고, 다양한 시나리오에서 그 효과를 검증해보세요. 이를 통해 보안에 대한 깊은 이해와 실무 적용 능력을 갖추게 될 것입니다.
궁금한 점이 있거나 추가적인 도움이 필요하면 언제든지 질문해 주세요. 성공적인 취업 준비를 응원합니다!