크로스 사이트 스크립팅(XSS)는 웹 애플리케이션의 보안 취약점 중 하나로, 공격자가 악성 스크립트를 웹 페이지에 삽입하여 다른 사용자에게 전달하는 공격 기법입니다 이를 통해 공격자는 사용자의 세션 쿠키 탈취, 파싱, 악성 코드 실행 등 다양한 악의적인 행위를 할 수 있습니다.
저장형 XSS (Stored XSS) : 공격자가 입력한 악성 스크립트가 서버에 저장되고, 다른 사용자가 해당 데이터를 조회할 때 스크립트가 실행됩니다. ex) 게시판에 악성 스크립트를 포함한 글을 작성
반사형 XSS (Reflected XSS) : 공격자가 조작한 URL이나 요청을 통해 악성 스크립트가 즉시 반영되어 실행됩니다. ex) 검색창에 스크립트를 삽입한 URL을 클릭했을 때 스크립트 실행.
DOM 기반 XSS : 클라이언트 사이드에서 자바스크립트가 DOM을 조작하면서 발생하는 XSS 입니다. ex) urL의 파라미터를 자바스크립트로 처리할 때 검증 없이 삽입.
XSS공격을 방어하기 위해서는 입력 검증(Input Validation)과 출력 인코딩(Output Encoding)이 핵심입니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 다른 설정들...
.headers()
.xssProtection()
.and()
.contentSecurityPolicy("script-src 'self'");
}
}
import javax.validation.constraints.NotBlank;
public class UserInput {
@NotBlank
private String name;
// getters and setters
}
<p th:text="${userInput}">User Input</p>
import org.springframework.web.util.HtmlUtils;
String safeHtml = HtmlUtils.htmlEscape(userInput);
model.addAttribute("safeHtml", safeHtml);
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 다른 설정들...
.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self'");
}
}
@Bean
public HttpSessionIdResolver httpSessionIdResolver() {
return HeaderHttpSessionIdResolver.xAuthToken();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 다른 설정들...
.sessionManagement()
.sessionFixation().migrateSession()
.and()
.csrf().disable()
.headers()
.httpStrictTransportSecurity()
.and()
.frameOptions().sameOrigin()
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired");
}
물론입니다! 신입 Java/Spring 백엔드 개발자로서 크로스 사이트 스크립팅(XSS)에 대해 이론을 이해하는 것뿐만 아니라 직접 실습을 통해 경험을 쌓는 것이 매우 중요합니다. 아래에 실습할 만한 단계별 프로젝트와 연습 과제를 제안드립니다.
Spring Initializr를 사용하여 새로운 Spring Boot 프로젝트를 생성합니다.
프로젝트 구조 설정
src/main/java/com/example/xssdemo
src/main/resources/templates
간단한 컨트롤러 작성
package com.example.xssdemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
@PostMapping("/submit")
public String submit(@RequestParam("input") String input, Model model) {
model.addAttribute("userInput", input);
return "result";
}
}
Thymeleaf 템플릿 작성
src/main/resources/templates/home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>XSS Demo</title>
</head>
<body>
<h1>입력 폼</h1>
<form action="/submit" method="post">
<input type="text" name="input" />
<button type="submit">제출</button>
</form>
</body>
</html>
src/main/resources/templates/result.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>결과</title>
</head>
<body>
<h1>입력 결과</h1>
<p th:text="${userInput}">사용자 입력</p>
</body>
</html>
애플리케이션 실행 및 테스트
http://localhost:8080
으로 접속합니다.result.html
에서 입력한 내용이 안전하게 출력되는지 확인합니다.취약점 확인
현재 result.html
에서 사용자가 입력한 내용을 th:text
를 사용하여 출력하고 있으므로, Thymeleaf는 기본적으로 HTML 이스케이프를 수행하여 XSS를 방어합니다. 이를 확인하기 위해 스크립트를 입력해봅니다.
<script>alert('XSS');</script>
테스트 결과 확인
th:text
대신 ${userInput}
을 직접 사용하면 XSS 취약점이 발생할 수 있습니다.입력 검증 강화
유효성 검사 어노테이션 추가
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
public class UserInput {
@NotBlank(message = "입력은 필수입니다.")
@Size(max = 100, message = "입력은 100자 이내여야 합니다.")
private String input;
// getters and setters
}
컨트롤러 수정
import javax.validation.Valid;
import org.springframework.validation.BindingResult;
@PostMapping("/submit")
public String submit(@Valid UserInput userInput, BindingResult result, Model model) {
if (result.hasErrors()) {
return "home";
}
model.addAttribute("userInput", userInput.getInput());
return "result";
}
Content Security Policy(CSP) 설정
Spring Security 설정 추가
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()
.antMatchers("/", "/submit").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self'");
}
}
HttpOnly 및 Secure 쿠키 설정
세션 쿠키 설정
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self'")
.and()
.httpStrictTransportSecurity()
.and()
.frameOptions().sameOrigin()
.and()
.sessionManagement()
.sessionFixation().migrateSession();
// 세션 쿠키 설정
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.rememberMe()
.rememberMeCookieName("remember-me")
.tokenValiditySeconds(86400)
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/");
return http.build();
}
}
Thymeleaf 자동 인코딩 확인
th:text
가 제대로 작동하는지 다시 한 번 테스트해봅니다.<script>
태그가 이스케이프되어 브라우저에서 스크립트가 실행되지 않아야 합니다.OWASP ZAP 사용
설치 및 실행
프로젝트 스캔
Burp Suite 사용
Spring Security CSRF 보호 활성화
SecurityConfig
에서 csrf().enable()
설정을 확인합니다.입력 필터링 라이브러리 사용
import org.owasp.html.PolicyFactory;
import org.owasp.html.Sanitizers;
public String sanitizeInput(String input) {
PolicyFactory policy = Sanitizers.FORMATTING.and(Sanitizers.LINKS);
return policy.sanitize(input);
}
로그 모니터링 및 알림 설정
이러한 실습을 통해 XSS뿐만 아니라 다른 보안 취약점에 대한 이해와 방어 능력을 키울 수 있습니다. 취업 준비에 많은 도움이 되길 바라며, 추가 질문이 있으면 언제든지 문의해주세요! 화이팅하세요!