Post View

HTTP 통신간의 쿠키와 세션의 동작방식

쿠키와 세션에 대한 자세한 정보를 원하신다면 괜찮다고 생각하는 글을 쿠키와 세션 하단에 링크를 남겨두었으니 읽어보시기 바랍니다.

쿠키: 클라이언트(브라우저) 측에 저장되는 데이터로 사용자가 임의로 조회, 추가, 수정, 삭제가 가능한 임시 데이터

참조 링크

세션: 브라우저의 인증을 위해 서버 측에 저장되는 임시 데이터

참조 링크

HTTP 프로토콜의 비연결성(Connectionless) 무상태(Stateless)라는 특성으로 인해 서버는 클라이언트(브라우저)가 몇 번을 접속하더라도 해당 클라이언트가 기존에 접속한 클라이언트(브라우저)인지 판단할 수 없다.

하지만 로그인과 같은 기능을 구현하기 위해서는 요청을 보낸 클라이언트가 누구인지를 식별할 수 있어야 하는데, 그래서 매 요청마다 클라이언트는 자신의 쿠키를 서버에 전달하고 서버는 해당 쿠키의 세션ID를 확인하여 기존에 접속된 사용자인지를 판단한다.

클라이언트가 웹서버로 최초 연결 시 서버는 클라이언트의 쿠키 정보에서 세션ID 정보가 있는지 판단하고, 만약 세션ID가 없거나 만료되었다면 새로운 세션 정보를 생성한 뒤 세션ID를 클라이언트의 쿠키에 저장한다.
이후 추가적인 요청(Request)마다 쿠키정보에 있는 세션ID 를 이용하여 세션정보를 확인하고, 이를 통해 해당 클라이언트가 어떤 사용자인지를 식별할 수 있다.

위의 내용만으로는 이해가 어려울 수 있으니 아래의 예제를 보고 쿠키와 세션의 관계를 간략하게 알아보겠습니다.

예제 1. 로그인/로그아웃

1. 최초 사이트 접근 시 서버는 새로운 세션 연결 및 브라우저의 쿠키에 세션 ID를 추가한다.

2. 사용자가 로그인 화면에서 회원 아이디, 비밀번호를 입력하고, 서버는 DB 조회를 통해 해당 사용자의 인증 정보가 일치하는지 확인한다.

3. 인증 정보가 일치한다면, 해당 사용자의 회원 아이디 정보를 세션에 저장한다.

4. 새로운 요청이 들어오더라도 쿠키에 있는 세션 ID로 세션 정보를 찾고, 세션 정보의 회원 아이디를 확인하여 로그인된 사용자라고 식별한다.

5. 해당 세션 자체를 폐기하거나, 세션 정보의 로그인 정보를 삭제함으로써 로그인 정보를 찾지 못하게 하여 로그아웃을 한다.

이런식으로 로그인을 위해서는 서버의 세션과 세션 정보를 찾을 세션ID가 함께 필요합니다.

그렇다면 아래의 문제를 보면서 추가적인 정보를 알아보겠습니다.

문제

1. 브라우저에 있는 세션ID가 삭제된다면 어떻게 될까?

세션ID가 삭제되면 [예제 1-1]에 적은 것 처럼 서버 입장에서는 세션ID를 확인할 수 없으니 새로운 세션을 추가하고, 해당 세션에 대한 세션ID를 클라이언트의 쿠키에 저장합니다.

2. 브라우저에 있는 세션ID를 다른 브라우저로 복제 시엔 어떻게 될까?

세션ID가 복제되어 다른 브라우저의 쿠키에 추가되는 경우 서버 입장에서는 해당 브라우저에 있는 세션ID에 대한 정보가 있으므로 같은 사용자라고 판단한다.
만약 해당 세션정보에 [예제 1-3]에서 저장된 로그인된 정보가 있는 경우 해당 세션ID가 있는 모든 브라우저에서 각각 로그인이 되어있는 것으로 나타나며 이런 방법을 이용한 해킹 방법을 "세션 하이재킹"이라고 한다.

3. 브라우저가 종료되면 세션 쿠키인 세션ID는 삭제된다. 그렇다면 세션 정보도 삭제되는 걸까?

