Client-side Basic

<world />·2021년 5월 20일
0

공부

목록 보기
14/17
post-thumbnail

정보 출처: https://dreamhack.io/

Client-side Basic

- Introduction


이 강의는 Client-side(클라이언트 사이드) 취약점의 대표적인 공격 방법과 방어법을 다룬다.
Introduction of Webhacking 강의에서는 HTTP는 Connectionless와 Stateless한 특성을 가지고 있기 때문에 웹 서버가 사용자를 식별하기 위해 보편적으로 쿠키와 세션을 사용한다고 했다. 공격자는 사용자로부터 본인을 식별하기 위한 사용자 정보, 즉 쿠키나 세션에 저장된 세션 아이디를 탈취해 사용자 권한을 얻거나, 사용자의 브라우저에서 자바스크립트를 실행하는 등의 특별한 행위를 수행해 사용자가 요청을 보낸 것처럼 하는 것이 클라이언트 사이드 취약점의 주목적이다.

위와 같은 클라이언트 사이드 취약점이 발생할 수 있는 이유는 웹 브라우저는 Stateful한 상태를 유지하기 위해 모든 HTTP 요청에 쿠키를 함께 보낸다. 아래는 웹 브라우저가 리소스를 요청할 때 보내는 HTTP 패킷이다.

GET /resource1 HTTP/1.1
Host: dreamhack.io
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Referer: http://dreamhack.io/sandbox
Accept-Encoding: gzip, deflate
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: cookie=choco_poco; user_id=admin
GET /resource1 HTTP/1.1
Host: dreamhack.io
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Referer: http://theori.io
Accept-Encoding: gzip, deflate
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: cookie=choco_poco; user_id=admin

서로 다른 사이트인 dreamhack.iotheori.io에서 dreamhack.io/resource1에 요청을 보내지만, 동일한 쿠기(cookie=choco_poco; user_id=admin)가 함께 전송되는 것을 확인할 수 있다.

웹 브라우저는 HTTP 요청을 생성할 때 시작 주소(Referer)와 상관없이 대상 호스트(Host, A사이트/B사이트..)가 발급한 쿠키를 삽입한다.






Client-side Basic

- Same Origin Policy(1)


- Same Origin Policy(SOP)

"Introduction of Webhacking" 강의에서 자바스크립트를 이용해 페이지 내에 있는 요소들을 관리할 수 있다고 배웠다. 또한 웹 브라우저를 통해 대상 호스트에 요청 시 사용자의 정보를 담고 있는 쿠키도 함께 전송되기 때문에 외부 리소스를 불러오는 엘리먼트(iframe, img, video)를 자바스크립트로 관리할 수 있다면 사용자의 동의 없이 해당 내용을 읽거나 변조할 수 있다. 예를 들면 dreamhack.io에서 자바스크립트 또는 HTML 태그들을 이용하여 페이스북의 메시지를 보거나, 지메일의 내용을 보는 행위 등을 웹 브라우저 내 사용자의 권한으로 사용할 수 있게 된다.

웹 브라우저가 위와 같은 공격으로부터 사용자를 보호하기 위해 Same Origin Policy(SOP) 정책을 만들었다. 이 정책은 서로 다른 오리진의 문서 또는 스크립트 들의 상호 작용을 제한한다.

가장 먼저 오리진은 프로토콜(protocol, scheme), 포트(port)호스트(host)로 구성 된다. 구성 요소가 모두 일치해야 동일한 오리진이라 할 수 있다.

https://same-origin.com/과 비교했을 때 결과는 아래 표와 같다


동일한 오리진이 아닌 경우 웹 브라우저가 사용자를 보호하기 위해 문서 또는 스크립트의 내용을 읽지 못하게 하는 것이 SOP의 대표적인 예시이다.

xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.facebook.com/');
xhr.onreadystatechange = function(e){ console.log(e.target.response); };
xhr.send();

위 코드를 https://dreamhack.io/에서 실행하게 되면 아래 그림 처럼 에러가 발생하는 것을 확인 할 수 있다.


아래에서는 현재 오리진이 https://same-origin.com/인 경우 same origin인 경우와 cross origin인 경우를 주소를 바꾸어 보며 확인해 볼 수 있다.




- Same Origin Policy (SOP)

