촉촉한초코칩

DreamHack Web Hacking Stage 3 본문

Study/Web Hacking

DreamHack Web Hacking Stage 3

햄친구베이컨 2022. 7. 1. 00:21

Stage 3 - Cookie & Session

Background:Cookie & Session

HTTP 프로토콜로 웹 서버와 통신 > 웹 서버에 명령을 내리기 위해 GET, POST와 같은 메소드와 자원의 위치를 가리키는 URL등이 포함되어 있음 + 헤더(Header)를 통해 웹 서버에게 요청, 웹 서버는 헤더를 읽고 클라이언트에게 결과 값 반환

헤더(쿠키, 세션)에는 클라이언트의 정보와 요청의 내용을 구체화하는 등의 데이터와 클라이언트의 인증 정보가 포함됨

 

쿠키

  • 클라이언트의 IP 주소, User-Agent : 매번 변경될 수 있는 정보
  • HTTP 프로토콜의 Connectionless와 Stateless : 웹 서버는 클라이언트를 기억할 수 없음 > Connectionless, Stateless 특징을 갖는 HTTP에서 상태를 유지하기 위해 쿠키 탄생
HTTP 프로토콜 특징
Connectionless  하나의 요청에 하나의 응답을 한 후 연결을 종료하는 것.
특정 요청에 대한 연결은 이후의 요청과 이어지지 않고 새 요청이 있을 때마다 항상 새로운 연결을 맺는다. 
Stateless  통신이 끝난 후 상태 정보를 저장하지 않는 것.
이전 연결에서 사용한 데이터를 다른 연결에서 요구할 수 없다.

쿠키

  • Key, Value로 이루어진 일종의 단위
  • 서버 > 클라이언트에게 쿠키 발급, 클라이언트는 서버에 요청을 보낼 때마다 쿠키 같이 전송
  • 서버 : 클라이언트의 요청에 포함된 쿠키를 확인해 클라이언트 구분

 

쿠키 용도

1) 클라이언트의 정보 기록

ex) 웹 서버, 클라이언트의 팝업 옵션을 기억하기 위해 쿠키에 해당 정보 기록하고 쿠키를 통해 팝업 창 표시 여부 판단

하지만 쿠키는 서버와 통신할 때마다 전송되기 때문에 쿠키가 필요 없는 요청을 보낼 때 리소스 낭비 발생
> Modern Storage APIs를 통해 데이터 저장 방식 권장 

2) 상태 정보 표현

웹 서버는 수많은 클라이언트의 로그인 상태와 이용자를 구별해야 하므로 클라이언트를 식별할 수 있는 값을 쿠키에 저장해 사용한다. 

 

쿠키가 없는 통신 vs 있는 통신

1) 쿠키가 없는 통신 : 서버는 요청을 보낸 클라이언트가 누군지 알 수 없기 때문에 어떤 클라이언트와 통신하는지도 알 수 없다.

2) 쿠키가 있는 통신 : 클라이언트는 서버에 요청을 보낼 때마다 쿠키를 포함하고, 서버는 해당 쿠키를 통해 클라이언트를 식별한다.

 

쿠키 변조

  • 쿠키 정보를 변조하여 서버에 요청을 보낼 수 있다. 
  • 만약, 서버가 별다른 인증 없이 쿠키를 통해 이용자의 인증 정보를 식별한다면 공격자가 타 이용자를 사칭해 정보를 탈취할 수도 있다.

 

세션 (Session)

  • 쿠키에 인증 상태를 저장하지만 클라이언트가 인증 정보를 변조할 수 없게 하기 위해 세션을 사용한다. 
  • 인증 정보 서버에 저장 > 해당 데이터에 접근할 수 있는 키(유추할 수 없는 랜덤 문자열)를 만들어 클라이언트에게 전달
  • 해당 키 : Session ID
  • 브라우저 : 해당 키를 쿠키에 저장, 이후에 HTTP 요청을 보낼 때 사용
  • 서버 : 요청에 포함된 키에 해당하는 데이터를 가져와 인증 상태 확인

 

쿠키와 세션의 차이점 

  • 쿠키 : 데이터 자체를 이용자가 저장
  • 세션 : 서버가 저장

 

쿠키 적용법

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

 

