Cả ba đều là chèn script vào trang, khác nhau ở nơi payload đi qua và nơi HTML được ghép.
- Reflected: payload nằm trong request (query string, form) và được server ghép thẳng vào HTML trả về. Code sinh lỗi nằm ở template phía server, kiểu
res.send("<h1>Không tìm thấy: " + req.query.q + "</h1>"). - Stored: payload được ghi vào DB (bình luận, tên hiển thị, mô tả sản phẩm) rồi render lại cho mọi người xem. Nguy hiểm nhất vì không cần dụ nạn nhân bấm link.
- DOM-based: request và response hoàn toàn sạch; lỗi nằm ở JavaScript phía client đọc dữ liệu từ một
sourcerồi ghi vào mộtsink.
js
// DOM-based: source = location.hash, sink = innerHTML
const tab = location.hash.slice(1)
document.querySelector('#panel').innerHTML = 'Tab: ' + tab
// #<img src=x onerror=alert(1)>Source hay gặp: location.href/search/hash, document.referrer, postMessage, localStorage. Sink hay gặp: innerHTML, outerHTML, document.write, eval, setTimeout(string), element.setAttribute('href', ...) với javascript:.
Điểm cần nói khi phỏng vấn: DOM-based XSS không đi qua server, nên WAF hay việc escape ở template phía server không chặn được — phải sửa ở chính đoạn JS.