kaki1013
[STAGE 3] Cookie & Session - Same Origin Policy 본문
# Mitigation: Same Origin Policy
0. 서론
쿠키 : 인증 상태를 나타내는 민감한 정보를 보관 &브라우저 내부에 저장
→ 브라우저가 웹 서비스에 접속할 때 : 브라우저는 자동으로 쿠키를 헤더에 포함시켜 요청을 보냄
→ 포털 사이트, SNS와 같은 웹 서비스에 한 번 로그인한 후 일정 기간은 로그인하지 않고도 바로 서비스를 사용 가능
이용자가 악의적인 페이지를 접속했을 때, 페이지가 자바스크립트를 사용해 이용자의 SNS 웹 서비스로 요청을 보낸다면?
→ 브라우저는 요청을 보낼 때 헤더에 해당 웹 서비스 쿠키를 포함시킴
→ 자바스크립트로 요청을 보낸 페이지는 로그인 된 이용자의 SNS 응답을 받음
→ 마음대로 페이지 접속자의 SNS에 글을 올리거나, 삭제하고, SNS 메신저를 읽는 것도 가능
→ 이와 같은 문제를 방지하기 위해 동일 출처 정책, Same Origin Policy (SOP) 보안 메커니즘이 탄생
→ SOP : 클라이언트 사이드 웹 보안에 있어 중요한 요소
→ 실제로 클라이언트 사이드 공격 : 이 SOP를 우회하기 위한 것(이라고 해도 과언이 아님)
1. Same Origin Policy (SOP)
(1) SOP
브라우저 : 인증 정보로 사용될 수 있는 쿠키를 브라우저 내부에 보관
& 이용자가 웹 서비스에 접속할 때 : 해당 웹 서비스에서 사용하는 인증 정보인 쿠키를 HTTP 요청에 포함시켜 전달
→ 이와 같은 특징은 사이트에 직접 접속하는 것에만 한정 X
→ 브라우저는 웹 리소스를 통해 간접적으로 타 사이트에 접근할 때도 인증 정보인 쿠키를 함께 전송하는 특징을 가짐
이 특징 때문에 악의적인 페이지가 클라이언트의 권한을 이용해
대상 사이트에 HTTP 요청을 보내고, HTTP 응답 정보를 획득 하는 코드를 실행할 수 있음
→ 이는 정보 유출과 같은 보안 위협이 생길 수 있는 요소
→ 클라이언트 입장에서는 가져온 데이터를 악의적인 페이지에서 읽을 수 없도록 해야 함
→ 이것이 바로 브라우저의 보안 메커니즘인 동일 출처 정책 (Same Origin Policy, SOP)
(2) Same Origin Policy의 오리진 (Origin) 구분 방법
브라우저가 가져온 정보의 출처인 오리진 (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가 다름 |
(3) SOP 실습
SOP : Cross Origin이 아닌 Same Origin일 때만 정보를 읽을 수 있도록 해줌
예시 코드) https://dreamhack.io 에서 javascript를 이용해 SOP를 테스트
cf) window.open = 새로운 창을 띄우는 함수, object.location.href = 객체가 가리키고 있는 URL 주소를 읽어오는 코드
Same Origin
sameNewWindow = window.open('https://dreamhack.io/lecture');
console.log(sameNewWindow.location.href);
// 결과: https://dreamhack.io/lecture
Cross Origin
crossNewWindow = window.open('https://theori.io');
console.log(crossNewWindow.location.href);
// 결과: Origin 오류 발생
Cross Origin 데이터 읽기/쓰기
: 위와 같이 외부 출처에서 불러온 데이터를 읽으려고 할 때는 오류가 발생해 읽지 못함
But 읽는 것 외에 데이터를 쓰는 것은 문제 없이 동작
→ 아래와 같은 코드는 오류 발생 X
crossNewWindow = window.open('https://theori.io');
crossNewWindow.location.href = "https://dreamhack.io";
2. Cross Origin Resource Sharing (CORS)
(1) Same Origin Policy 제한 완화
SOP : 클라이언트 사이드 웹 보안에서 중요한 요소
But 브라우저가 이러한 SOP에 구애 받지 않고 외부 출처에 대한 접근을 허용해주는 경우가 존재함
→ 이미지나 자바스크립트, CSS 등의 리소스를 불러오는 <img>, <style>, <script> 등의 태그는 SOP의 영향을 받지 않음
이외에도 웹 서비스에서 동일 출처 정책인 SOP를 완화하여 다른 출처의 데이터를 처리 해야 하는 경우도 있음
→ 예를 들어 특정 포털 사이트가 카페, 블로그, 메일 서비스를 아래의 주소로 운영하고 있다면..
→ 각 서비스의 Host가 다르기 때문에 브라우저는 각 사이트의 오리진이 다르다고 인식
- 카페: https://cafe.dreamhack.io
- 블로그: https://blog.dreamhack.io
- 메일: https://mail.dreamhack.io
- 메인: https://dreamhack.io
→ 이용자가 수신한 메일의 개수를 메인 페이지에 출력하려면?
개발자는 메인 페이지에서 메일 서비스에 관련된 리소스를 요청하도록 해야함
→ 두 사이트는 오리진이 다르므로 SOP를 적용받지 않고 리소스를 공유할 방법이 필요
교차 출처 리소스 공유 (Cross Origin Resource Sharing, CORS) : 자원을 공유하기 위해 사용할 수 있는 공유 방법
→ 교차 출처의 자원을 공유하는 방법 : CORS와 관련된 HTTP 헤더를 추가하여 전송하는 방법을 사용함
→ 이 외에도 JSON with Padding (JSONP) 방법을 통해 CORS를 대체 가능
(2) 교차 출처 리소스 공유 (Cross Origin Resource Sharing, CORS)
: HTTP 헤더에 기반하여 Cross Origin 간에 리소스를 공유하는 방법
발신측에서 CORS 헤더를 설정해 요청 → 수신측에서 헤더를 구분해 정해진 규칙에 맞게 데이터를 가져갈 수 있도록 설정
예시 코드) 웹 리소스를 요청하는 발신측 코드의 일부
/*
XMLHttpRequest 객체를 생성합니다.
XMLHttpRequest는 웹 브라우저와 웹 서버 간에 데이터 전송을
도와주는 객체 입니다. 이를 통해 HTTP 요청을 보낼 수 있습니다.
*/
xhr = new XMLHttpRequest();
/* https://theori.io/whoami 페이지에 POST 요청을 보내도록 합니다. */
xhr.open('POST', 'https://theori.io/whoami');
/* HTTP 요청을 보낼 때, 쿠키 정보도 함께 사용하도록 해줍니다. */
xhr.withCredentials = true;
/* HTTP Body를 JSON 형태로 보낼 것이라고 수신측에 알려줍니다. */
xhr.setRequestHeader('Content-Type', 'application/json');
/* xhr 객체를 통해 HTTP 요청을 실행합니다. */
xhr.send("{'data':'WhoAmI'}");
* 발신측의 HTTP 요청
OPTIONS /whoami HTTP/1.1
Host: theori.io
Connection: keep-alive
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: https://dreamhack.io
Accept: */*
Referer: https://dreamhack.io/
→ 발신측에서 POST 방식으로 HTTP 요청을 보냈으나, OPTIONS 메소드를 가진 HTTP 요청이 전달됨
→ 이를 CORS preflight라고 함 & 수신측에 웹 리소스를 요청해도 되는지 질의하는 과정
위의 요청에서, "Access-Control-Request"로 시작하는 헤더가 존재
→ 해당하는 헤더 뒤에 따라오는 Method와 Headers는 각각 메소드와 헤더를 추가적으로 사용할 수 있는지 질의함
* 서버의 응답
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://dreamhack.io
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type
* 응답 결과에 대한 설명
Header | 설명 |
Access-Control-Allow-Origin | 헤더 값에 해당하는 Origin에서 들어오는 요청만 처리 |
Access-Control-Allow-Methods | 헤더 값에 해당하는 메소드의 요청만 처리 |
Access-Control-Allow-Credentials | 쿠키 사용 여부를 판단 (예시의 경우 쿠키의 사용을 허용) |
Access-Control-Allow-Headers | 헤더 값에 해당하는 헤더의 사용 가능 여부를 나타냄 |
위 과정을 마치면..
→ 브라우저는 수신측의 응답이 발신측의 요청과 상응하는지 확인
→ 그때야 비로소 POST 요청을 보내 수신측의 웹 리소스를 요청하는 HTTP 요청을 보냄
(3) JSONP
위에서 말했듯이 이미지나 자바스크립트, CSS 등의 리소스는 SOP에 구애 받지 않고 외부 출처에 대해 접근을 허용
→ JSONP 방식은 이러한 특징을 이용해 <script> 태그로 Cross Origin의 데이터를 불러옴
→ But <script> 태그 내에서는 데이터를 자바스크립트의 코드로 인식하기 때문에 Callback 함수를 활용해야 함
→ Cross Origin에 요청할 때 callback 파라미터에 어떤 함수로 받아오는 데이터를 핸들링할지 넘겨주면,
대상 서버는 전달된 Callback으로 데이터를 감싸 응답함
예시 코드) 웹 리소스 요청 코드
<script>
/* myCallback이라는 콜백 함수를 지정 */
function myCallback(data){
/* 전달받은 인자에서 id를 콘솔에 출력*/
console.log(data.id)
}
</script>
<!--
https://theori.io의 스크립트를 로드하는 HTML 코드
단, callback이라는 이름의 파라미터를 myCallback으로 지정함으로써
수신측에게 myCallback 함수를 사용해 수신받겠다고 알림
-->
<script src='http://theori.io/whoami?callback=myCallback'></script>
마지막 줄에서 Cross Origin의 데이터를 불러옴 & 이 때 callback 파라미터로 myCallback을 함께 전달함
→ Cross Origin에서는 응답할 데이터를 myCallback 함수의 인자로 전달될 수 있도록
myCallback으로 감싸 Javascript 코드를 반환해줌
→ 반환된 코드는 요청측에서 실행되기 때문에 3~6번 줄에서 정의된 myCallback 함수가 전달된 데이터를 읽을 수 있음
다만 JSONP는 CORS가 생기기 전에 사용하던 방법 → 현재는 거의 사용하지 않는 추세
→ 새롭게 코드를 작성할 때에는 CORS를 사용해야 함
* 웹 리소스 요청에 따른 응답 코드
/*
수신측은 myCallback 이라는 함수를 통해 요청측에 데이터를 전달합니다.
전달할 데이터는 현재 theori.io에서 클라이언트가 사용 중인 계정 정보인
{'id': 'dreamhack'} 입니다.
*/
myCallback({'id':'dreamhack'});
참고 : https://ko.wikipedia.org/wiki/JSONP
JSONP - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. JSONP 로고 JSONP(JSON with Padding 또는 JSON-P[1])는 클라이언트가 아닌, 각기 다른 도메인에 상주하는 서버로부터 데이터를 요청하기 위해 사용된다. 2005년에 Bob Ippolito
ko.wikipedia.org
'버그바운티 스터디 > Web Hacking' 카테고리의 다른 글
[STAGE 5] Cross Site Request Forgery (CSRF) (0) | 2023.08.02 |
---|---|
[STAGE 4] Cross-Site-Scripting (XSS) (0) | 2023.07.31 |
[STAGE 3] Cookie & Session - Cookie & Session (0) | 2023.07.31 |
[STAGE 2] Background(Web) - 웹 브라우저 - Browser DevTools (0) | 2023.07.30 |
[STAGE 2] Background(Web) - 웹 브라우저 - Web Browser (0) | 2023.07.30 |