-
오늘은 개발된 소스를 운영하기 위해서 보안취약점 점검등을 하게 되면 자주 발생하게 되는 CSRF 취약점에 대하여 대응 방안을 말씀드리겠습니다. CSRF가 무엇인지에 대해서는 수많은 공식문서와 블로그 등에 있으니 오늘은 대응방법에 대해 바로 말해보도록 하겠습니다. 이번에 설명 드릴 환경은 일반적인 환경이 아니라 하나의 세션에서 돌아가는 시스템이 아니라 WEB/WAS과 완벽히 분리되어 있는 환경에서의 대응 방안에 대해서 설명드리겠습니다.
1. 구성
제가 적용했엇던 시스템은 WAS와 WEB서버가 위와 같이 물리적으로 완전 분리되있는 구성으로 되어 있었습니다. 단순히 WAS는 API서버로의 의미를 가지고 있는 시스템 이였습니다. 일단, CSRF토큰을 공유하기 위해서는 대표적으로 세션을 통해 공유되고, 이를 통신시에 Http Header에 포함하여 주고 받으며 처리합니다.
하지만, 물리적으로 아예 분리되있는 환경에서 Web과 WAS가 별개로 구성되어 있을 때는 이러한 세션을 통한 방식이 잘 되지 않습니다. 물론, Web의 빌드 경로를 맞추어서 WAS의 static한 경로에 추가하여 세션을 공유하게 하는 방식도 있습니다. 오늘은 이러한 방식 보다 조금 더 편리한 방법을 소개시켜 드릴려고 합니다.
2. WAS (SpringBoot)
@GetMapping("/csrf") public CsrfToken getCsrfToken(HttpServletRequest request) { return (CsrfToken) request.getAttribute(CsrfToken.class.getName()); }
우리는 가장 먼저 CSRF토큰이 영향을 미치는 범위를 알아야 됩니다. HTTP GET 통신은 리소스를 제공하는 용도 일뿐 리소스의 상태를 변화시키지 않는 용도로 사용합니다. 물론, 예외적으로 GET으로 리소스에 접근하고 수정하는 행위가 시스템에 포함되어 있다면 해당 방법은 사용할 수 없습니다. 그렇지 않을 때엔 위와 같이 예외적으로 GET요청을 통해 CSRF토큰을 발급 받고 발급받은 토큰을 클라이언트로 넘겨줄 수 있습니다.
3. WEB (VUE)
import axios from 'axios'; const api = axios.create({ baseURL: 'apiURL', withCredentials: true, }); api.interceptors.request.use((config) => { const csrfToken = '상태관리에서 가져온 토큰'; if (csrfToken) { config.headers['X-CSRF-TOKEN'] = csrfToken; } return config; }); export default api;
제 시스템은 vue프레임워크와 axios라이브러리를 사용하였고, vue, axios 이외에도 모든 프레임워크 및 Fetch 등에서 사용 가능한 방식 입니다. 저는 넘겨온 데이터를 임의의 공간(상태관리 저장소)에 저장해두 었다가, 이를 꺼내어 통신의 전처리과정에 헤더에 포함시키는 작업을 해주었습니다.
이후, 위와 같은 코드를 통해 최초 1회의 get통신을 통해 받아온 csrf토큰을 통신의 전처리과정에서 header에 포함시켜주고, 이후 POST요청을 하게 되면 정상적으로 csrf인증 절차가 완료되는 것을 볼 수 있습니다. 이렇게 우리는 특이케이스에서 CSRF인증처리를 한 케이스를 보았습니다. 이외에도 다양한 방법들이 있으니 참고용도로만 봐주시면 됩니다.
오늘은 이렇게 간단히 csrf처리에 대해서 알아보았습니다. 실제 프로젝트를 하다보면 보안취약점 점검을 꼭 하게되고 이러한 점검을 통과하기 위해서라면 무조건 처리되어있어야 되는 것이 csrf입니다. 이 외에도 다양한 케이스에 따라 그 상황에 맞는 csrf대응 방안이 있으니, 자신의 프로젝트 상황을 보고 방식을 채택하면 좋습니다.
반응형'frontend > javascript&web' 카테고리의 다른 글
[Web] 순수 자바스크립트로 양방향 데이터 바인딩 구현(Pure Javascript Two-way Data binding) - 추가작업(이벤트 재할당) (0) 2023.06.13 [Web] 순수 자바스크립트로 양방향 데이터 바인딩 구현(Pure Javascript Two-way Data binding) (0) 2023.06.12 [사이드 프로젝트 회고] 코드 복붙 서비스 개발기 - 1(기획, 구현물) (0) 2022.11.13 [웹 최적화] 이미지 로딩 최적화(Image loading Optimzation) (0) 2022.09.13 이벤트 위임 - 캡처링/버블링 (Event Delegation - Captruring / Bubbling) (0) 2022.02.21