브라우저가 종료되는 경우 세션 쿠키에 해당하는 세션 ID는 쿠키상에서 삭제된다.
그리고 서버입장에서는 확인할 세션 ID가 없기 때문에 브라우저 종료 전에 로그인 되어있었더라도 다시 접속하는 경우 로그아웃이 된 것으로 보여진다.
그럼 서버에 있는 세션 정보도 삭제된걸까?

답은 아니다.
세션의 경우 웹서버에 설정되어있는 세션 만료시간을 따라가며, 해당 만료시간이 종료되기 전까지는 세션은 계속해서 유지된다.
만약 세션 만료시간 전에 같은 클라이언트가 접속을 하면 세션 만료시간은 다시 갱신되고 세션 ID가 클라이언트에서 삭제되더라도 세션 만료시간 이내에 다시한번 같은 세션 ID를 쿠키에 추가하면 세션이 유지되는 것을 볼 수 있다.

만약 여기서 세션 만료시간을 무제한으로 둔다면 같은 세션이 영원히 남아있게 되고, 저장된 세션(메모리, 스토리지, 데이터베이스 등)이 더 이상 저장할 수 없는 상태가 되면 여러가지의 치명적인 오류가 발생하게 될 것이다.

그렇다고 세션 만료시간이 너무 짧다면 예를 들어 로그인된 사용자가 글을 작성 중에 세션이 만료되어 정상적으로 저장되지 않는 문제가 발생할 수 있으므로 서비스에 맞춰 적절한 만료시간을 지정해주어야 할 것이다.

아래의 예제는 위의 내용을 이해하기 쉽도록 놀이공원과 놀이공원 이용객에 비유하여 작성한 내용입니다.

사전정의 내용

  1. "놀이공원(세션)"은 오전 9시부터 오후 6시까지 입장이 가능(세션 만료시간)하다.
  2. 입장 시 입장권(세션ID)을 구매해야하며 구매한 입장권은 폐장(세션 만료) 시까지 이용이 가능하다.
  3. 폐장 이전에 놀이공원에서 퇴장(브라우저 종료)하실 경우 입장권은 폐기(세션쿠키 삭제)된다.

예제 2. 놀이공원 비유

1. 사용자는 놀이공원을 9시에 입장한다.
    * 페이지를 접속하여 세션을 생성한다.

2. 처음엔 입장권이 없으므로 입장권을 구매하고 여러가지 놀이기구를 이용한다.
    * 세션ID가 없으므로 세션ID를 클라이언트에게 제공하고 이후 요청 시 해당 세션ID를 세션 정보를 사용한다.

3. 도중 점심을 먹기 위해 놀이공원에서 나간다. 이 때 기존 입장권은 잘라서 폐기한다.
    * 브라우저를 종료하면서 쿠키에 존재하는 세션ID를 폐기한다.

4. 점심을 먹고 다시 놀이공원에 입장하려 했지만, 이미 입장권이 폐기되어 다시 사용할 수 없었다.
    * 기존 세션은 여전히 존재하지만 입장권이 폐기되었으므로 기존 세션 정보에 접근할 수 없다.

5. 결국 새로운 입장권을 다시 구매하여 놀이공원을 이용한다.
    * 새로운 세션을 생성하고 세션ID를 발급받아 다시 서버와 통신한다.

이런식으로 로그인을 하기 위해서는 서버의 세션과 세션 정보를 찾을 세션ID가 모두 필요합니다.

위의 예제에서 알 수 있는 점은 사용자의 브라우저에 있는 쿠키 정보 내 세션ID(입장권)가 폐기 된다고 하더라도,
서버에서는 세션ID에 해당하는 세션 정보는 만료시간(폐장 시간)이 지나지 않았으므로 여전히 남아있다는 점입니다.

또한 세션ID(입장권)가 폐기된 시점에서 다시 한번 페이지 접속(놀이공원 입장)을 하기 위해서는 새로운 세션ID(입장권)를 쿠키에 저장해야하구요.
여기서 중요하게 생각하셔야 할 점은 클라이언트의 쿠키에 존재하는 세션ID의 만료와 서버의 세션의 만료는 별개라는 점! 기억하시기 바랍니다.
그렇다면 위의 예제를 조금 변형해서 더 알아보겠습니다.

