Dom-Based-XSS
DOM-Based-XSS란?
DOM-Based-XSS는 Reflected xss와 유사하지만, 엄연히 다르다. 이 둘의 차이점은 DOM-Based의 경우 Relected 와 달리 입력 값을 통해 동적 웹 페이지를 구성 및 악성 스크립트가 실행되는 구간이 웹 브라우저(Client Side)이다. 즉 주로 URL의 해시(fragment identifier)나 클라이언트 측에서 동적으로 변경되는 DOM 요소에 악성 스크립트가 삽입되어 발생한다. 오늘날에 Server의 부하를 줄이기 위해 dom사용이 증가하고 있어, DOM-Based의 중요도가 커지고 있다. 또한 DOM-Based의 경우 사용자의 입력값에 대해 처리 로직이 브라우저단에서 이루어져 소스코드로 노출 될 수 있다.
예를 들어, innerHTML와 같은 코드를 사용해 DOM 을 제어할 수 있는 경우, 이 때 악의적인 입력값을 통해 브라우저 단에서, JavaScript를 실행시킬 수 있다.
- 일반적으로 JS가 URL과 같은 소스에서 데이터를 추출하여 innerHTML과 같은 속성을 사용하여 동적 코드를 실행할 때 발생한다 이를 통해 공격자는 악의적인 JS 를 실행할 수 있다.
💡 여기서 DOM이란? Dpcument Object Model의 약자로, 한글로 직역하면 문서 객체 모델이다. 이는 html, xml 문서의 프로그래밍 interface이며, 문서의 구조화된 표현을 제공하고, 프로그래밍 언어를 통해 dom 구조에 접근할 수 있는 방법을 제공한다. 이를 이용하게 되면, 문서의 구조, 스타일, 내용등을 변경할 수 있다.
[WEB] DOM (Document Object Model)
[WEB] DOM (Document Object Model)
DOM이란 무엇인가? Document Object Model 즉 문서 객체 모델로서 XML 또는 HTML 문서에 접근할 수 있도록 하는 인터페이스이며, 계층 적으로 표현되는데, 이를 통해 내용을 생성, 변경 및 삭제등 작업을
hg2lee.tistory.com
Detection
사용자의 입력 값이 매개변수로 사용되는 싱크를 찾아 임의의 값을 입력해 보아야 한다.
그 후 브라우저 단에서 소스코드를 확인해보며, 입력값을 찾았다면 여러 방법등을 통해 출력되는 구간을 탈출 할 수 있는지 확인해야한다.
<aside> 💡 innerHTML태그는 html5부터 <script> 태그가 실행되지 않게 설정되 HTML 이벤트 헨들러를 사용하여 악성 스크립트를 실행시켜야 한다.
</aside>
예를 들어 아래와 같은 코드가 존재한다고 가정해보자.
<script>
function trackSearch(query) {
document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');
}
var query = (new URLSearchParams(window.location.search)).get('search');
if(query) {
trackSearch(query);
}
</script>
사용자가 입력한 값을 query 라는 매개변수에 저장하고 위와같이 dom을 제어하는
document.write를 사용하여 브라우저에 출력 시키는 기능이다.
이 때 우리는 입력값을 조작하여, 강제적으로 <img> 태그를 종료시키고 새롭게 태그를 만들어
dom을 조작할 수 있다.
">;<img src='' onerror=alert(1)>//
or
">;<script>alert(1)</script>//
위와 같이 조작된 코드를 삽입하게 되면, 아래와 같이 동작하게 된다. 즉 두개의 태그가 document.write에 의해 브라우저에서 실행되게 된다.
document.write('<img src="/resources/images/tracker.gif?searchTerms=">;<script>alert(1)</script>//">');
사용자의 입력값 제출이 없거나 혹은 브라우저 내 렌더링 되지 않는다면?
흔히 xss 라고하면 사용자의 입력값을 제출하고 입력값이 웹 페이지 내에 렌더링 될 때 xss 취약점이
존재한다고 판단하지만, 그렇지 않는 경우 또한 있다. 이러한 공격 표면을 찾아내기 위해서는,
DevTools를 이용하여 소스코드를 유심히 보고 DOM 을 제어하는 부분을 찾아내야한다.
<script>
var stores = ["London","Paris","Milan"];
var store = (new URLSearchParams(window.location.search)).get('storeId');
document.write('<select name="storeId">');
if(store) {
document.write('<option selected>'+store+'</option>');
}
for(var i=0;i<stores.length;i++) {
if(stores[i] === store) {
continue;
}
document.write('<option>'+stores[i]+'</option>');
}
document.write('</select>');
</script>
위와 같은 코드가 존재 한다고 가정해보자.
window.location.search 를 사용해서 storeId라는 매개변수의 값을 가져와 store 에 저장하고
저장된 변수를 document.write를 사용하여 렌더링한다.
분명 웹 페이지에 내에 입력값을 따로 주는 부분은 없으며, 무언가를 체크하는 기능을 사용해도
storeId 라는 매개변수로 넘어가지는 않는다.
이 때 burpswite와 같은 프록시 툴을 사용하여 넘어가는 패킷을 보게되면
POST /product/stock HTTP/2
Host: 0aca004e0468e36b8201847c003b0018.web-security-academy.net
Cookie: session=7vniRwYfK2aFaYCUDVOUIfv1yFoMPCSv
Content-Length: 25
Sec-Ch-Ua: "Not=A?Brand";v="99", "Chromium";v="118"
Sec-Ch-Ua-Platform: "Windows"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.88 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: <https://0aca004e0468e36b8201847c003b0018.web-security-academy.net>
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: <https://0aca004e0468e36b8201847c003b0018.web-security-academy.net/product?productId=1>
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
**productId=1&storeId=Paris**
아래쪽에 storeId에 값을 받아 넘기고 있다. 그럼 이를 확인했으니, URL을 통해 GET으로 해당 매개변수를 통해 Script 전송 할 수 있다.
productId=1&storeId=<script>alert(1)</script>
innerHTML 을 사용하는 구간
innerHTML 은 HTML5 이후 <script> 태그가 사용되지 못하도록 되었다. 이로 인해 html태그 내에서 이벤트 핸들러를 사용하여 스크릅티를 발생시켜야 한다.
<img src='' onerror=alert(1)>
document.write()
document.writeln()
document.domain
element.innerHTML
element.outerHTML
element.insertAdjacentHTML
element.onevent
여러 프레임워크에서 발생하는 DOM XSS
1. JQuery
jquery는 현재 정말 많이 사용되는 프레임워크이지만 해당 프레임워크에서도 dom based xss 취약점이 존재한다. 이는 hashchange라는 이벤트 핸들러로 인해 발생되는데, 이는 URL 해시가 변경될 떄 발생하게 되는데, (#(Fragement) 뒤에 오는 문자열을 일컫는다.)
또한 $() 라는 JQuery의 선택기 를 악용하는것인데 이는, HTML을 구문 분석을하기에 가능하다.
<script>
$(window).on('hashchange', function(){
var post = $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');
if (post) post.get(0).scrollIntoView();
});
</script>
위와 같은 코드가 존재할 때
hashchange 즉 # 해시값이 변경될 때 function을 실행하며,
URL #뒤에 나오는 Hash 부분에서 1번째 값을 추출해서 가져오고 sectuib clss가 blog-list이며, h2태그의 이름에 hash값과 동일한 부분이 있으면 스크롤이 이동하는 기능이다.
이 떄 $() 은 HTML을 구문분석 하므로, HTML 태그가 실행이 가능하다. 하지만 일반적인 방법으로는 hash 값이 변경되지 않으므로, iframe을 이용할 수 있다.
아래와 같이 사용할 경우 xss취약점이 존재하는 사이트로 이동 후 이동에 성공하였으니 onload 이벤트 핸들러가 동작하며, 현재 사이트의 주소에서 해시값 뒤에 값을<img src='' onerror=alert(1)> 사용하게 되어 xss가 발생하게 된다.
<iframe src="attack.com/#" onload="this.src='<img src='' onerror=alert(1)>'">
add()
after()
append()
animate()
insertAfter()
insertBefore()
before()
html()
prepend()
replaceAll()
replaceWith()
wrap()
wrapInner()
wrapAll()
has()
constructor()
init()
index()
jQuery.parseHTML()
$.parseHTML()
2. Angular JS
Angular JS또한 많이 쓰이는 js기반의 프레임워크이며, 웹 브라우저에서 Angular JS를 사용할 경우
<> ,”” 와 같인 기능이 필터링 되어 있더라도 이를 사용하지 않고 JavaScript 를 실행시킬 수 있다.
<aside> 💡 HTML 요소 내 ng-app가 존재하면 Angular JS를 사용한다는 것이다.
</aside>
<body ng-app>
위와 같은 속성을 발견했으면, Angular JS 의표현식을 사용할 수 있다.
{{$on.constructor('alert(1)')()}}
<aside> 💡 사용자의 입력값이 브라우저단에 노출되지만, 소스코드에 보이지 않을경우 사용 함수를 유심히 본 후 BurpSuite 같은 프록시 툴을 사용하여, 사이트맵을 통한 js파일에서 해당 함수의 원형과 구조를 살펴보면 그 구간에서도 DOM 문자로 이어지는 XSS 취약점이 존재함.
</aside>
<script>search('search-results')</script>
eval('var searchResultsObj = ' + this.responseText);
{"results":[{"id":1,"title":"I'm At A Loss Without It - Leaving Your Smartphone Behind","image":"blog/posts/55.jpg","summary":"The other day I left my purse in a friend's car. This led to the most disturbing 19 hours of my life until it was returned to me."}],"searchTerm":"Test"}
위처럼 존재할 경우
searchTerm 에 입력값이 들어가며, eval 함수로 전달되니 \”} 로 해당 부분을 닫고
연산자를 통해 연결하여 \”}-alert(1)// 와 같은 페이로드로 xss가 동작할 수 있다.
Referance
https://portswigger.net/web-security/cross-site-scripting/dom-based