보안/드림핵 강의

[Web Hacking]Cookie & Session 정리

haerim9.9 2025. 2. 1. 20:33

Background: Cookie & Session

웹 서버는 수많은 클라이언트를 어떻게 구별하고 서로 다른 결과를 반환해줄까?

HTTP 프로토콜로 웹 서버와 통신할 때에는 웹 서버에 명령을 내리기 위해 GET, POST와 같은 메소드와 자원의 위치를 가리키는 URL 등이 포함되어 있다.

이외에도 헤더(Header)를 통해서 웹 서버에게 요청을 보내고, 웹 서버는 헤더를 읽고 클라이언트에게 결과 값을 반환한다. 이때, 헤더에는 클라이언트의 정보와 요청의 내용을 구체화하는 등의 데이터가 포함되는데, 클라이언트의 인증 정보 또한 포함될 수 있다.


쿠키
클라이언트의 IP 주소와 User-Agent는 매번 변경될 수 있는 고유하지 않은 정보일 뿐만 아니라, HTTP 프로토콜의 Connectionless와 Stateless 특징 때문에 웹 서버는 클라이언트를 기억할 수 없다.

  • Connectionless: 하나의 요청에 하나의 응답을 한 후 연결을 종료하는 것을 의미한다. 특정 요청에 대한 연결은 이후의 요청과 이어지지 않고 새 요청이 있을 때 마다 항상 새로운 연결을 맺는다.
  • Stateless: 통신이 끝난 후 상태 정보를 저장하지 않는 것을 의미한다. 이전 연결에서 사용한 데이터를 다른 연결에서 요구할 수 없다.


이러한 Connectionless, Stateless 특성을 갖는 HTTP에서 상태를 유지하기 위해 쿠키(Cookie)가 탄생했다.

 

쿠키 : Key와 Value로 이뤄진 일종의 단위로, 서버가 클라이언트에게 쿠키를 발급하면, 클라이언트는 서버에 요청을 보낼 때마다 쿠키를 같이 전송한다. 서버는 클라이언트의 요청에 포함된 쿠키를 확인해 클라이언트를 구분할 수 있다.

일반적으로 쿠키는 클라이언트의 정보 기록과 상태 정보를 표현하는 용도로 사용한다.

쿠키가 없는 통신 : 서버는 요청을 보낸 클라이언트가 누군지 알 수 없기 때문에 현재 어떤 클라이언트와 통신하는지 알 수 없다.
쿠키가 있는 통신 : 클라이언트는 서버에 요청을 보낼 때마다 쿠키를 포함하고, 서버는 해당 쿠키를 통해 클라이언트를 식별한다.

쿠키 변조
쿠키는 클라이언트의 브라우저에 저장되고 요청에 포함되는 정보이다. 따라서 악의적인 클라이언트는 쿠키 정보를 변조해 서버에 요청을 보낼 수 있다.
만약 서버가 별다른 검증 없이 쿠키를 통해 이용자의 인증 정보를 식별한다면 공격자가 타 이용자를 사칭해 정보를 탈취할 수 있다.


세션
 웹 통신에서도 클라이언트가 쿠키를 변조해 서버에 요청을 보낼 수 있다. 따라서, 쿠키에 인증 상태를 저장하지만 클라이언트가 인증 정보를 변조할 수 없게 하기 위해 세션(Session)을 사용한다.


세션은 "인증 정보를 서버에 저장"하고 해당 데이터에 접근할 수 있는 키를 만들어 클라이언트에 전달하는 방식으로 작동한다.
해당 키를 일반적으로 Session ID라고 한다. 브라우저는 해당 키를 쿠키에 저장하고 이후에 HTTP 요청을 보낼 때 사용한다. 서버는 요청에 포함된 키에 해당하는 데이터를 가져와 인증 상태를 확인한다.


