View
해당 게시물은 DreamHack Web Hacking 강의를 토대로 작성하였습니다.
쿠키, Cookie
- Connectionless, Stateless 특성 갖는 HTTP에서 상태 유지를 위한 것
- Key와 Value로 이뤄진 일종의 단위
- 서버가 클라이언트에게 쿠키 발급하면 클라이언트는 서버에 요청 보낼 때마다 쿠키 같이 전송, 서버는 클라이언트 요청에 포함된 쿠키 확인해 클라이언트 구분할 수 있다.
Connectinless
→ 하나의 요청에 하나의 응답을 한 후 연결을 종료하는 것을 의미
→ 특정 요청에 대한 연결은 이후의 요청과 이어지지 않고 새 요청이 있을 때 마다 새로운 연결 맺음
Stateless
→ 통신이 끝난 후 상태 정보를 저장하지 않는 것을 의미
→ 이전 연결에서 사용한 데이터를 다른 연결에서 요구할 수 없음
쿠키의 용도
- 정보 기록
- 웹 서버는 각 클라이언트의 팝업 옵션 ("다시 보지 않기", 7일 간 표시하지 않기" 등)을 기억하기 위해 쿠키에 해당 정보를 기록, 쿠키를 통해 팝업 창 표시 여부를 판단
- 과거에는 클라이언트 정보 저장하기 위해 쿠키 종종 사용, 쿠키는 서버와 통신할 때마다 전송되기 때문에 쿠키가 필요없는 요청을 보낼 때 리소스 낭비가 발생할 수 있다 → 이러한 단점 보완 위해 Modern Storage APIs 통해 데이터 저장하는 방식 권장하고 있음
- 상태 정보 표현
- 웹 서버에서는 수많은 클라이언트의 로그인 상태와 이용자 구별해야 함, 이때 클라이언트를 식별할 수 있는 값을 쿠키에 저장해 사용
쿠키 있는 통신
- 클라이언트는 서버에 요청 보낼 때마다 쿠키 포함하고 서버는 해당 쿠키를 통해 클라이언트를 식별
- 위 그림처럼 "이름=드림이" 라는 쿠키를 통해 서버는 클라이언트가 "드림이" 라는 것을 식별한다.
쿠키 변조
- 쿠키는 클라이언트의 브라우저에 저장되고 요청에 포함되는 정보이다.
- 악의적인 클라이언트는 쿠키 정보를 변조해 서버에 요청을 보낼 수 있다. (클라이언트가 서버에 요청 보낼 때 쿠키를 요청 헤더에 넣어 전송하기 때문에 이용자가 요청 보낼 때 쿠키 헤더 변조 가능)
- 때문에 서버가 별 다른 검증 없이 쿠키를 통해 이용자 인증 정보를 식별한다면 공격자가 타 이용자를 사칭해 정보 탈취 할 수 있다.
쿠키 설정
- 쿠키는 클라이언트에 저장되기 때문에 저장된 쿠키를 조회, 수정, 추가가 가능하다.
- 쿠키 설정 시 만료 시간 지정 가능, 만료 시간 이후에는 클라이언트에서 쿠키 삭제된다. (쿠키 만료는 클라이언트(브라우저)에서 관리)
- 서버에서 설정 : HTTP 응답 중 헤더에 쿠키 설정 헤더 (Set-Cookie) 추가하면 클라이언트의 브라우저가 쿠키 설정
- 클라이언트 : 자바스크립트 사용 쿠키 설정
클라이언트에서 쿠키 활용
크롬 Console
- console 탭에서 document.cookie 입력하면 쿠키 정보 확인 가능
- 쿠키 옵션(HttpOnly)에 따라 자바스크립트에서 쿠키 확인 불가능 할 수 있다.
크롬 Application
- Application 탭에서 Cookies 펼치면 목록 확인 가능하고 설정된 쿠키 정보 확인 및 수정 가능
세션, Session
- 쿠키에 인증 상태를 저장하지만 클라이언트가 인증 정보를 변조할 수 없게 하기 위해 세션 사용
- 인증 정보를 서버에 저장, 해당 데이터에 접근할 수있는 키(랜덤 문자열) 만들어 클라이언트에 전달하는 방식으로 작동 (Key = Session ID)
- 브라우저는 해당 키를 쿠키에 저장하고 이후 HTTP 요청 보낼 때 사용, 서버는 요청에 포함된 키에 해당하는 데이터 가져와 인증 상태를 확인
세션, Session 예시
- 로그인 시 개발자도구 Network 탭에서 로그인 성공 응답 보면 set-cookie 헤더 통해 브라우저의 쿠키에 세션 정보 저장
- Cookies 목록 보면 set-cookie 통해 설정된 쿠키 확인 가능
- sessionid 값을 복사 한 후 삭제하고 쿠키 빈 칸에 session 헤더 추가 후 값 입력하면 로그인 가능
※ 공격자가 이용자 쿠키 훔칠 수 있으면 세션에 해당하는 이용자의 인증 상태를 훔칠 수 있다. 이를 세션 하이재킹(Session Hijacking) 이라고 한다.
※ 쿠키는 데이터 자체를 이용자가 저장, 세션은 서버가 저장
SOP, Same Origin Policy (동일 출처 정책)
- 브라우저는 인증 정보로 사용될 수 있는 쿠키를 브라우저 내부에 보관, 이용자가 웹 서비스 접속 시 브라우저는 해당 웹 서비스에서 사용하는 인증 정보인 쿠키를 HTTP 요청에 포함시켜 전달한다.
- 브라우저는 웹 리소스를 통해 간접적으로 타 사이트에 접근할 때도 인증 정보인 쿠키를 함께 전송하는 특징을 가지고 있다.
- 이러한 특징 때문에 악의적인 페이지가 클라이언트의 권한을 이용해 대상 사이트에 HTTP 요청 보내고 HTTP 응답 정보 획득하는 코드를 실행할 수 있다. (정보 유출과 같은 보안 위협 생길 수 있는 요소)
- ex) SOP이 없을 때 사용자가 악의적 Script가 포함된 페이지 접속 시 Script 실행되면 사용자 모르는 사이 대상 사이트에 임의 요청 보내고 응답 값을 해커 서버로 보내서 개인정보 탈취
- 클라이언트 입장에서는 가져온 데이터를 악의적인 페이지에서 읽을 수 없도록 해야함 (브라우저 보안 메커니즘 SOP 등장 배경)
SOP의 Origin (오리진) 구분 방법
- Origin은 프로토콜 (Protocol, Scheme), 포트 (Port), 호스트 (Host)로 구성
- 구성 요소가 모두 일치해야 동일한 Origin
- SOP는 동일 Origin일 때만 정보 읽을 수 있게 해준다. (http://same-origin.com 로 서버에 요청 보내면 서버는 http://same-origin.com로만 응답 보낼 수 있음)
- Same Origin: 현재 페이지와 동일한 출처, Cross Origin: 현재 페이지와 다른 출처
- 개발자 도구 콘솔 창에 location.origin 입력하면 현재 출처 확인 가능
SOP 실습
- http://dreamhack.io 에서 실습 진행
- window.open - 새로운 창 띄우는 함수, object.location.href - 객체(object)가 가리키고 있는 URL 주소 읽어오는 코드
- same origin일 때는 결과 출력 (URL 주소)
- cross origin일 때는 오류 출력 (현재 페이지(dreamhack.io) 와 다른 출처)
- 외부 출처에서 불러온 데이터 읽으려고 할 때는 오류 발생
- 읽는 것 외 데이터 쓰는 것은 문제 없이 동작 (crossNewWindow.location.href = ~~~)
SOP 제한 완화
- SOP는 클라이언트 사이드 웹 보안에서 중요한 요소, 하지만 브라우저가 SOP에 구애 받지 않고 외부 출처에 대한 접근 허용해주는 경우 존재 (이미지, 자바스크립트, CSS 등의 리소스 불러오는 <img>, <style>, <script> 등 태그는 SOP 영향 받지 않음)
- 위 경우 외에도 웹 서비스에서 SOP 완화하여 다른 출처 데이터 처리해야 하는 경우 있다. (특정 포털 사이트가 카페, 블로그, 메일 서비스를 Host 다르게 운영 시 브라우저는 각 사이트 오리진 다르다고 인식)
- ex) 메인: https://dreamhack.io, 카페: https://cafe.dreamhack.io, 블로그: http://blog.dreamhack.io
- 위와 같은 환경에서 메인 페이지가 메일 서비스에 관련 리소스(메일 개수를 메인 페이지에 출력 등) 요청 하려면 SOP 적용받지 않고 리소스 공유할 방법이 필요
- 이런 상황에서 자원 공유하기 위해 사용할 수 있는 방법을 Cross Origin Resource Sharing, 교차 출처 리소스 공유 라고 한다. (CORS와 관련된 HTTP 헤더 추가하여 전송하는 방법 사용하여 자원 공유)
- 이 외에도 JSON with Padding 방법 통해 CORS 대체 가능
CORS, Cross Origin Resource Sharing (교차 출처 리소스 공유)
- CORS는 HTTP 헤더에 기반하여 Cross Origin 간 리소스를 공유하는 방법
- 발신측에서 CORS 헤더 설정해 요청하면 수신측에서 헤더 구분해 정해진 규칙에 맞게 데이터 가져갈 수 있도록 설정
- 크게 Preflight Request, Simple Request, Credentialed Request 3가지로 구분
Preflight Request
- OPTIONS 메소드로 HTTP 요청 미리 보내 실제 요청이 전송하기에 안전한지 확인 (다른 출처 요청이 유저 데이터에 영향 줄 수 있기 때문에 미리 전송한다는 의미)
ex)
발신측에서 POST 방식으로 HTTP 요청을 보냄
OPTIONS 메소드를 가진 HTTP 요청이 전달 (수신측에 웹 리소스 요청해도 되는지 질의하는 과정)
OPTIONS 사용해
요청 헤더
origin | 어디서 요청했는지 서버에 알려주는 주소 |
access-control-request-method | 실제 요청이 보낼 HTTP 메소드 |
access-control-request-headers | 실제 요청에 포함된 header |
위 요청에 대한 응답
응답 헤더
access-control-allow-origin | 서버거 허용하는 출처, 해당 값에서 들어오는 요청만 처리 |
access-control-allow-methods | 서버가 허용하는 HTTP 메소드 리스트 (해당 메소드 요청만 처리) |
access-control-allow-headers | 서버가 허용하는 header 리스트 |
access-control-allow-credentials | 쿠키 사용 여부 판단 |
위 과정 후 브라우저는 수신측 응답이 발신측 요청과 상응하는지 확인하고 이후 POST 요청 보내 수신측 웹 리소스를 요청하는 HTTP 요청(실제 요청) 보냄 (과정: Preflight Request - Preflight Response - Request - Response)
Simple Request, 단순 요청
- Preflight 없이 요청 보냄, 아래와 같은 조건 만족해야한다.
- GET, HEAD, POST 요청만 가능
- Accept, Accept-Language, Content-Language, Content-Type과 같은 CORS 안전 리스트 헤더 또는 User-Agent 헤더
- Content-Type 헤더는 application/x-www-form-urlencoded, multipart/form-data and text/plain만 가능
- ReadableStream 객체 사용되지 않음
- XMLHttpRequest 객체를 사용하여 요청하면 요청에서 사용된 XMLHttpRequest.upload에 의해 반환되는 객체에 어떠한 이벤트 리스너도 등록되지 않음
ex) origin에 주소 담어서 요청 보내면 서버는 요청 확인하고 다른 출처 주소(origin)에 접근 가능하다는 access-control-allow-origin에 해당 주소 담아서 결과 리턴
Credentialed Request, 신용 요청
- 쿠키, 인증 헤더, TLS 클라이언트 인증서 등의 신용정보를 함께 요청
- 기본적으로 CORS 정책은 다른 출처 요청에 인증정보 포함을 허용하지 않는다.
- 요청에 인증 포함하는 플래그 있거나 access-control-allow-credentials가 true로 설정한다면 요청 가능
JSON with Padding (JSONP)
- JSONP 방식은 이미지나 자바스크립트, CSS 등의 리소스는 SOP에 구애 받지 않고 외부 출처에 대해 접근 허용한다는 특징 이용해 <script> 태그로 Cross Origin 데이터 불러온다.
- <script> 태그 내에서는 데이터를 자바스크립트의 코드로 인식하기 때문에 Callback 함수 활용해야함
- Cross Origin에 요청할 때 callback 파라미터에 어떤 함수로 받아오는 데이터를 핸들링할지 넘겨주면 대상 서버는 전달된 callback으로 데이터 감싸 응답함
- CORS 생기기 전 사용하던 방법으로 현재는 거의 사용 안함
'Security > DreamHack 강의' 카테고리의 다른 글
[Web Hacking] Background - Web (0) | 2023.09.02 |
---|