이 전에 프로젝트에서 SpringSecurity를 사용하다 CSRF에 대해 알아보게 되었고 글을 쓴 적이 있었다. 오늘 LMS강의로 SpringSecurity파트 중 CsrfFilter를 공부했는데, 이전 글과 관련하여 더 쉽고 확실하게 정리할 수 있을 것 같아서 작성한다. (이전 글 : Rest Api 서버에서의 CSRF방어와 JWT (JWT 도입))
CSRF(Cross-site request forgery) 사이트간 요청위조
- 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 웹 서비스에 요청하게 하는 공격
- 핵심은 웹서비스가 인증된 사용자의 웹브라우저를 신용하고 있다 는 것을 노린 공격
- 2개의 조건 필요
- 사용자가 웹 서비스에 로그인한 상태
- 사용자가 악의적인 피싱사이트에 접속
- 공격과정
- 사용자가 로그인하여 쿠키를 발급받음
- 피싱사이트에 접속
- 사용자가 피싱사이트에서 csrf공격이 담긴 html페이지를 받음
ex) <img src = "https://travel.service.com/travel_update?.src=Korea&.dst=Hell"> //보통 이미지를 가장한 공격코드를 사용
- 사용자가 이미지를 로드하기위해 위 링크로 요청을 보내게됨
* 이 예시 코드에서는 요청의 출발지와 도착지를 위조함
* 위키백과 참고 - 사이트 간 요청 위조
CSRF 공격 대응
방법 1. Referrer 검증
요청하는 페이지가(위 공격과정 3에 해당) 정상적으로 웹서비스에서 제공한 페이지인지 검증
방법 2. CSRF Token 검증 (더 확실한 방법)
- 사용자가 서버 접속시 세션에 CSRF 토큰을 발급해주고, 이 토큰을 서버의 세션(CsrfTokenRepository)에 저장
* 로그인 여부와 상관 없이- 사용자는 리소스 변경(POST, PUT, DELETE) 요청 시 이 토큰을 함께 전달
- 서버가 해당 토큰이 세션에 존재하는지 확인 후 승인
* POST 요청은 반드시 CSRF토큰이 필요, 따라서 로그인시도도 이 CSRF토큰이 없으면 거부
CsrfFilter
-> SpringSecurity에서 CsrfFIlter가 위 두 번째 방법으로 CSRF 방어를 담당함