쿠키는 서버와 클라이언트 둘 다 설정할 수 있다.

1) 서버 - 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;...

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

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

* 크롬 Console 창 활용 - document.cookie를 입력하면 쿠키의 정보를 확인할 수 있다. 

* 크롬 Application 활용 - 좌측의 Cookie를 누르면 Origin 목록을 확인할 수 있다. Origin(해당 URL)을 누르면 설정된 쿠키 정보를 확인/수정할 수 있다. 

 

세션 연습

 

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

 

정리

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

 

Same Origin Plicy (SOP)

  • 쿠키 : 인증상태를 나타내는 민감한 정보 보관, 브라우저 내부에 저장
  • 브라우저 : 인증 정보로 사용될 수 있는 쿠키를 브라우저 내부에 보관, 이용자가 웹 서비스에 접속할 때, 브라우저는 해당 웹 서비스에서 사용하는 인증 정보인 쿠키를 HTTP 요청에 포함시켜 전달
  • + 사이트에 직접 접속할 때 뿐만 아니라 웹 리소스를 통해 간접적으로 타 사이트에 접근할 때도 인증 정보인 쿠키를 함께 전송한다. 
  • 때문에 악의적인 페이지가 클라이언트의 권한을 이용해 대상 사이트에 HTTP 요청을 보내고, HTTP 응답 정보를 획득하는 코드를 실행할 수도 있다.

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

 

Same Origin Plicy의 오리진 (Origin) 구분 방법

  • 오리진 구성 요소 : 프로토콜(Protocol, Scheme), 포트(Port), 호스트(Host)
  • 구성요소가 모두 일치해야 동일한 오리진이다.

ex) https://same-origin.com/ 과 비교

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

-> SOP는 Same Origin일 때만 정보를 읽을 수 있도록 한다. 

* javascript를 이용해 SOP를 테스트 하는 코드

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

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

 

Cross Origin 데이터 읽고 쓰기

  • 외부 출처에서 읽어온 데이터를 읽으려고 할 때는 오류가 발생해 읽지 못한다.
  • 하지만 읽는 것 외에 데이터를 쓰는 것은 문제 없이 동작한다. 
crossNewWindow = window.open('https://theori.io');
crossNewWindow.location.href = "https://dreamhack.io";

 

Same Origin Policy 데모

- 코드

<!-- iframe 객체 생성 -->
<iframe src="" id="my-frame"></iframe>
<!-- Javascript 시작 -->
<script>
/* 2번째 줄의 iframe 객체를 myFrame 변수에 가져옵니다. */
let myFrame = document.getElementById('my-frame')
/* iframe 객체에 주소가 로드되는 경우 아래와 같은 코드를 실행합니다. */
myFrame.onload = () => {
    /* try ... catch 는 에러를 처리하는 로직 입니다. */
    try {
        /* 로드가 완료되면, secret-element 객체의 내용을 콘솔에 출력합니다. */
        let secretValue = myFrame.contentWindow.document.getElementById('secret-element').innerText;
        console.log({ secretValue });
    } catch(error) {
        /* 오류 발생시 콘솔에 오류 로그를 출력합니다. */
        console.log({ error });
    }
}
/* iframe객체에 Same Origin, Cross Origin 주소를 로드하는 함수 입니다. */
const loadSameOrigin = () => { myFrame.src = 'https://same-origin.com/frame.html'; }
const loadCrossOrigin = () => { myFrame.src = 'https://cross-origin.com/frame.html'; }
</script>
<!--
버튼 2개 생성 (Same Origin 버튼, Cross Origin 버튼)
-->
<button onclick=loadSameOrigin()>Same Origin</button><br>
<button onclick=loadCrossOrigin()>Cross Origin</button>
<!--
frame.html의 코드가 아래와 같습니다.
secret-element라는 id를 가진 div 객체 안에 treasure라고 하는 비밀 값을 넣어두었습니다.
-->
<div id="secret-element">treasure</div>

