Spring Security를 사용하는 예제들을 보면 기본적으로 csrf.disable()을 깔고가는 예제들이 많다. CSRF 공격은 쿠키+세션이 있어야 공격이 가능한데 요즘에는 Stateless하게 api 서버를 만들고 세션 베이스가 아닌 토큰 베이스로 인증을 하다보니 쿠키를 사용할 일이 없어서 csrf를 disable하는 것이다. 그렇다면 좀 더 자세히 CSRF 공격이 무엇인지 알아보도록하겠다.
CSRF 공격이란?
CSRF는 Cross Site Request Forgery인데 한국말로는 사이트 간 위조 요청이다. 사용자가 본인도 모르는 사이에 해커가 의도한 요청을 웹사이트에 하게 되는 것이다. CSRF 공격은 쿠키와 세션을 통해 당하게 되는데 어떻게 공격을 당하는지 알기 위해 먼저 세션과 쿠키에 대해서 알아보도록하자.
쿠키와 세션
쿠키와 세션은 스프링에서 인증을 하는데 필요하다. 서버에 로그인을 하면 서버에 세션이 생기고 JSESSIONID라는 쿠키를 사용자에게 전달해준다. 그리고 사용자는 서버에 요청할 때마다 JSESSIONID라는 쿠키를 서버에 전달하고 서버는 이 쿠키를 통해서 어떤 사용자인지 확인하고 인증을 완료한다.
CSRF 공격 과정 및 조건
CSRF 공격에 필요한 전제조건
1. 사용자가 서버에 인증을 해서 세션 및 쿠키가 생성되었다.
2. 공격자가 세션 쿠키를 획득할 수 있다.
3. 공격자가 서버의 API 명세를 알고 있어야 한다. ex)유저 조회는 http://localhost:8080/users
CSRF 공격 과정
1. 사용자가 서버에 로그인 해서 세션 및 쿠키가 생성된다.
2. 해커가 사용자에게 악성 스크립트가 심어진 페이지를 누르도록 유도한다. 여기서 악성 스크립트는 게시판에 악성스크립트를 포함한 글을 올렸을 수도 있고 메일로 악성 스크립트를 보내는 등의 방식이 있다.
3. 사용자가 링크를 클릭하면 악성스크립트와 함께 세션 쿠키가 서버로 함께 전달되면서 인증을 통과하게 되고 해커가 지정한 요청이 수행 되게 된다. 방법 중에 하나는 이미지 태그를 숨겨 놓는 방법이다. 이미지 태그는 클릭하지 않아도 요청을 바로 하기 때문에 페이지에 진입하는 순간 자동으로 요청이 날아간다.
<img src="http://localhost:8080/change?name=wassupbro" style="width: 0px; height: 0px;"/>
CSRF 방어 방법
1. Referrer 검증
서버에서 사용자의 요청에 Referer 정보를 확인하게 하는 방법이다. Request Header에 담겨오는 referrer의 정보를 확인해서 서버와 동일한 도메인인지 확인한다. 해킹은 다른 사이트에서 이뤄지기 때문에 CSRF 공격을 할 경우 referrer가 달라서 방어가 가능해진다.
2. Double Sumit Cookie 검증
브라우저의 same origin 정책을 이용한 것인데, origin이 다른 곳에서는 자바스크립트로 쿠키 값을 CRUD 할 수 없다는 점을 이용한다. 클라이언트에서 쿠키와 요청헤더에 각각 uuid를 생성해서 보내는 방법인데, 만약 origin이 다른 사이트에서 CSRF 공격 요청을 한다면 쿠키에 uuid가 생성되지 않을 것이다. 서버에서는 쿠키와 요청헤더의 값이 동일한지 비교하면 되는데 다른 사이트에서 요청을 했을 경우 쿠키값이 없을 것이기 때문에 방어가 가능해진다.
3. CSRF 토큰 검증
서버에서 임의의 CSRF 토큰을 만들어서 저장해놓고 클라이언트에 전달해준다. 클라이언트에서는 쿠키가 아닌 다른 곳에 CSRF토큰을 가지고 있다가 토큰과 함께 전달한다. 다른 사이트에서 요청을 할 경우 서버에서 받은 CSRF를 가지고 있을 수가 없기 때문에 서버에서 인증이 실패하게 된다.
'Spring' 카테고리의 다른 글
Spring - Security SuccessHandler 와 FailureHandler (0) | 2022.08.12 |
---|---|
Spring - @Component @Service Annotation 들의 차이 (0) | 2022.08.09 |
Spring - Oauth2 Authorization Server에 대해서 (0) | 2022.08.06 |
Spring Boot - Oauth2 AuthorizationServer(authorization_code) 구축하기 (React 연동) (0) | 2022.08.05 |
[Spring] Ioc(제어의 역전)와 DI(의존성 주입)란? (0) | 2022.07.26 |