Write Up
먼저, Prototype pollution 근원지를 수동으로 탐색해 본다. 이는 많은 시도와 에러들이 동반된다. 즉 Object.prototype 이 작동하는 근원지를 찾을 때까지 임의의 속성을 추가하는 다양한 방법을 시도해야 한다.
→ 쿼리 스트링, URL fragment, JSON input을 통해 임의 속성 주입을 시도해 본다.
해당 Lab에서는 쿼리 스트링을 사용해 속성 주입을 시도하였고, 성공적으로 prototype pollution 이 발생하였다.
만약, 속성이 Prototype에 추가되지 않은 경우 대괄호 표기 대신 점 표기 방식으로 전환하거나 그 반대로 전환하는 등 다양한 기술을 사용해봐야 한다. ( 해당 Lab에서는 . 표기 법으로는 prototype pollution에 실패 )
→ 위에서 전역에 임의의 속성을 추가할 수 있는 소스를 식별한 후의 단계는 exploit을 만드는 데 사용할 수 있는 적합한 가젯을 찾는 것이다.
deparam.js는 결론적으로 봤을 때, 객체를 반환하는 역할을 하는 js 이다. 그리고 searchLogger.js의 주요 코드는 아래와 같다.
async function searchLogger() {
let config = {params: deparam(new URL(location).searchParams.toString())};
if(config.transport_url) {
let script = document.createElement('script');
script.src = config.transport_url;
document.body.appendChild(script);
}
if(config.params && config.params.search) {
await logQuery('/logger', config.params);
}
}
config 객체에 transport_url이 존재하면, 새로운 <script> 태그를 생성하여 src 속성을 transport_url로 설정하며, 이 <script> 태그를 문서의 body에 추가하여 외부 스크립트를 동적으로 로드한다.
config 객체에 정의된 transport_url 속성이 없고, 이는 src 요소를 제어할 수 있는 잠재적인 장치이다.
→ exploit
위와 같이 개발자 도구의 debugger를 활용하여, break point를 걸어준 뒤 config 객체의 transport_url 속성 값이 할당되는 것을 확인할 수 있다.
위 그림 4와 같이 XSS를 유발하는 payload를 삽입하여, <script>를 동적으로 로드 시켜 문제를 해결한다.
▶ 참고 및 출처
- https://portswigger.net/web-security/prototype-pollution/client-side/lab-prototype-pollution-dom-xss-via-client-side-prototype-pollution
- https://medium.com/@fath3ad.22/understanding-dom-based-xss-sources-and-sinks-c17ae4bc7455