CSRF토큰이뭔데이렇게저를괴롭히는건가요

메인프로젝트를 진행하면서 나를 힘들게하던 CSRF토큰에 대해 알아보자.

 

쿠키에 대한 아주 기본적인 개념은

쿠키🍪여기에 작성해두었다.

 

쿠키와!!! CSRF

쿠키에 별도로 설정을 하지않는다면, 크롬을 제외한 브라우저들은 모든 HTTP요청에 대해서 쿠리를 전송하게 된다. 그 요청에는 HTML문서 요청, HTML 문서에 포함된 이미지 요청, XHR 혹은 Form을 이용한 HTTP 요청등 모든 요청이 포함된다.

 

CSRF(Cross Site Request Forgery)는 다른 사이트에서 유저가 보내는 요청을 조작하는 공격이다

예) 이메일에 첨부된 링크를 누르면 내 은행계좌의 돈이 빠져나가는 방식의 해킹

클라이언트가 자신이 하고싶은 행동에 대한 명령을 내렸는데, 해커가 페이지를 바꿔치기 하는등의 방법으로 해킹을 시도하기 때문에 이를 방지하기 위해 CSRF 토큰이 존재한다.

  1. 공격대상 사이트는 쿠키로 사용자 인증을 수행한다
  2. 피해자는 공격 대상 사이트에 이미 로그인이 되어있어서 브라우저에 쿠키가 있는 상태
  3. 공격자는 피해자에게 그럴듯한 사이트 링크를 전송하고 누르게한다.
  4. 링크를 누르면 HTML문서가 열리는데, 이 문서는 공격 대상 사이트에 HTTP요청을 보낸다
  5. 이 요청에는 쿠키가 포함(서드 파티 쿠키)되어 있으므로 공격자가 유도한 동작을 실행할 수 있다.

CSRF토큰은 서버에 들어온 요청이 실제 서버에서 허용한 요청이 맞는지 확인하기 위한 토큰이다.

 

SameSite 쿠키

SameSite 쿠키는 서드파티 쿠키의 봉나적 문제를 해결하기 위해 만들어진 기술이다. 크로스 사이트(cross-site)로 전송하는 요청의 경우 쿠키의 전송에 제한을 두도록한다.

samesite 쿠키의 정책으로 None, Lax,Strict 세가지 종류를 선택할 수 있고, 각각 동작하는 방식이 다르다.

 

None SameSite가 탄생하기 전 쿠키와 동작하는 방식이 같다. none으로 설정된 쿠키의 경우 크로스 사이트 요청의 경우에도 항상 전송된다. 즉, 서드 파티 쿠키도 전송된다. 보안적으로도 samesite를 적용하지 않은 쿠키와 마찬가지로 문제가 있는 방식이다.
Strict 가장 보수적인 정책이다. strict로 설정된 쿠키는 크로스 사이트 요청에는 항상 전송되지 않는다. 즉, 서드 파티 쿠키는 전송되지 않고, 퍼스트 파티 쿠키만 전송된다.
Lax strict에 비해 상대적으로 느슨한 정책이다. Lax로 설정된 경우, 대체로 서드 파티 쿠키는 전송되지 않지만, 몇 가지 예외적인 요청에는 전송된다.

 

 

Secure 정책

sameSite 속성으로 None을 사용하려면 반드시 해당쿠키는 secure 쿠키여야한다. secure 쿠키는 HTTPS가 적용된(암호화된) 요청에만 전송되는 쿠키이다. 이 정책을 구현하는 브라우저는 크롬밖에 없다.

 

 

csrf 토큰은 항상 에러 403을 뱉어냈다.

백엔드는 장고를 사용했기때문에 백엔드에서 samesite 설정과 헤더 이름을 어떻게 설정했는지부터 확인해야했음.

  1. 뷰에서 템플릿을 만들어 넘길때 CSRF 토큰 값을 쿠키에 담아서 보내준다.
  2. 장고에서 설정한 헤더와 쿠키로 CSRF 토큰을 넘기면 된다. (프론트에서)

내가 찾아본 결과

axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = "X-CSRFToken"
axios.defaults.headers.common['X-CSRFToken'] = getCookie("csrftoken");

 

이걸 작성해야한다고 했다.

  1. 백엔드에서 쿠키로 CSRF 토큰을 발급해준다 
  2. 프론트에서 그 쿠키를 가지고 axios 호출 시 Header로 보낸다.
구분 백엔드 프론트 비고
쿠키명 csrftoken XSRF-TOKEN 백엔드 -> 프론트
헤더명 HTTP_X_CSRFTOKEN X-XSRF-TOKEN 프론트 -> 백엔드

 

설정 기본 값이 다르기때문에 axios의 설정을 장고에 맞게 맞춘다.

axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = 'X-CSRFToken'

 

서버는 인증된 사용자에게 csrftoken을 setCookie 형태로 response header에 담아 전송한다.

이를 받은 클라이언트는 이후부터 자신의 Header와 cookie에 토큰을 담은 채로 api call을 하게 되고 서버는 

이 토큰이 헤더에 포함되어 있는 경우에만 DB 수정을 허가한다.

 

그래서 나는 희망을 찾은것 같았다.. 저것만 맞추면 해결 되는걸까..? 하고.. 나는 api 폴더에 instance.ts를 만들어 거기다 저 코드들을 작성했다.

 

하지만!!!!!!!

 

나는.. 안됐다.

바로 써야 했는데 기억이 가물가물하지만 기억을 떠올려서 말해보자면.......

  1. same site에서 경고가 떴다. None으로 바꾸라는 경고였던것 같은데 정확히 기억은 나지않는다
  2. samsite를 해결하니 프론트에서 crsf 토큰에 접근을 못한다.

어떻게 해결했냐면..?

아직 해결하지 못했다.

 

백엔드 레포 깃클론 받아서 내가 로컬에서 서버 돌리고

프론트 테스트를 했다 하하..!

이후엔 최종적으로 배포된 사이트에선 csrf토큰에 접근이 가능하고 자유롭게 쓸수있다.

하지만... 로컬은 아직이다.

그래도 이 프로젝트를 통해서 쿠키관련된 정보들을 더 알 수 있게 되어 좋은 경험이였다고 생각한다💖

완전 럭키비키 🍀

 

참고

개발일지 2 CSRF 토큰이날 괴롭힌다

브라우저 쿠키와 SameSite 속성

'기타' 카테고리의 다른 글

Github Action을 이용한 AWS S3로 자동 배포하기  (1) 2024.10.07
RESTful API란  (0) 2024.08.14
동기식 처리 모델 vs 비동기식 처리 모델  (0) 2023.12.18
JWT(Json Web Token)  (0) 2023.12.14
쿠키  (3) 2023.12.12

댓글