글 작성 계기
팀 프로젝트 정적 분석 중 아래와 같은 잠재적 보안 취약점이 탐지된 것을 확인했다.

그래서 CSRF가 무엇인지, 우리 코드가 해당 공격에 취약한 지 파악하는 시간을 가지게 되었다.
CSRF란
-
CSRF란
- Cross-Site Request Forgery (사이트 간 요청 위조)
- 웹사이트 취약점 공격 기법.
- 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 특정 웹사이트에 요청하게 하는 공격을 말한다.
-
공격 주요 개념 정리
-
CSRF 가 성공하기 위한 조건 세 가지
- 사용자는 보안이 취앿한 서버로부터 이미 로그인이 되어있는 상태
- 쿠키 기반의 서버 세션정보를 획득할 수 있어야 함
- 공격자는 서버를 공격하기 위한 요청방법에 대해 미리 파악해야 함
-
CSRF 공격이 이루어지는 과정

- 사용자가 서버에 로그인
- 서버에 저장된 세션 정보를 사용할 수 있는 session ID가 사용자의 브라우저 쿠키에 저장된다.
- 공격자는 사용자가 악성 스크립트 페이지를 누르도록 유도합니다.
- 게시판에 악성 URL 기재
- 메일 등으로 악성 스크립트를 전달
- 악성 스크립트가 적힌 페이지 링크를 전달 등등
- 사용자가 악성 스크립트가 작성된 페이지 접근 시, 웹 브라우저에 의해 쿠키가 저장된 session ID와 함께 서버로 요청됨
- 서버는 쿠키에 담긴 session ID를 보고 해당 요청이 인증된 사용자로부터 온 것으로 판단하고 처리
CSRF 공격 방지
- CSRF 공격 방지의 핵심
- 공격자 요청과 서비스 웹사이트 상의 실제 요청을 구분하는 것이다. 이 두 요청을 구분할 수 없다면 CSRF 공격에 취약해질 수 있다
- CSRF 보호를 비활성화 (disable) 해도 되는 경우?
- 클라이언트 기반 인증 방식 (토큰 등)을 사용하는 경우는 각 요청마다 인증하게되므로
- 브라우저가 아닌 애플리케이션의 클라이언트가 이용하는 경우에는 CSRF를 비활성화 할 수 있다.
- 주류 의견: RestAPI는 JWT 등 토큰 기반 인증을 사용하는 경우가 많기 때문에 (stateless하게 개발) disable해도 무방하다
- 그러나 우리 서버는 세션 기반 인증방식을 사용하고 있음
- 애초에 일반적으로 api 서버는 세션보단 JWT 토큰을 사용하는 이유가 따로 있는걸까?
- 그것이 HTTP의 stateless 특성을 잘 살린 완전한 Restful 이기 때문.
그래서 우리 프로젝트는?
-
우리 프로젝트는 서버와 통신하는 api서버이지만, 로그인 만료 기능이라는 요구사항 때문에 세션을 사용한 로그인 방식을 사용하고 있음 (즉, stateless한 프로젝트가 아님)
-
그래서 우리 서버가 CSRF 공격에 취약한가?
- 세션 ID를 어디에 보관하는 지가 중요. 쿠키에 보관한다면 공격에 취약한 상태임.
- 서버 개발자로서의 판단: 세션 ID를 클라이언트에 보관한다는 것은 우리의 책임이 아니고, 세션을 통한 보안 취약상태에 놓이는 것을 방지하는 것이 옳기 때문에 csrf가 disable되어있는 것은 취약하다고 말할 수 있고, 활성화 시키는 것이 옳다.
Reference
https://security.stackexchange.com/questions/166724/should-i-use-csrf-protection-on-rest-api-endpoints