DOM XSS
Reading time: 9 minutes
tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:
HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
DOM 취약점
DOM 취약점은 공격자가 제어하는 소스(예: location.search, document.referrer, 또는 document.cookie)에서 데이터가 안전하지 않게 싱크로 전송될 때 발생합니다. 싱크는 악성 데이터를 받으면 해로운 콘텐츠를 실행하거나 렌더링할 수 있는 함수나 객체(예: eval(), document.body.innerHTML)입니다.
- 소스는 공격자가 조작할 수 있는 입력으로, URL, 쿠키 및 웹 메시지를 포함합니다.
- 싱크는 악성 데이터가 부작용을 초래할 수 있는 잠재적으로 위험한 엔드포인트로, 스크립트 실행과 같은 결과를 초래할 수 있습니다.
위험은 데이터가 적절한 검증이나 정화 없이 소스에서 싱크로 흐를 때 발생하며, 이로 인해 XSS와 같은 공격이 가능해집니다.
tip
더 업데이트된 소스 및 싱크 목록은 https://github.com/wisec/domxsswiki/wiki에서 확인할 수 있습니다.
일반적인 소스:
document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
IndexedDB(mozIndexedDB, webkitIndexedDB, msIndexedDB)
Database
일반적인 싱크:
| Open Redirect | Javascript Injection | DOM-data manipulation | jQuery |
|---|---|---|---|
location | eval() | scriptElement.src | add() |
location.host | Function() constructor | scriptElement.text | after() |
location.hostname | setTimeout() | scriptElement.textContent | append() |
location.href | setInterval() | scriptElement.innerText | animate() |
location.pathname | setImmediate() | someDOMElement.setAttribute() | insertAfter() |
location.search | execCommand() | someDOMElement.search | insertBefore() |
location.protocol | execScript() | someDOMElement.text | before() |
location.assign() | msSetImmediate() | someDOMElement.textContent | html() |
location.replace() | range.createContextualFragment() | someDOMElement.innerText | prepend() |
open() | crypto.generateCRMFRequest() | someDOMElement.outerText | replaceAll() |
domElem.srcdoc | ``Local file-path manipulation | someDOMElement.value | replaceWith() |
XMLHttpRequest.open() | FileReader.readAsArrayBuffer() | someDOMElement.name | wrap() |
XMLHttpRequest.send() | FileReader.readAsBinaryString() | someDOMElement.target | wrapInner() |
jQuery.ajax() | FileReader.readAsDataURL() | someDOMElement.method | wrapAll() |
$.ajax() | FileReader.readAsText() | someDOMElement.type | has() |
| ``Ajax request manipulation | FileReader.readAsFile() | someDOMElement.backgroundImage | constructor() |
XMLHttpRequest.setRequestHeader() | FileReader.root.getFile() | someDOMElement.cssText | init() |
XMLHttpRequest.open() | FileReader.root.getFile() | someDOMElement.codebase | index() |
XMLHttpRequest.send() | Link manipulation | someDOMElement.innerHTML | jQuery.parseHTML() |
jQuery.globalEval() | someDOMElement.href | someDOMElement.outerHTML | $.parseHTML() |
$.globalEval() | someDOMElement.src | someDOMElement.insertAdjacentHTML | Client-side JSON injection |
| ``HTML5-storage manipulation | someDOMElement.action | someDOMElement.onevent | JSON.parse() |
sessionStorage.setItem() | XPath injection | document.write() | jQuery.parseJSON() |
localStorage.setItem() | document.evaluate() | document.writeln() | $.parseJSON() |
**[**`Denial of Service`**](dom-xss.md#denial-of-service)** | someDOMElement.evaluate() | document.title | ``Cookie manipulation |
requestFileSystem() | ``Document-domain manipulation | document.implementation.createHTMLDocument() | document.cookie |
RegExp() | document.domain | history.pushState() | WebSocket-URL poisoning |
| Client-Side SQl injection | Web-message manipulation | history.replaceState() | WebSocket |
executeSql() | postMessage() | `` | `` |
innerHTML 싱크는 최신 브라우저에서 script 요소를 허용하지 않으며, svg onload 이벤트도 발생하지 않습니다. 이는 img 또는 iframe과 같은 대체 요소를 사용해야 함을 의미합니다.
이러한 종류의 XSS는 찾기 가장 어려운 유형일 가능성이 높습니다. JS 코드 내부를 살펴보고, 제어할 수 있는 값의 객체를 사용하는지 확인한 후, 이를 통해 임의의 JS를 실행할 수 있는 방법이 있는지 확인해야 합니다.
이를 찾기 위한 도구
- https://github.com/mozilla/eslint-plugin-no-unsanitized
- 잠재적인 싱크에 도달하는 모든 데이터를 확인하는 브라우저 확장: https://github.com/kevin-mizu/domloggerpp
예시
Open Redirect
출처: https://portswigger.net/web-security/dom-based/open-redirection
DOM에서의 Open redirect 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 도메인 간 탐색을 시작할 수 있는 싱크에 기록할 때 발생합니다.
URL의 시작 부분을 제어할 수 있는 경우, **javascript:alert(1)**와 같은 임의의 코드를 실행할 수 있다는 점을 이해하는 것이 중요합니다.
싱크:
location
location.host
location.hostname
location.href
location.pathname
location.search
location.protocol
location.assign()
location.replace()
open()
domElem.srcdoc
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.ajax()
$.ajax()
Cookie manipulation
From: https://portswigger.net/web-security/dom-based/cookie-manipulation
DOM 기반 쿠키 조작 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 쿠키의 값에 포함할 때 발생합니다. 이 취약점은 쿠키가 사이트 내에서 사용될 경우 웹페이지의 예기치 않은 동작으로 이어질 수 있습니다. 또한, 쿠키가 사용자 세션 추적에 관여하는 경우 세션 고정 공격을 수행하는 데 악용될 수 있습니다. 이 취약점과 관련된 주요 싱크는:
Sinks:
document.cookie
JavaScript Injection
From: https://portswigger.net/web-security/dom-based/javascript-injection
DOM 기반 JavaScript 주입 취약점은 공격자가 제어할 수 있는 데이터를 JavaScript 코드로 실행할 때 생성됩니다.
Sinks:
eval()
Function() constructor
setTimeout()
setInterval()
setImmediate()
execCommand()
execScript()
msSetImmediate()
range.createContextualFragment()
crypto.generateCRMFRequest()
Document-domain manipulation
From: https://portswigger.net/web-security/dom-based/document-domain-manipulation
Document-domain manipulation vulnerabilities는 스크립트가 공격자가 제어할 수 있는 데이터를 사용하여 document.domain 속성을 설정할 때 발생합니다.
document.domain 속성은 브라우저의 same-origin policy 강제에 중요한 역할을 합니다. 서로 다른 출처의 두 페이지가 document.domain을 같은 값으로 설정하면 제한 없이 상호작용할 수 있습니다. 브라우저는 document.domain에 할당할 수 있는 값에 대해 특정 제한을 두지만, 실제 페이지 출처와 완전히 관련 없는 값을 할당하는 것은 방지합니다. 일반적으로 브라우저는 자식 또는 부모 도메인의 사용을 허용합니다.
Sinks:
document.domain
WebSocket-URL poisoning
From: https://portswigger.net/web-security/dom-based/websocket-url-poisoning
WebSocket-URL poisoning는 스크립트가 제어 가능한 데이터를 WebSocket 연결의 대상 URL로 사용할 때 발생합니다.
Sinks:
WebSocket 생성자는 WebSocket-URL poisoning 취약점으로 이어질 수 있습니다.
Link manipulation
From: https://portswigger.net/web-security/dom-based/link-manipulation
DOM 기반 링크 조작 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 현재 페이지 내의 탐색 대상에 기록할 때 발생합니다. 예를 들어 클릭 가능한 링크나 양식의 제출 URL이 있습니다.
Sinks:
someDOMElement.href
someDOMElement.src
someDOMElement.action
Ajax 요청 조작
From: https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation
Ajax 요청 조작 취약점은 스크립트가 XmlHttpRequest 객체를 사용하여 발행되는 Ajax 요청에 공격자가 제어할 수 있는 데이터를 작성할 때 발생합니다.
Sinks:
XMLHttpRequest.setRequestHeader()
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.globalEval()
$.globalEval()
로컬 파일 경로 조작
From: https://portswigger.net/web-security/dom-based/local-file-path-manipulation
로컬 파일 경로 조작 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 파일 처리 API에 filename 매개변수로 전달할 때 발생합니다. 이 취약점은 공격자가 URL을 구성하여 다른 사용자가 방문할 경우 사용자의 브라우저가 임의의 로컬 파일을 열거나 작성하게 할 수 있습니다.
Sinks:
FileReader.readAsArrayBuffer()
FileReader.readAsBinaryString()
FileReader.readAsDataURL()
FileReader.readAsText()
FileReader.readAsFile()
FileReader.root.getFile()
FileReader.root.getFile()
클라이언트 측 SQL 인젝션
From: https://portswigger.net/web-security/dom-based/client-side-sql-injection
클라이언트 측 SQL 인젝션 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 클라이언트 측 SQL 쿼리에 안전하지 않은 방식으로 포함할 때 발생합니다.
Sinks:
executeSql()
HTML5-storage manipulation
From: https://portswigger.net/web-security/dom-based/html5-storage-manipulation
HTML5-storage manipulation 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 웹 브라우저의 HTML5 저장소(localStorage 또는 sessionStorage)에 저장할 때 발생합니다. 이 작업 자체는 본질적으로 보안 취약점이 아니지만, 애플리케이션이 이후에 저장된 데이터를 읽고 안전하지 않게 처리할 경우 문제가 됩니다. 이는 공격자가 저장 메커니즘을 활용하여 교차 사이트 스크립팅 및 JavaScript 주입과 같은 다른 DOM 기반 공격을 수행할 수 있게 할 수 있습니다.
Sinks:
sessionStorage.setItem()
localStorage.setItem()
XPath 주입
From: https://portswigger.net/web-security/dom-based/client-side-xpath-injection
DOM 기반 XPath 주입 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 XPath 쿼리에 포함할 때 발생합니다.
Sinks:
document.evaluate()
someDOMElement.evaluate()
클라이언트 측 JSON 주입
From: https://portswigger.net/web-security/dom-based/client-side-json-injection
DOM 기반 JSON 주입 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 JSON 데이터 구조로 구문 분석되고 애플리케이션에 의해 처리되는 문자열에 포함할 때 발생합니다.
Sinks:
JSON.parse()
jQuery.parseJSON()
$.parseJSON()
웹 메시지 조작
From: https://portswigger.net/web-security/dom-based/web-message-manipulation
웹 메시지 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 웹 메시지로 다른 문서에 전송할 때 발생합니다. 취약한 웹 메시지 조작의 예는 PortSwigger의 웹 보안 아카데미에서 찾을 수 있습니다.
Sinks:
웹 메시지를 전송하기 위한 postMessage() 메서드는 메시지를 수신하는 이벤트 리스너가 수신 데이터를 안전하지 않게 처리할 경우 취약점으로 이어질 수 있습니다.
DOM 데이터 조작
From: https://portswigger.net/web-security/dom-based/dom-data-manipulation
DOM 데이터 조작 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 DOM 내의 필드에 기록할 때 발생하며, 이는 가시 UI 또는 클라이언트 측 로직에서 사용됩니다. 이 취약점은 공격자가 URL을 구성하여 다른 사용자가 방문할 경우 클라이언트 측 UI의 모양이나 동작을 변경할 수 있도록 악용될 수 있습니다.
Sinks:
scriptElement.src
scriptElement.text
scriptElement.textContent
scriptElement.innerText
someDOMElement.setAttribute()
someDOMElement.search
someDOMElement.text
someDOMElement.textContent
someDOMElement.innerText
someDOMElement.outerText
someDOMElement.value
someDOMElement.name
someDOMElement.target
someDOMElement.method
someDOMElement.type
someDOMElement.backgroundImage
someDOMElement.cssText
someDOMElement.codebase
document.title
document.implementation.createHTMLDocument()
history.pushState()
history.replaceState()
서비스 거부
From: https://portswigger.net/web-security/dom-based/denial-of-service
DOM 기반 서비스 거부 취약점은 스크립트가 공격자가 제어할 수 있는 데이터를 문제의 플랫폼 API에 안전하지 않게 전달할 때 발생합니다. 여기에는 호출될 때 사용자의 컴퓨터가 과도한 CPU 또는 디스크 공간을 소비하게 할 수 있는 API가 포함됩니다. 이러한 취약점은 브라우저가 localStorage에 데이터를 저장하려는 시도를 거부하거나 바쁜 스크립트를 종료함으로써 웹사이트의 기능을 제한하는 등의 중대한 부작용을 초래할 수 있습니다.
Sinks:
requestFileSystem()
RegExp()
Dom Clobbering
tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:
HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks