일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 알고리즘
- redis
- MySQL
- 네트워크
- 백준
- MSA
- react
- spring webflux
- Kafka
- mongoDB
- Galera Cluster
- 디자인 패턴
- 파이썬
- JPA
- C
- 자료구조
- Java
- Proxy
- 운영체제
- design pattern
- Spring
- 자바
- Heap
- c언어
- Data Structure
- IT
- 컴퓨터구조
- OS
- Algorithm
- JavaScript
Archives
- Today
- Total
시냅스
Java 코드 예시로 보는 CSRF 설명과 예방 본문
CSRF
Cross-Site Request Forgery
- 공격자의 요청이 사용자의 요청인 것처럼 속이는 공격 방식
- 사용자가 특정 사이트에 로그인한 상태로 악의적인 웹사이트에 방문하여 로그인한 특정 사이트에 악성 요청을 보내도록 유도
- 사용자가 인증한 세션에서 웹 애플리케이션이 정상적인 요청과 비정상적인 요청을 구분하지 못하는 점을 악용
- 쿠키와 같은 정보를 포함하고 있기 때문에
- XSS와 비슷하지만 XSS는 세션이 없어도 가능하다.
예시
<https://bank.com/transfer?to=another_user&amount=1000>
- bank 라는 사이트에서는 타인에게 송금할 때 위와 같은 url을 사용한다.
<html>
<body>
<form action="https://bank.com/transfer?to=attacker&amount=1000000" method="POST">
<input type="submit" value="Click here to win a million dollars!">
</form>
</body>
</html>
- 공격자가 위와 같은 HTML을 사용자에게 전송한다.
- 위의 폼을 통해 공격자에게 1000000 원을 이체하게 된다.
- 이때 서버는 인증된 세션값을 올바른지, 올바른지 인식하지 못하므로 송금을 수행하게 된다.
예방
- 사용자 차원의 예방
- 사용하지 않는 웹 애플리케이션 로그아웃
- 로그인 정보 안정하게 보관
- 여러 웹사이트를 동시에 사용하지 않는다.
- 서버 차원의 예방
- CSRF Token
- 서버에서는 모든 폼 요청에 대해 CSRF 토큰을 생성하고 폼에 포함시켜 요청 시 검증한다.
- SameSite 쿠키 속성 설정
- 쿠키가 언제나 동일한 사이트에서 전송되도록 하는 방법
- Referer 검증
- HTTP Referer 헤더는 요청이 시작된 웹 페이지의 URL을 제공한다.
- Referer 헤더를 검증하여 요청이 유효한지 여부를 가린다.
- Referer 헤더를 변경할 수 있으므로 그다지 실효성을 갖진 않는다.
- 단, REST API는 stateless (session 이나 cookie 를 사용하지 않기 때문에) 하며, CORS 를 사용하여 다른 도메인에서도 API를 호출할 수 있도록 하기 때문에 CSRF를 사용하기 어렵다
- CORS : 다른 도메인에서 리소스에 접근하는 것을 허용하는 보안 기능
- 따라서 spring security 에서 기본적으로 제공하는 csrf 공격을 방지하는 기능을 spring security를 통해 disable 시켜 헤더에서 검사하지 않게 한다.
- CSRF Token
아래 예시에서 CSRF Token 에 대한 사용법을 spring security 를 사용하여 간략히 알아본다.
예시
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// CSRF 설정 추가
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
// ...
}
- HttpOnly가 설정되어 있다면 javascript 에서 Cookie에 접근할 수 없으므로 false로 한다.
- 위에서 설명했듯, csrf token 은 spring security 에서 기본적으로 제공한다.
- spring security를 사용하지 않는다면, 유저가 로그인할 때 session에 임의의 값을 csrf token 으로 직접지정하거나, cookie 나 header에 저장할 수 있겠다.
<!DOCTYPE html>
<html>
<head>
<!-- CSRF Token을 생성하기 위한 태그 추가 -->
<meta name="_csrf" th:content="${_csrf.token}" />
<meta name="_csrf_header" th:content="${_csrf.headerName}" />
</head>
<body>
<form method="POST" action="/form">
<!-- CSRF Token을 전송하기 위한 hidden 태그 추가 -->
<input type="hidden" name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<!-- form 입력 필드들 -->
<input type="text" name="username" />
<input type="password" name="password" />
<button type="submit">로그인</button>
</form>
</body>
</html>
- 클라이언트에서는 csrf token을 전송하며 함께 보내준다
@Controller
public class MyController {
@PostMapping("/form")
public String handleFormSubmit(@RequestParam("username") String username,
@RequestParam("password") String password,
HttpServletRequest request) {
// CSRF Token 검증하기
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (token != null) {
String csrfToken = token.getToken();
String csrfHeader = request.getHeader("X-CSRF-TOKEN");
if (!csrfToken.equals(csrfHeader)) {
throw new IllegalStateException("Invalid CSRF token.");
}
}
// ...
}
}
- 서버에서는 위와 같이 csrf token을 클라이언트로부터 받아 검증하는 절차를 거칠 수 있게 된다.
'Java, Spring' 카테고리의 다른 글
코드로 뜯어보는 System.out.println 대신 logger 를 사용해야 하는 이유 (0) | 2023.03.19 |
---|---|
Spring 예제로 보는 보안을 위한 HMAC (2) | 2023.03.11 |
JNI, Java의 Native Code 사용 설명 및 예제 (0) | 2023.03.05 |
Spring 과 Ulimit, Socket 자원 관리에 대해 (0) | 2023.03.05 |
JVM 의 Xmx 와 Xms 를 지정해야 하는 이유에 대해 (2) | 2023.03.02 |
Comments