예제 3. 놀이공원 입장권 복제

1. 예제 2-2까지 동일

2. 도중 점심을 먹기 위해 놀이공원에서 나간다. 이 때 기존 입장권을 복사해둔 뒤 하나의 입장권만 잘라서 폐기한다.
    * 브라우저의 쿠키정보에 존재하는 세션ID 값을 메모장에 복사한 뒤 브라우저를 종료한다.

3. 점심을 먹고 다시 놀이공원에 입장하면서 복사한 입장권을 제시하고 놀이공원을 이용한다.
    * 브라우저의 쿠키 정보에 메모장에 복사해둔 세션ID를 추가한 뒤 페이지를 새로고침 한다.

4. 정상적으로 놀이공원 이용이 가능해진다.
    * 세션ID에 해당하는 세션 정보가 아직 서버에 존재하므로 기존 로그인 정보로 로그인된다.

아까 이야기 했던 것처럼 "세션 만료 시간(놀이공원 폐장 시간)"은 "쿠키의 만료(입장권의 폐기)"와는 별개이기 때문에 세션ID(입장권)를 복사한다면, 기존의 입장권으로도 같은 세션(놀이공원 입장)을 이용할 수 있게 됩니다.

하지만 세션ID(입장권)이 늘어난다고 해서 세션 정보(놀이공원)가 늘어나는건 아닙니다.

마지막으로 해당 입장권을 복사하여 악용하는 예제를 보여드리겠습니다.

예제 4. 놀이공원 입장권 탈취 및 복제

1. 예제 2-2까지 동일

2. 입장권을 잠깐 풀어놓고 화장실을 간 사이에 다른 사람이 내 입장권을 복사해간다.
    * XSS등의 보안 취약점을 이용하여 쿠키 내 세션ID를 탈취하는 "세션 하이재킹"

3. 놀이기구를 이용하고 점심을 먹으려고 놀이공원을 벗어난다.
    * 브라우저 종료로 내 브라우저 내 세션ID는 삭제된다.

4. 그러나 내 입장권을 복사해간 사람은 내 입장권으로 놀이공원 폐장 시 까지 놀이기구를 이용할 수 있게 된다.
    * 서버의 세션은 계속 유지되므로 만료되기 전이라면 탈취된 세션ID로 나와 같은 권한을 누릴 수 있게된다.

위에서 말하는 세션 하이재킹으로 회원 권한을 빼앗기게 되면 해커가 내 계정에 대한 권한을 마음대로 사용할 수 있게 됩니다.
만약 관리자 권한을 빼앗기게 된다면 피해가 더욱 크겠죠?
이러한 세션 하이재킹을 막기위한 방법 또한 있지만 그 내용까지는 이 글에 적기엔 안그래도 내용이 많아... 생략하였습니다.

구글에 세션 하이재킹으로 검색하면 좋은 예제들이 많으니 그걸 보며 실습해보시는 것도 추천드립니다.

마지막으로 정리 한번 하고 글을 마무리 하겠습니다.

  1. 세션과 쿠키는 별개의 개념이다.
  2. 세션은 HTTP의 비연결성, 무상태에 의해 사용된다.
  3. 클라이언트의 쿠키에 저장된 세션ID가 없거나 만료된 경우 서버는 세션을 생성하고 새로운 세션ID를 클라이언트의 쿠키에 저장한다.
  4. 클라이언트에 존재하는 세션ID는 사용자에 의해 복제될 수 있다.
  5. 로그인된 세션ID를 복제하여 별개의 클라이언트에 입력하면 인증 없이 로그인 된 상태로 이용할 수 있다.
  6. 세션ID를 해킹을 통해 복제하는 것을 "세션 하이재킹"이라고 한다.

브라우저 종료 시 세션도 삭제되는게 아닌가요? 라는 질문을 많이 봐서 답변을 해주다가 이렇게 정리해보았고,
최대한 이해하기 쉽게 적으려고 노력했지만 그래도 어렵다고 느껴지시는 분들은 댓글에 남겨주시거나 더 알기 쉽게 정리된 글을 찾아보시기를 추천합니다.

글에 오류가 있거나 이해하는데 어려움이 있다면 댓글에 남겨주시기 바랍니다.
감사합니다.

Comments