-  코드 동작 설명

  1. 두번째 줄의 iframe : 현재 웹 페이지 안에 또 다른 하나의 웹 페이지를 삽입하는 HTML 태그. src 요소를 설정함으로써 삽입할 웹 페이지의 주소가 결정된다. 
  2. 10번째 줄의 onload : 이벤트 핸들러로써, 해당 객체가 성공적으로 로드되었을 때 동작한다. 10~23번 줄이 iframe 객체에 페이지가 로드되면 동작하는 코드이다.
  3. 14~15번째 줄 : 로드가 완료되면 iframe 내에 삽입된 주소에서 secret-element 객체의 값인 treasure를 읽어와 콘솔에 출력한다. 

 

Cross Origin Resource Sharing (CORS) - Same Origin Policy 제한 완화

브라우저가 SOP에 구애받지 않고 외부 출처에 대한 접근을 허용해주는 경우 존재
ex) 이미지, JS, CSS 등의 리소스를 불러오는 <img>, <style>, <script>등의 태그는 SOP의 영향을 받지 않는다.

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

ex) 특정 포털 사이트의 카페, 블로그, 메일 서비스의 Host가 다를 때, 브라우저는 각 사이트의 오리진이 다르다고 인식한다. > 이용자가 메일을 메인 페이지에 출력하려면 개발자는 메인 페이지에서 메일 서비스 관련된 리소스를 요청해야 한다. 이때, 두 사이트는 오리진이 다르므로 SOP를 적용받지 않고 리소스를 공유할 방법이 필요하다. 

 

교차 출처 리소스 공유(Cross Origin Resource Sharing, CORS) : 자원을 공유하기 위해 사용할 수 있는 공유 방법

  1. CORS와 관련된 HTTP 헤더를 추가하여 전송
  2. 이 외에도 JSON with Padding (JSONP) 방법을 통해 CORS 대체 가능

 

1) Cross Origin Resource Sharing (CORS)

  • HTTP 헤더에 기반하여 Cross Origin 간에 리소스를 공유하는 방법
  • 발신측 : CORS 헤더 설정해서 요청 > 수신측 : 헤더를 구분해 정해진 규칙에 맞게 데이터를 가져갈 수 있도록 설정

* Access-Control-Request : 해당하는 헤더 뒤에 따라오는 Method와 Headers는 각각 메소드와 헤더를 추가적으로 사용할 수 있는지 질의한다. 

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

발신측에서 POST 방식으로 HTTP 요청 -> Options 메소드를 가진 HTTP 요청이 전달됨 

: CORS preflight (수신측에서 웹 리소스를 요청해도 되는지 질의하는 과정)

> 브라우저는 수신측의 응답이 발신측의 요청과 상응하는지 확인한 뒤에 POST 요청을 보내 수신측의 웹 리소스를 요청하는 HTTP 요청을 보낸다. 

 

2) JSON with Padding (JSONP)

  • 이미지, JS, CSS 등의 리소스는 SOP에 구애받지 않고 외부 출처에 대해 접근을 허용한다. 
  • JSONP 방식은 이러한 특징을 이용해 <script> 태그로 Cross Origin 데이터를 불러온다. 
  • 하지만 <script> 태그에서는 데이터를 자바스크립트 코드로 인식하기 때문에 Callback 함수를 활용해야 한다.
  • Cross Origin에 요청할 때 callback 파라미터에 어떤 함수로 받아오는 데이터를 핸들링할지 넘겨주면 대상 서버는 전달된 callback으로 데이터를 감싸 응답한다.

  • 13번째 줄 : Cross Origin 데이터 불러오기. 
  • callback 파라미터로 myCallback 전달 > Cross Origin에서는 응답할 데이터를 myCallback 함수의 인자로 전달될 수 있도록 myCallback으로 감싸 JS 코드를 반환해준다.
  • 반환된 코드는 요청측에서 실행됨. > 3-6번 줄에서 정의된 myCallback 함수가 전달된 데이터를 읽을 수 있다.

* 하지만 JSONP는 CORS가 생기기 전에 사용하던 방법으로 CORS를 사용하는 것이 좋다.

 

정리

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

'Study > Web Hacking' 카테고리의 다른 글

Dreamhack - xss-1  (0) 2022.07.05
DreamHack Web Hacking Stage 4  (0) 2022.07.05
Dreamhack - session-basic  (0) 2022.07.01
Dreamhack - Cookie  (0) 2022.07.01
DreamHack Web Hacking Stage 1, 2  (0) 2022.03.22