쿠키 적용법
쿠키는 클라이언트에 저장되기 때문에 클라이언트는 저장된 쿠키를 조회, 수정, 추가할 수 있다. 클라이언트가 서버에 요청을 보낼 때 저장된 쿠키를 요청 헤더에 넣어 전송하기 때문에 이용자가 요청을 보낼 때 쿠키 헤더를 변조할 수 있다. 쿠키를 설정할 때에는 만료 시간을 지정할 수 있고, 만료 시간 이후에는 클라이언트에서 쿠키가 삭제된다. 쿠키의 만료는 클라이언트(브라우저)에서 관리된다.
쿠키는 서버와 클라이언트 양 측 모두 설정할 수 있다.

 


쿠키 설정


서버
HTTP 응답 중 헤더에 쿠키 설정 헤더(Set-Cookie)를 추가하면 클라이언트의 브라우저가 쿠키를 설정한다.

HTTP/1.1 200 OK
Server: Apache/2.4.29 (Ubuntu)
Set-Cookie: name=test;
Set-Cookie: age=30; Expires=Fri, 30 Sep 2022 14:54:50 GMT;
...


클라이언트
자바스크립트를 사용해 쿠키를 설정한다.

document.cookie = "name=test;"
document.cookie = "age=30; Expires=Fri, 30 Sep 2022 14:54:50 GMT;"



쿠키 열람

Console 활용 : Console 탭에 document.cookie를 입력하면 쿠키 정보를 확인할 수 있다.
Application 활용 : Application 탭에서 좌측에 나열된 목록에서 Cookies를 펼치면, Origin 목록을 확인할 수 있다. 설정 된 쿠키 정보를 확인/수정할 수 있다.

쿠키에는 세션 정보가 저장되어 있고 서버는 이를 통해 이용자 식별하고 인증을 처리한다. 공격자가 이용자의 쿠키를 훔칠 수 있으면 세션에 해당하는 이용자의 인증 상태를 훔칠 수 있는데, 이를 세션 하이재킹(Session Hijacking)이라고 한다.


 

요약

더보기

Connectionless: 하나의 요청에 하나의 응답을 한 후 연결을 종료하는 것을 의미한다.
Stateless: 통신이 끝난 후 상태 정보를 저장하지 않는 것을 의미한다.
쿠키 (Cookie): HTTP에서 상태를 유지하기 위해 사용하는 Key-Value 형태의 값
세션 (Session): 쿠키에 포함된 Session ID를 사용해 서버에 저장된 세션 데이터에 접근하는 방식
세션 하이재킹 (Session Hijacking): 타 이용자의 쿠키를 훔쳐 인증 정보를 획득하는 공격


 Exercise: Cookie, Exercise: Cookie & Session

 

 

Cookie 문제 풀이

Session-basic 문제 풀이


Mitigation: Same Origin Policy

Same Origin Policy (SOP)
브라우저는 인증 정보로 사용될 수 있는 쿠키를 브라우저 내부에 보관한다. 그리고 이용자가 웹 서비스에 접속할 때, 브라우저는 해당 웹 서비스에서 사용하는 인증 정보인 쿠키를 HTTP 요청에 포함시켜 전달한다. 이와 같은 특징은 사이트에 직접 접속하는 것에만 한정되지 않는다. 브라우저는 웹 리소스를 통해 간접적으로 타 사이트에 접근할 때도 인증 정보인 쿠키를 함께 전송하는 특징을 가지고 있다.
이 특징 때문에 악의적인 페이지가 클라이언트의 권한을 이용해 대상 사이트에 HTTP 요청을 보내고, HTTP 응답 정보를 획득 하는 코드를 실행할 수 있다. 이는 정보 유출과 같은 보안 위협이 생길 수 있는 요소가 된다.

 

따라서, 클라이언트 입장에서는 가져온 데이터를 악의적인 페이지에서 읽을 수 없도록 해야 한다. 이것이 바로 브라우저의 보안 메커니즘인 동일 출처 정책(Same Origin Policy, SOP)이다.

Same Origin Policy의 오리진 (Origin) 구분 방법
오리진은 프로토콜(Protocol, Scheme), 포트(Port), 호스트(Host) 로 구성된다. 구성 요소가 모두 일치해야 동일한 오리진이라고 한다.

 

