DOM Invader, BurpSuite의 DOM-XSS Testing 도구

아.. PortSwigger에서 또 물건 하나 만든 것 같습니다. PortSwigger의 BurpSuite 스캔 성능 중 손에 꼽는 부분이 바로 DOM Testing 부분입니다. 보통의 도구들은 DOM XSS를 찾기 위해 정해진 패턴을 headless browser로 렌더링하여 테스트하거나 js 코드 내 공격에 주로 사용되는 패턴(eval, innerHTML, document.write 등)을 감지하고 사용자에게 전달해주는 형태로 동작합니다.

BurpSuite는 위 과정을 기본으로 포함하며, 추가적으로 Code 추적과 StackTracing을 통해서 굉장히 정밀하게 테스트합니다. 그래서 DOM XSS 결과를 보면 실제 Trigger가 되는 형태의 페이로드까지 제공해줄 수 있는거구요. 다만 이 기능이 스캐너로만 존재했었는데, 이번 Gareth Heyes가 추가한 DOM Invader 기능을 통해 Manual Testing 시 사용할 수 있게 됩니다. 오늘은 DOM Invader에 대해 알아봅시다.

DOM Invader

정말 따끈따끈한 도구입니다. 6/30일 공개되었고 2021.07 자 Burpsuite 패치를 통해서 Pro 버전과 CE 버전 모두 사용할 수 있도록 추가되었습니다. DOM Invader는 BurpSuite의 내장 브라우저에서 확장 기능 형태로 추가되었으며, 자체적으로 Augmented DOM을 구성해서 대상의 코드/DOM 구조를 TreeView 형태로 볼 수 있게 제공합니다.

`Proxy` > `Open browser` > `우측 상단 확장 기능 중 DOM Invader` 로 접근할 수 있어요.

이는 원래 DOM 분석 시에도 개발자 도구를 통해 사용할 때 크게 편리함을 느끼는 부분인데, 여기에 BurpSuite에서 미리 정의 해둔 패턴(Sinks)에 의해 구조화되어 나타납니다. 결국 Reflected XSS 테스트하는 것과 비슷하게 즉시 DOM 구조와 데이터를 보면서 테스팅 할 수 있습니다.

Released?

오늘 일하면서 잠깐 체크해봤는데, 아직 릴리즈는 아닌 것 같네요. 아마 업데이트가 되어야 사용하실 수 있을 것 같습니다.

그리고 릴리즈 노트에 재미있는게 있었는데요, BurpSuite 로딩 시 보여주는 팝업에는 javascript 코드가 보이는데, 그 이미지 코드의 버그를 누가 제보해서 수정했나봅니다.. 🤣

괄호가 없다아아아아아아

List of source and sinks

DOM Invader 소개 내용 중 List of source and sinks 부분이 있습니다. 이는 DOM Invader에서 사용하는 패턴에 대한 내용인데, 다른 도구에서도 충분히 참고할 수 있을만한 내용이라서 따로 추가해둡니다. (dalfox에서도 아래 패턴을 테스트해줄 수 있도록 고민해볼게요!)

