안녕하세요. intadd 입니다.
Dom clobbering을 활용한 xss 에 대해서 포스팅하겠습니다.
작성 계기는 재밌어 보여서입니다.
그리고 Dom Clobbering 에 대한 기술적 설명이 있는 한글 문서가 없더라구여 그래서 작성하게 되었습니다.
(있으면 링크좀 부탁드리겠습니다,,, ㅎ)
+
최근에 발생한(2019년 8월) GMaill xss 가 Dom Clobbering 기반으로 익스 되었다고 함
(이 내용도 뒤에 다루겠습니다.)
Dom Clobbering에 대해서 처음알았기도 하고 너무 신기하고 재밌습니다.
이 기술이 나온지는 조금 오래 됐다고 합니다.
(저만 늦게 안거 같네요,, 근데 진짜 신기합니다.)
또한 이 글은
https://research.securitum.com/xss-in-amp4email-dom-clobbering/
https://www.netsparker.com.tr/blog/web-guvenligi/dom-clobbering/
https://medium.com/@terjanq/dom-clobbering-techniques-8443547ebe94
위 세개의 글을 번역 + 정리+추가 하여 작성한 글입니다.
더 자세하게 알고 싶으신 분은 원본 글을 읽는 것을 추천드립니다.
DoM이란 무엇인가?
https://wit.nts-corp.com/2019/02/14/5522
위 블로그 글에서 "요약정리" 에서 말하는 Dom의 사용 이유중 1
"페이지의 콘텐츠 및 구조, 그리고 스타일이 자바스크립트 프로그램에 의해 수정되기 위해 사용됩니다."
라고 합니다. 한번 읽어 보시면 좋을 것 같습니다. ㅎㅎ
(안읽어 봐도 DOM 이 뭔지 알면 좋을 것 같습니다.)
Dom Clobbering 이란
클로버링 (Clobbering)은
(처음 papago에 처보니까 두두려 패다? 라고 나오길래 아니 어떻게 해야 Dom을 두두려 패버리는 것인가. 라고 생각했습니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ)
진짜 정의 : 파일 또는 데이터의 우연적인 삭제 또는 겹쳐 씀을 말한다. 라고 합니다.
예를 들어
<a id="CONFIG"></a>
이 태그가 있다고 가정합시다.
일반적으로는 해당 태그에 접근하기 위해서는
javasciprt 방법
document.getElementById('CONFIG')
을 많이 사용합니다.
하지만
window object를 통해서
document.getElementById와 동일 하게 사용할 수 있습니다.
window.CONFIG
이를(window.name)통해 global 변수를 존재 여부로 판단하는 코드에서
문제가 발생합니다.
어떻게 문제를 발생 시킬지는 아래에서 다루겠습니다.
이를 이용한 취약점을 Dom Clobbering이라고 합니다.
자 그러면 dom 을 어떻게 겹치고 사용하는지 보겠습니다.
브라우저는 FORM의 elements 중 name 과 id 를 Form 의 property으로 처리합니다.
만약에 "FORM에 동일한 property 이름이있는 경우 FORM의 element(id,name)가 property으로 대체됩니다."
즉 form.propertyname 이 이미 있는 상태에서
form 의 id나 name에 propertyname 이 들어가게 되면
form.propertyname 은 기존에 있던
propertyname이 아닌
getElementid (id,name) 처럼 사용된다는 것입니다
잘 이해가 안가시면 아래 test를 봅시다.
Dom Clobbering Test1
test1.
위는 특이한 점이 없는 단순한 form 태그와 input 태그입니다.
8~10 라인은 forms[0] 의 submit 을 실행하는 js 입니다.
(forms[0] = form 태그들 중에 0번째)
브라우저를 통해서 열어보면 계속 정상적으로 action="" 값으로 submit() 함수를 실행할 것입니다.
(아마 계속 반복하겠죠? 중요한거 아닙니다.)
자여기서 Dom Clobbering 을 살짝 사용해보면 아래와 같습니다.
5번 라인만 변경했습니다. name="submit" (input 태그의 name 을 submit으로 지정)
브라우저를 통해서 확인해보면
너무 신기하지 않나요?
자 그러면 관리자 도구로 값을 확인해보겠습니다.
첫번 째 (그림 A) 는 아래와 같이 정상적으로 submit() function 을 리턴하고 있습니다.
두번 째 (그림 B Dom clobbering) 는 아래와 같이 function 이 아닌 input Code를 리턴하고있습니다.
자 위의 실습을 정리를 해보면
원래 정상적으로는 document.forms[0].submit 의 값이 submit() fuction(함수)가 되는 것이 맞습니다.
하지만 name의 값을 submit 으로 지정해주므로써 (dom clobbering)
(Property(submit()) 가 덮어씌어짐)
document.forms[0].submit 이 코드가
submit 함수가 아닌 , forms[0] 의 "name이 submit"인 값을 찾게 되는거죠.
이거 저만 신기하나요? ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
(cf. window 안썼는데 저게 왜 전역이야 ? ㅡㅡ,
--> document == window.document)
또한
문서 개체(document object)의 property 와 동일한 이름을 가지고 있거나
같은 이름의 변수가 global scope에 있을 경우에 곂침이 발생하여
Overwrite(덮어씌어짐)가 발생합니다.
자 위의 소스코드를 보시면 <div> 태그가 있고,
아래에 js를 통해서 intadd 라는 Elementid를 갖고 오겠다 뭐이런 의미입니다.
추가적으로 변수나 다른 작업을 안해서 가지고만 오는 코드입니다.
콘솔에 에러도 안뜨고 모두가 평화롭고 정상적으로 작동하네요
매우 잘 작동하죠?
document.getElementById 함수가 매우 잘 작동합니다.
여기서 Dom Clobbering 한번 넣어보겠습니다.
동일한 소스코드에 3~4 라인만 추가되었습니다.
form 태그의 name이 getElementById 가 되었네요
브라우저를 통한 콘솔을 확인해보면
(코알라 짤 + 고양이 짤) 한번더 쓰겠습니다.
여기까지가 Dom Clobbering 에대한 설명과 예시입니다.
이해가 가시나요?
이해가 안가시면 제가 설명을 잘 못한것 같습니다,, ㅜㅜ
이제 실제 Dom Clobbering 을 이용한 XSS 에 대해서 알아보겠습니다.
여기까지만 보시면,
음 아 대충 dom clobbering 이 이런거구나,,
,,,,,,,,
근데 ?
이걸로 뭐할건데?
뭐지,,,?
잉?
라는 결론에 도출합니다.
이제 xss 에 활용해보겠습니다.
조건.
1. HTML injection 이 가능해야한다.
2. 1번을 통해 작성되는 html tag가 js 가 해당 object 에 접근 하기 전에 선언 되어 있어야한다.
간단하게 2개정도가 되겠네요
1번은 뭐,, 단순한 xss의 선행 조건이기도 하니까요
다른 사이트들에서 사용한 예시를 약간 수정해서 사용하겠습니다.
이러한 js 가 있습니다.
위의 소스코드만 보면 8~15 line 까지 CONFIG (object)를 정의해줍니다.
8 line : window.CONFIG 가 없을 경우 {..} 값을 지정
13 line: CONFIG.test 가 false 가 아닐 때 document.write를 통해서
"A" 를 작성할 겁니다.
정상적이라면 이 8~15라인을 수정하지 않는 한
14라인을 실행시킬 수 없습니다.
위를 브라우저를 통해 열어보면 당연히 "A" 는 출력 되지 않고,
CONFIG.test 도 false 입니다.
여기서 위에서 다룬 DOM Clobbering 을 적용하면
위 5 line에 입력 하겠습니다.
5~7 라인을 추가했습니다.
위를 브라우저로 올려보면
자 이렇게 DOM Clobbering 을 통해서
간단한 js 우회? 를 해봤습니다.
원리는 생략해도 될까요? 하하 ...
이 우회가 가능헀던 이유 1번 째는 10 라인입니다.
window.CONFIG = window. CONFIG || { .. 이하 생략 ..}
이 구문에서 window.CONFIG 가 존재하면
그대로 사용하고, 아니면 { 이하 생략 } 으로 대체한다 라는 구문입니다.
정상적이라면 window.CONFIG 가 undefined 이겠지만,
Dom clobbering을 통해서 <input >로 대체 된겁니다.
그러므로 15 라인을 통과한 것이지요
자 그러면 XSS 를 하는 방법에 대해서 보겠습니다.
원하는 값을 쓰기 위해서는 return 값이 object 가 아닌
저희가 조작할 수 있는 데이터가 들어가야합니다.
어떠한 함수를 사용하는지에 따라서 데이터를 넣을 수 있는지 없는지가 나누어집니다.
위의 table 에 적혀있는 것들이 ToString을 사용하는 것들이네요
태그 중 ToString 방법이 Object.prototype으로 부터 계승 되는지
아니면 다른 방식으로 정의 되는지 확인하여야 합니다.
이게 무슨 말이냐면,
객체들이 가지고 있는 ToString 이라는 function 이
어떠한 방법으로 구현?(계승) 되는지를 판단하는 겁니다.
확인하는 js 코드입니다.
Elements 를 포함하는 개체들 중 prototype.toString 과
Object.prototype.toString 이 이 다른 것을 찾아라 하는 코드입니다.
결과는 <a> 태그와 <area> 태그가 있네요
어떻게 다른지 확인해보겠습니다.
자 위의 코드가 있습니다.
해당 태그들의 toString 값을 확인해 볼까요?
자 그러면 A Tag의 (object , HTMLAnchorElement) 의 toString은 어디서 값을 가져오는 걸까요?
위의 보시면 "href" 값을 반환한다고 되어 있습니다.
이를 이용해서 값을 변조하는 예시를 보겠습니다.
이러한 소스코드가 있다고 가정합시다.
13 라인을 보시면
CONFIG.KeyValue 값이 false가 아닐경우
CONFIG 의 ToLocation 으로 이동 시킵니다. (14 line )
false일 경우
CONFIG 의 DefaultLocation 으로 이동시킨다고 합니다.(17 line)
저의의 목표는 Dom Clobbering 을 적용하여 alert를 발생시키는 것입니다.
조건 1. CONFIG 가 False 아니여야 한다.
조건 2. window.CONFIG.Location 이 js alert를 가르켜야한다.
조건 1번은 이미 했기 때문에 넘어가겠습니다.
저희는 a Tag의 toString이 href 라는 것을 알고 있습니다.
window.CONFIG.ToLocation을 변경하기 위해서는
이러한 HTML 이 있으면 되겠죠?
위의 코드로 테스트를 해보면
undefined으로 가게된니다.
왜일까요?
input 태그는 form 태그의 속성값으로 사용 할 수 있지만,
a 태그는 form 태그의 속성값으로 사용 할 수 없습니다.
그러면 다른 방법을 사용하여야 합니다.
HTML Collections에 대한 활용
'
이러한 동일한 id를 갖는 a tag 가 있습니다.
우리가 window.hello 를 출력하면
< a id ="hello">1</a>
(동일 속성값의 첫번 째)
가 나올 것으로 예상 할 수 있습니다.
하지만 값을 확인해보면,
자 이렇게 보시면 HTMLCollection이 반환되는 것을 확인 할 수 있습니다.
또한 저희는 HTMLCollection을 index(0,1) 와 id로 접근 할 수 있는 것을 알고있습니다.
window.hello.hello 로 접근을 하면 첫 번 째 element을 반환하네요
name을 통해서 HTMLCollection에 새로운 속성도 생성 할 수 있습니다.
자 이걸 정리해보면
동일한 id를 만들어 HTMLCollection을 만든 후
id 중 하나를 name 을 통해 새로운 속성으로 만들어주는 겁니다.
다시 저희가 문제를 보겠습니다.
조건 2. window.CONFIG.Location 이 js alert를 가르켜야한다.
를 구현한다면,
이렇게 되겠죠?
브라우저를 통해서 확인해보면
짠 이렇게 alert가 정상 작동합니다.
값을 확인해보겠습니다.
이해가 가시나요?
자 그러면 구글 GMAIL의 AMP4EMAIL 케이스를 보겠습니다.
문제점이 발생한 소스코드를 보기 쉽게 정리하면 아래와 같습니다.
출처: https://research.securitum.com/xss-in-amp4email-dom-clobbering/
자 위에서 Dom Clobbering 을 공부했으니 취약점이 보이시나요?
5 line:
AMP_MODE.test (window.AMP_MODE.test) 와 window.testLocation 존재 여부를 검사하네요
True 일 경우 window.testLocation을 사용한다고 합니다.
또한
11 line:
AMP.localDev 가 False 이면 loc를 cdn.. 으로 넣기 때문에
payload가 성립이 안됩니다.
근데 이 값들은 다 저희가 만들어줄 수 있죠!
Dom Clobbering을 통해서 ㅎㅎ
그러므로 다시 필요 없는 코드를 다 제거하면,
(b 는 line 1~2 의 script 입니다.)
위와 같이 되겠네요
원하는 js 주소를 를 script(b)의 src로 지정하기 위해서는
위와 같은 페이로드가 나오네요
주석도 잘 달려 있어서 따로 설명은 안해도 될꺼 같은데 ㅎㅎ
Payload를 완성하기 위한 조건.
1.AMP_MODE.localDev 와 AMP_MODE.test 가 False 이면 안됩니다.
이를 충족하기 위해서 2~4 line이 있는 겁니다.
2. testLocation.protocol 의 값을 원하는 값으로 변경하여야 한다.
7~9 line이 있는 겁니다.
이렇게 하면 pastebin/생략.js으로 <script src= 가 되겠네요
!!!!!!
이걸로 Dom Clobbering 포스팅을 마무리 할려고 합니다...
아 그전에 잠깐,
방금 봤던 Gmail Xss 는 결론적으로 CSP 때문에
완벽하게 동작하지 못했다고 하네요
(What is CSP? )
하하 아무튼 포스팅은 여기까지 하겠습니다.
너무 오래 걸렸네요... 힘들다..
보안 기법도 해야하는데,,
다음에 뵙겠습니다.
안녕~
'web > 웹 해킹 및 보안' 카테고리의 다른 글
똑똑, 스팸메일입니다. (분석기) (1) | 2020.06.07 |
---|---|
NEW? XSS Error bypass using '{}' (js block statement) (0) | 2020.02.25 |
JavaScript-based DDoS[번역] (0) | 2019.04.28 |
SSG CTF 2017[noitcejni] payload 및 후기 (3) | 2017.05.30 |
OWASP 취약점 정리(4/10) 취약점 직접 객체 참조 (0) | 2017.05.25 |
댓글