HTTP Cookie 와 SameSite 정책에 대해서

RookieAND·2023년 5월 11일
0

Solve My Question

목록 보기
20/27
post-thumbnail

✒️ Cookie

  • HTTP 쿠키란, 서버가 사용자의 브라우저에 전송하는 작은 데이터 조각이다. 하나에 최대 4KB 까지 저장할 수 있다.
  • 하나의 클라이언트에 최대 300개까지 저장이 가능하고, 하나의 도메인당 최대 20개의 값만 가질 수 있다.
  • 브라우저는 데이터를 저장한 뒤 동일한 서버에 요청을 보낼 때 저장된 데이터를 요청 헤더에 동봉하여 전송한다.
  • 주로 로그인 상태를 유지하는 세션 관리 혹은 사용자가 임의로 세팅한 옵션이나 테마 등을 저장하는데 쓰인다.
    • 유저 인증에 쓰이는 JWT의 경우 Refresh Token 을 쿠키에 담아 보내는 경우가 대부분이다. (httpOnly, Secure 속성도 추가해서)
    • 사용자가 다크 모드를 선택한 경우, 사이트 재방문 시 이전에 다크 모드를 설정했음을 인지하도록 쿠키에 모드 값을 저장할 수도 있다.
  • 과거에는 클라이언트에 데이터를 저장할 때 쓰였으나, 매 요청마다 쿠키가 전송되기 때문에 오버헤드가 생겨 최근에는 스토리지에 담긴다.
  • 서버로부터 온 응답 헤더 내에 Set-Cookie 가 포함된 경우, 브라우저에서는 해당 필드에 있던 데이터를 저장한다.
  • 이후 브라우저에서 해당 서버로 요청을 보낼 때마다 HTTP 헤더의 Cookie 필드에 저장해둔 데이터를 담아 전송한다.
  • 쿠키는 키와 값이 한 쌍을 이루는 형태이며, 만료일 혹은 지속시간과 같은 특별한 속성도 추가할 수 있다.
// 서버로부터 받은 응답 헤더 내에 Set-Cookie 가 있다면, 브라우저에서는 이를 저장한다.
Set-Cookie: RefreshToken=...; Domain=localhost; SameSite=Lax; 

Cookie: RefreshToken=...;
  • 일반적으로 쿠키는 브라우저가 닫힐 때 지워지며, 특정 브라우저의 경우 현재 세션이 끝나는 시점을 정의하고 재시작시 세션을 복원해 쿠키를 무기한 유지하기도 한다.
  • 만약 정해진 기간에만 쿠키를 보존시키고 싶다면, Expires 속성을 통해 명시된 일자에 쿠키를 삭제하거나 Max-Age 속성에 명시된 기간 이후 쿠키를 삭제할 수 있다.
// Expires 속성을 통해 특정 일자까지 쿠키를 보관하고, 이후에는 삭제하도록 지정할 수 있다.
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

// Expires 속성을 통해 특정 일자까지 쿠키를 보관하고, 이후에는 삭제하도록 지정할 수 있다.
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
  • Domain 속성을 통해 쿠키가 전송되게 할 도메인을 지정해줄 수 있다. 별도로 명시된 도메인이 없다면 쿠키를 보낸 서버의 도메인으로 설정된다.
  • Path 속성은 쿠키를 헤더에 동봉하기 위해 요청 URL 에 반드시 존재해야 하는 경로다. 값은 디렉토리 구분자이기 때문에 서브 디렉토리와 매칭된다.
// Domain, Path 속성을 통해 특정 도메인에서 특정 경로로 요청을 보낼때만 쿠키를 동봉시킬수도 있다.
// localhost:3000 도메인에서 /docs 하위 디렉토리에 요청이 왔을 때만 쿠키를 동봉하도록 설정했다.
Set-Cookie: id=a3fWa; Domain=localhost:3000 Path=/docs
  • Secure 속성이 추가된 쿠키는 오직 HTTPS 프로토콜 상에서 암호화된 요청일 경우에만 전송된다. 만약 HTTP 요청인 경우 설정되지 않는다.
  • httpOnly 속성은 JS document 스펙 내의 document.cookie 로 쿠키에 접근하지 못하게 하는 속성이다.
  • 쿠키에 설정된 도메인을 기준으로 퍼스트 파티 쿠키서드 파티 쿠키로 기준을 정할 수 있는데, 이는 현재 사용자와 접속한 페이지와 쿠키에 설정된 도메인이 일치하는지에 따라서 달라진다.
  • 예를 들어 localhost:3000 에 접속한 사용자가 서버로부터 응답을 받아 localhost:8080 에서 보낸 쿠키를 인계 받았다면, 두 도메인이 서로 다르므로 서드 파티 쿠키로 분류된다.

✒️ Security of Cookie

  • 쿠키에 별도의 설정을 가하지 않으면, 브라우저는 모든 HTTP 요청에 대해서 저장된 쿠키를 동봉하게 되는데 이를 악용하여 CSRF 공격을 당할 수 있다.
  • 요지는 공격자가 개설한 사이트에 사용자가 접속할 경우, 사용자의 브라우저 내에 저장된 쿠키를 악용하여 인증 과정을 무력화 하고 공격자가 유도한 동작을 시행하도록 하는 것이다.
  • 정리하자면 공격자가 설계한 다른 사이트, 즉 다른 Origin 에서 악성 요청이 들어오더라도, 쿠키에 저장된 값은 유효한 데이터라 공격이 성공하게 된다. 이것이 서드 파티 쿠키의 문제점이다.

📒 Same Site Policy

  • 따라서 2020년부터 Chrome 은 SameSite 쿠키를 별도로 신설하고 다른 출처로부터 전송되는 요청에 대해서 쿠키 전송을 제한하도록 하였다.
  • SameSite 정책에 의해 사용자는 총 세 가지 중 하나를 택할 수 있으며, 크롬에서는 기본적으로 Lax 로 설정된다
    • None : 다른 출처의 요청, 즉 서드 파티 쿠키도 전송된다. 단 secure 속성이 있어야 한다.
      • 만약 SameSite 속성을 None 으로 설정했음에도 Secure 속성이 없다면 쿠키가 설정되지 않는다.
    • Strict : 오직 동일 출처의 요청에서 생성된 퍼스트 파티 쿠키만을 전송한다.
    • Lax : 대부분의 서드 파티 쿠키를 전송하지 않으나, 몇 가지 예외적인 케이스에만 전송된다.
      • Top Level Navigation (웹 페이지 이동) 의 경우 유저가 링크를 누르거나 리다이렉트를 통해 이동된 경우가 포함된다. 하지만 <img> 태그나 <iframe> 태그 내에서 페이지를 이동하는 경우에는 Top Level 이라 부를 수 없으므로 전송되지 않는다.
      • 서버의 상태를 바꾸지 않을 것이라 기대하는 GET HTTP Method 요청에 대해서는 쿠키를 동봉한다.
      • 당연하지만 서드 파티 쿠키가 아닌 퍼스트 파티 쿠키, 동일 출처로부터 전송된 쿠키는 그냥 동봉된다.
profile
항상 왜 이걸 써야하는지가 궁금한 사람

0개의 댓글