const sourcesList = [
    "location",
    "location.href",
    "location.hash",
    "location.search",
    "location.pathname",
    "document.URL",
    "window.name",
    "document.referrer",
    "document.documentURI",
    "document.baseURI",
    "document.cookie"
];
const sinkRanking = {
    "jQuery.globalEval":1,
    "eval":2,
    "Function":3,
    "execScript":4,
    "setTimeout":5,
    "setInterval":6,
    "setImmediate":7,
    "msSetImmediate":7,
    "script.src":8,
    "script.textContent":9,
    "script.text":10,
    "script.innerText":11,
    "script.innerHTML":12,
    "script.appendChild":13,
    "script.append":14,
    "document.write": 15,
    "document.writeln": 16,
    "jQuery":17,
    "jQuery.$":18,
    "jQuery.constructor":19,
    "jQuery.parseHTML":20,
    "jQuery.has":20,
    "jQuery.init":20,
    "jQuery.index":20,
    "jQuery.add": 20,
    "jQuery.append": 20,
    "jQuery.appendTo": 20,
    "jQuery.after": 20,
    "jQuery.insertAfter": 20,
    "jQuery.before": 20,
    "jQuery.insertBefore": 20,
    "jQuery.html": 20,
    "jQuery.prepend": 20,
    "jQuery.prependTo": 20,
    "jQuery.replaceWith": 20,
    "jQuery.replaceAll": 20,
    "jQuery.wrap": 20,
    "jQuery.wrapAll": 20,
    "jQuery.wrapInner": 20,
    "jQuery.prop.innerHTML": 20,
    "jQuery.prop.outerHTML": 20,
    "element.innerHTML":21,
    "element.outerHTML":22,
    "element.insertAdjacentHTML":23,
    "iframe.srcdoc": 24,
    "location.href":25,
    "location.replace":26,
    "location.assign":27,
    "location":28,
    "window.open":29,
    "iframe.src":30,
    "javascriptURL":31,
    "jQuery.attr.onclick":32,
    "jQuery.attr.onmouseover":32,
    "jQuery.attr.onmousedown":32,
    "jQuery.attr.onmouseup":32,
    "jQuery.attr.onkeydown":32,
    "jQuery.attr.onkeypress":32,
    "jQuery.attr.onkeyup":32,
    "element.setAttribute.onclick":33,
    "element.setAttribute.onmouseover":33,
    "element.setAttribute.onmousedown":33,
    "element.setAttribute.onmouseup":33,
    "element.setAttribute.onkeydown":33,
    "element.setAttribute.onkeypress":33,
    "element.setAttribute.onkeyup":33,
    "createContextualFragment":34,
    "document.implementation.createHTMLDocument": 35,
    "xhr.open":36,
    "xhr.send": 36,
    "fetch": 36,
    "fetch.body": 36,
    "xhr.setRequestHeader.name": 37,
    "xhr.setRequestHeader.value": 38,
    "jQuery.attr.href":39,
    "jQuery.attr.src":40,
    "jQuery.attr.data":41,
    "jQuery.attr.action":42,
    "jQuery.attr.formaction":43,
    "jQuery.prop.href":44,
    "jQuery.prop.src":45,
    "jQuery.prop.data":46,
    "jQuery.prop.action":47,
    "jQuery.prop.formaction":48,
    "form.action":49,
    "input.formaction":50,
    "button.formaction":51,
    "button.value": 52,
    "element.setAttribute.href":53,
    "element.setAttribute.src":54,
    "element.setAttribute.data":55,
    "element.setAttribute.action":56,
    "element.setAttribute.formaction":57,
    "webdatabase.executeSql": 58,
    "document.domain":59,
    "history.pushState":60,
    "history.replaceState":61,
    "xhr.setRequestHeader":62,
    "websocket":63,
    "anchor.href":64,
    "anchor.target": 65,
    "JSON.parse": 66,
    "document.cookie":67,
    "localStorage.setItem.name": 68,
    "localStorage.setItem.value": 69,
    "sessionStorage.setItem.name": 70,
    "sessionStorage.setItem.value": 71,
    "element.outerText": 72,
    "element.innerText": 73,
    "element.textContent": 74,
    "element.style.cssText": 75,
    "RegExp":76,
    "window.name":77,
    "location.pathname": 78,
    "location.protocol": 79,
    "location.host": 80,
    "location.hostname": 81,
    "location.hash": 82,
    "location.search": 83,
    "input.value": 84,
    "input.type": 85,
    "document.evaluate": 86
};

Conclusion

제가 예전에 JS 기반의 DOM 분석 도구를 만드려다가 접은 프로젝트가 있습니다. DOM 분석 자체가 생각보다 굉장히 복잡하고 까다로웠기 떄문인데요.. 어쨌던 PortSwigger에는 똑똑하신 분들이 많아서 그런지 깔끔하게 잘 만들어져서 제가 다시 만들까 했던 의지가 사라져버렸네요 ㅋㅋ (무려 최근에 다시 해볼까 고민중이였지요)

아무튼, 이로써 BurpSuite의 입지는 조금 더 확실해집니다. 물론 ZAP이나 hetty를 사용하시는 분들은.. 별도의 대안을 찾아야겠지요. 요건 제가 확장 기능을 따로 분석해보고, Burp와 연동이 필요한지 체크해볼게요. (아마 버프 자체의 엔진을 쓸겁니다. 왜냐면 버프의 DOM Scanning은 정말 좋은 엔진이거든요)

만약에 혹시나 만약에라도 확장 자체에서 모든걸 처리하는 형태라면, 다른 도구 사용자에게도 희망은 있겠네요 :D

References