이전까지 나의 일상이 된 웹과 어플리케이션들을 사용하며 단 한번도 어떻게 정보가 전송되고 전달받을 수 있는지 궁금해 했던적이 없었다.
Node.js와 MongoDB를 통한 서버를 구축해보며, 구축에 필요한 여러 모듈들과 프레임워크들, 미들웨어들의 원리를 알지 못하더라도 정보이동의 흐름으로 어느정도 알고 있다고 착각했었다.
‘로그인 이용자 상태 유지’ 부분을 구축하다가 쿠키와 세션, 토큰이 구분이 되지않은 상태에서 모듈들만 사용하려다 보니 연결이 정상적으로 되지않았고, 매우 비효율적으로 시간을 쓰고 있다는것을 알았다.
이전까지는 쿠키는 클라이언트 로컬에 정보를 담아두고, 세션은 서버에 정보를 담아둬서 상태를 유지한다라고만 알고 있었다. 이렇게 둘은 완전 독립적이며, 세션이 보안상 쿠키에 우수하기 때문에 쿠키는 거의 쓰이지 않을 것이라고 생각했고, 이 생각 때문에 passport를 통한 인증구현을 몇번을 읽어도 이해하지 못한 상태였다.
이런 상태라면, 다음 단계를 진행할 수 없다고 생각했고, passport-jwt를 이용한 local사용자 및 OAuth 구현은 조금 뒤로 미루고 Node.js의 express 중심으로 쿠키와 세션에 대해서 알아보기로 했다.
HTTP 프로토콜의 특징
HTTP는 Connectionless하고, Stateless하다고 한다.
Connectionless란, 클라이언트가 행위를 통해 서비스를 제공받기 위해 서버에 request(요청)를 하면 서버는 클라이언트의 요청값에 따라 클라이언트에게 response(응답)하게 된다.
이렇게 한번의 request — response의 결과로 클라이언트는 어플리케이션이 제공하는 서비스를 받게되면서, 서로의 접속을 끊게 된다는 특성이다.
Stateless란, 접속을 끊는 순간 서버와 클라이언트간의 통신이 끊키고 상태정보를 유지하지 않는다는 특성이다.
이 두가지 특성은 장점이자 단점이 되는데, 접속을 유지함에 따르는 리소스를 줄일 수 있는 장점과 통신을 할때마다 클라이언트 인증을 해야한다는 단점이 있다.
이러한 단점을 보완하기 위해 쿠키, 세션이 생기게 되었다.
쿠키란?
쿠키(cookie)란 하이퍼 텍스트의 기록서(HTTP)의 일종으로서 인터넷 사용자가 어떠한 웹사이트를 방문할 경우 그 사이트가 사용하고 있는 서버를통해 인터넷 사용자의 컴퓨터에 설치되는 작은 기록 정보 파일을 일컫는다. HTTP 쿠키, 웹 쿠키, 브라우저 쿠키라고도 한다. 이 기록 파일에 담긴 정보는 인터넷 사용자가 같은 웹사이트를 방문할 때마다 읽히고 수시로 새로운 정보로 바뀐다. — 위키백과
쿠키는 ‘루 몬틀리’라는 넷스케이프의 프로그램 개발자가 개발한 것으로, 이전까지의 HTTP 통신은 사용자의 정보를 기록할 수 있는 수단이 없이 일방적인 정보 전달의 수단일 뿐이었다고 한다.
Statless상태의 프로토콜에서 상태기반정보를 기억할 수 있는 쿠키가 개발되고 서버는 쿠키를 이용하여 사용자 맞춤형 서비스, 웹 계정 권한부여, 로그인 유지 등 현재는 일상이 되어 당연하게 여겼던 서비스들을 제공 할 수 있게 되었다.
예로, 만약 쿠키가 없다면 11번가에서 어제 봤던 제품을 구매하기 위해서는 제품명을 쳐서 다시 찾아가야하고 장바구니라는게 없어서 수첩에 내가 구매해야할 제품들을 적어서 하나씩 구매해야 할 것이다. 또한, 매 제품 구매 단계마다 로그인을 해야하는 번거로움이 있을 것이다.
쿠키 옵션
쿠키에는
1. 클라이언트에 저장되는 키와 값들이 하드디스크에 저장되어 참조된다.
2. 파일 안에는 이름, 값, 만료일(이 날짜에 따라 저장), 경로 정보 등이 들어 있다.
이는 세션 관리, 개인화, 트래킹 이라는 목적을 갖게 된다.
위에 쿠키의 내용이 적혀있는 사진을 통해 각 항목의 뜻하는 내용은,
Name : 쿠키의 이름
Value : 쿠키의 내용( 대부분의 경우 raw값을 노출시키 않기 위해 보안처리를 한다.)
Domain : 쿠키가 전송되게 될 호스트들을 명시하며, 만약 명시되지 않았다면 현재 문서 위치의 호스트를 기본값으로 갖는다. 도메인이 설정이 되면, 서브도메인들은 항상 포함이 된다. (ex. www.google.com :기본 도메인 <-> docs.google.com : 서브 도메인)
Path : cookie 헤더를 전송하기 위해서 요청되는 URL내에 반드시 존재해야할 URL이며, “/” 문자는 디렉티브 구분자로 구분한다. (/path 로 지정했다면 하위 path(/path/auth/login …) 역시 포함)
Expires / Max-Age : 만료기한을 걸어둔 쿠키의 쿠키 만료 시간을 제공한다.
Size : 쿠키의 크키
HTTP : Cross-site 스크립팅 (XSS) 공격 및 세션 하이재킹을 방지하기 위해 JavaScript의 Document.cookie API에 접근하지 못하도록 한다.
Secure : HTTPS 프로토콜 상에서 암호화된 요청일 경우에만 전송하도록 강제한다.
Samesite : 쿠키가 cross-site 요청과 함께 전송되지 않았음을 요구하게 만들어, cross-site 요청 위조 공격(CSRF)에 대해 어떤 보호 방법을 제공한다.
Express를 통한 cookie 전송
express에서 기본적으로 제공하는 cookie 객체를 이용하여 우리가 원하는 값을 클라이언트의 쿠키에 넣어보면서 쿠키의 이동과정을 알아보고자 한다.
※ 기본적으로 새로운 페이지에 접근하기전에는 클라이언트는 쿠키를 갖고 있지 않는다.
1. 클라이언트는 방문한 적 없는 최초의 요청한 페이지에 접속하면서 서버는 기본적인 쿠키틀을 제공한다.
2. 제공받은 쿠키는 클라이언트의 로컬 하드에 저장된다.
3. 클라이언트가 재접속시 Request와 Set-cookie값을 서버측으로 전송한다.
4. 서버측에서는 서비스 로직에 따라 클라이언트의 cookie값을 update 하게 된다.
1. 방문 기록이 없는 페이지에 접근하면서 서버측에서 제공하는 쿠키틀을 제공받게 된다. express 모듈에서는 밑 코드처럼
app.get(‘/count’, function(req, res){ let count = req.cookies.count; req.cookies.count = req.cookies.count ? parseInt(req.cookies.count) : count=0 count++; res.cookie(‘count’, count); res.send(‘count : ‘+ req.cookies.count); });
req.cookies를 통해 클라이언트의 cookie에 접근할 수 있고,
res.cookie를 통해 cookie를 클라이언트에 제공할 수 있다.
위 코드에서 end point인 /count로 최초 접근하게 되면 클라이언트에는 쿠키가 없으므로 req.cookies.count를 받아 올 수 없기 때문에 기본 정보들과 count라는 객체를 cookie로 생성하여 클라이언트에게 전달하게 된다.
2. 서버측에서 Response로 받은 쿠키는 브라우저 로컬에 저장되게 된다.
/count에 2번 접속하게 되어 count value가 2인것을 확인 할 수 있다.
3. 클라이언트의 쿠키는 사용자가 요청하지 않아도 Request시 자동으로 Request Header에 넣어서 요청하게 된다.
Requsets cookie는 서버측에서 count를 올리기 전의 정보를 담고 있다.
4. /count 에서 짜인 로직에 따라 cookies.count++ 가 되어 Response 로 count가 2로 업데이트 되는것을 볼 수 있다.
쿠키의 한계
쿠키는 정보보안 측면에서 여러 문제점을 가지고 있다고 한다.
1. XSS(Cross-Site Scripting) 공격
: 공격자가 자바스크립트 문을 이용하여 cookie값을 탈취하는 방법이다.
document.cookie를 사용하는 스크립트 문을 찾아 공격을 해서 탈취한다고 한다.
2. 스니핑(Sniffing) 공격
: 암호화 되지 않은 쿠키값을 사용하는 사이트에서 스니핑 공격을 통해 쿠키정보를 탈취한다.
3. 공용 PC에서 쿠키값 유출
: 사용자가 웹 페이지에 이동하여 사용을 하게 된다면, 원치 않아도 쿠키값이 남아있는 문제가 있다.
4. 호스팅 공유 문제
: 호스팅을 공유하는 사이트를 이용하는 경우, 공유된 사이트중 보안이 취약한 사이트를 찾아 공격을 하면 모든 공유사이트들 역시 공격 당할 수 있는 문제를 가지고 있다.
5. 쿠키의 개인정보 침해 위험
: 웹사이트의 무분별한 수집 및 안일한 보안 구축으로 인한 피해
따라서, 개인정보와 같은 민감한 정보들은 다음에 알아볼 세션이나 토큰 방식으로 인증하는 방식을 이용하여 유출을 방지하다
이렇게 쿠키의 탄생배경과 통신과정, 쿠키옵션 값, 한계를 알아보았다.
다음에는 클라이언트 정보보안 차원에서 조금 더 안전한 세션에 대해서 알아보고자 한다.
참고 :
https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies
http://interconnection.tistory.com/74
https://ko.wikipedia.org/wiki/HTTP_%EC%BF%A0%ED%82%A4
http://expressjs.com/en/4x/api.html#req.cookies