<iframe src="" id="my-frame"></iframe>
<script>
let myFrame = document.getElementById('my-frame')
myFrame.onload = () => {
    try {
        let secretValue = myFrame.contentWindow.document.getElementById('secret-element').innerText;
        console.log({ secretValue });
    } catch(error) {
        console.log({ err![](https://velog.velcdn.com/images%2Fnew__world%2Fpost%2Ff2d494e0-05ee-429b-b13e-bdf7b4386f84%2Fimage.png)or });
    }
}
const fn1 = () => { myFrame.src = 'https://same-origin.com/frame.html'; }
const fn2 = () => { myFrame.src = 'https://cross-origin.com/frame.html'; }
</script>
<button onclick=fn1()>same origin</button><br>
<button onclick=fn2()>cross origin</button>
<!-- frame.html -->
<div id="secret-element">treasure</div>

위 코드는 SOP가 어떻게 보호하는지를 나타낸 예제이다.

13번 라인은 same origin 페이지를 불러오는 코드이다.
성공적으로 iframe에 로드 되면 onload핸들러가 해당 iframesecret-element의 값을 가져온다. 14번 라인에서 같은 행위를 하지만 same origin이 아닌 https://cross-origin.com의 페이지를 불러온다. 따라서 same origin 버튼을 누르게 되면 콘솔창에 treasure가 정상적으로 출력되고 cross origin 버튼을 누르면 익셉션을 출력한다.




- Cross Origin Resource Sharing(CORS)

일반적으로는 SOP 영향으로 서로 다른 오리진과 리소스를 공유하지 못한다. 하지만 개발 또는 운영의 목적으로 다른 오리진들과 리소스를 공유해야하는 상황이 있을 수 있다. 때문에 SOP가 적용된 상태에서도 리소스를 공유하는 방법이 존재한다.

  • postMessage: 메시지를 주고받기 위한 이벤트 핸들러를 이용해 리소스를 공유한다.
  • JSONP: 스크립트 태그를 통해 외부 자바스크립트 코드를 호출하면 현재 오리진에서 해당 코드가 실행된다는 점을 이용한 방법이다. 스크립트 태그를 통해 다른 오리진의 리소스를 요청하고, 응답 데이터를 현재 오리진의 Callback 함수에서 다루는 방식으로 리소스를 공유한다.
  • Cross Origin Resource Sharing(CORS)헤더 사용: 다른 오리진이 허용하는 설정 등을 HTTP 헤더를 통해 확인한 후 허용하는 요청을 보내 리소스를 공유하는 방식이다.

아래 에서는 각각의 방법을 통해 서로 다른 오리진인 https://dreamhack.io에서 http://test.dreamhack.io로 리소스를 공유하는 방식을 간단하게 구현한 예시이다.

> postMessage


> JSONP


> CORS헤더 사용


CORS 헤더 사용, postMessage, JSONP의 자세한 원리와 잘못된 설정으로 발생하는 취약점 케이스는 "Client-side Advanced" 강의에서 심도있게 다루겠다.

웹을 사용하는 사용자를 대상으로 공격을 하는 클라이언트 사이드 취약점은 본인을 식별하기 위한 사용자 정보, 즉 쿠키에 저장된 세션 아이디를 탈취해 사용자 권한을 얻거나 사용자의 브라우저에서 자바스크립트를 실행하여 사용자가 보낸 것처럼 요청을 전송하는 것을 주 목적으로 한다.

어떤 취약점들이 있고 어떻게 공격할 수 있는지 다음과 같은 순서대로 다루겠다.

  • Cross Site Scripting(XSS): 공격자의 입력값이 크로스 사이트의 자바스크립트 일부로 웹 브라우저에서 실행되는 취약점을 말한다. 실행된 스크립트는 해당 사이트의 일부가 되어 SOP 제약 없이 사이트의 구조를 변경하거나 임의 HTTP 요청을 보낼 수 있다.
  • Cross Site Request Forgery(CSRF): 비정상적으로 사용자의 의도와 무관하게 HTTP 요청을 보내는 것을 CSRF 공격이라 한다. Simple Request나 HTML 엘리먼트라면 SOP 제약을 받지 않는다는 점을 이용한다.
  • Open Redirect: Redirect 기능을 악용해 피싱사이트로 접속을 유도하거나, 다른 취약점을 연계하여 사용자를 공격할 수 있다.
  • Click Hijacking: 공격자가 생성한 버튼, 이미지와 같은 엘리먼트를 정상적인 iframe 위에 겹쳐 올려 UI를 스푸핑해 사용자 의도와는 다른 작업을 수행하게 하는 취약점이다.

0개의 댓글