https://same-origin.com/ 라는 오리진과 아래 URL을 비교했을 때 결과

URL 결과 이유
https://same-origin.com/frame.html Same Origin Path만 다름
http://same-origin.com/frame.html Cross Origin Scheme이 다름
https://cross.same-origin.com/frame.html Cross Origin Host가 다름
https://same-origin.com:1234/ Cross Origin Port가 다름



window.open : 새로운 창을 띄우는 함수

object.location.href : 객체가 가리키고 있는 URL 주소를 읽어오는 코드


Same Origin Policy 제한 완화
SOP는 클라이언트 사이드 웹 보안에서 중요한 요소이다. 하지만, 브라우저가 이러한 SOP에 구애 받지 않고 외부 출처에 대한 접근을 허용해주는 경우가 존재한다.

*예시 : 이미지나 자바스크립트, CSS 등의 리소스를 불러오는 <img>, <style>, <script> 등의 태그는 SOP의 영향을 받지 않는다.

웹 서비스에서 동일 출처 정책인 SOP를 완화하여 다른 출처의 데이터를 처리 해야 하는 경우도 있다.

자원을 공유하기 위해 사용할 수 있는 공유 방법을 교차 출처 리소스 공유(Cross Origin Resource Sharing, CORS)라고 한다. 교차 출처의 자원을 공유하는 방법은 CORS와 관련된 HTTP 헤더를 추가하여 전송하는 방법을 사용한다. 이 외에도 JSON with Padding (JSONP) 방법을 통해 CORS를 대체할 수 있다.


Cross Origin Resource Sharing (CORS)
교차 출처 리소스 공유(CORS)는 HTTP 헤더에 기반하여 Cross Origin 간에 리소스를 공유하는 방법이다.

발신측에서 CORS 헤더를 설정해 요청하면, 수신측에서 헤더를 구분해 정해진 규칙에 맞게 데이터를 가져갈 수 있도록 설정한다.


요청 시 응답 결과에 대한 설명

Header 설명
Access-Control-Allow-Origin 헤더 값에 해당하는 Origin에서 들어오는 요청만 처리한다.
Access-Control-Allow-Methods 헤더 값에 해당하는 메소드의 요청만 처리한다.
Access-Control-Allow-Credentials 쿠키 사용 여부를 판단한다.
Access-Control-Allow-Headers 헤더 값에 해당하는 헤더의 사용 가능 여부를 나타낸다.


브라우저는 수신측의 응답이 발신측의 요청과 상응하는지 확인하고, 그때야 비로소 POST 요청을 보내 수신측의 웹 리소스를 요청하는 HTTP 요청을 보낸다.


JSON with Padding (JSONP)
이미지나 자바스크립트, CSS 등의 리소스는 SOP에 구애 받지 않고 외부 출처에 대해 접근을 허용한다. JSONP 방식은 이러한 특징을 이용해 <script> 태그로 Cross Origin의 데이터를 불러온다.

<script> 태그 내에서는 데이터를 자바스크립트의 코드로 인식하기 때문에 Callback 함수를 활용해야 한다. Cross Origin에 요청할 때 callback 파라미터에 어떤 함수로 받아오는 데이터를 핸들링할지 넘겨주면, 대상 서버는 전달된 callback으로 데이터를 감싸 응답한다.

다만 JSONP는 CORS가 생기기 전에 사용하던 방법으로 현재는 거의 사용하지 않는 추세이다.

 


 

요약

더보기

Same Origin Policy (SOP): 동일 출처 정책, 현재 페이지의 출처가 아닌 다른 출처로부터 온 데이터를 읽지 못하게 하는 브라우저의 보안 메커니즘
Same Origin: 현재 페이지와 동일한 출처
Cross Origin: 현재 페이지와 다른 출처
Cross Origin Resource Sharing (CORS): 교차 출처 리소스 공유, SOP의 제한을 받지 않고 Cross Origin의 데이터를 처리할 수 있도록 해주는 메커니즘