## https://sploitus.com/exploit?id=6CC8C408-170F-525D-B20B-CF0E282DDE5A
# CVE-2025-14321
# Proof of Concept - Probado en Mozilla Firefox 145.0.1 - Se provoca un crash
## Descripción
PoC para una vulnerabilidad Use-After-Free (UAF) en el componente `RTCEncodedFrameBase` de Firefox, explotable a través de la API WebRTC Encoded Transforms.
**CVE-2025-14321**: El destructor de `RTCEncodedFrameBase` no llama a `DetachArrayBuffer()` al liberar la memoria nativa del frame. Como resultado, los ArrayBuffers de JavaScript retienen punteros a memoria ya liberada (dangling pointers), permitiendo lectura y escritura arbitraria sobre el heap del proceso content de Firefox.
## Causa raíz
Firefox expone los frames de video/audio codificados como ArrayBuffers de JavaScript a través de `NewArrayBufferWithUserOwnedContents()`. Cuando el frame nativo (C++) se destruye, la memoria backing del ArrayBuffer se libera, pero el ArrayBuffer en JavaScript **no se desvincula (detach)**. Esto viola la invariante de ownership y genera un dangling pointer.
Código vulnerable (`dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp`):
```cpp
// ❌ Destructor no desvincula el ArrayBuffer
RTCEncodedFrameBase::~RTCEncodedFrameBase() = default;
```
Código parcheado:
```cpp
// ✅ Desvincula el ArrayBuffer antes de liberar memoria nativa
RTCEncodedFrameBase::~RTCEncodedFrameBase() {
DetachData();
}
```
## Versiones afectadas
- Firefox ` de 320×240 con animación a 30fps vía `captureStream(30)`. Esto genera frames de video codificados de forma predecible. Una vez que ICE conecta y se usó la cámara, el PoC reemplaza el track de cámara por el de canvas vía `replaceTrack()` y libera la cámara.
### 3. Conexión WebRTC loopback
Se crean dos `RTCPeerConnection` locales (pc1 ↔ pc2) con negociación SDP estándar y trickle ICE. Los candidatos se intercambian directamente entre peers.
### 4. Transform Worker (RTCRtpScriptTransform)
Se asigna un `RTCRtpScriptTransform` al sender de pc1 **antes** de la negociación SDP. El worker intercepta cada frame codificado del pipeline de envío.
### 5. Retención de ArrayBuffers (200 frames)
Para cada uno de los primeros 200 frames, el worker:
1. Extrae `frame.data` (ArrayBuffer que apunta a memoria nativa)
2. Guarda la referencia en un array (`leaks[]`)
3. Escribe un patrón conocido: `new Uint8Array(buf).fill(0x41)`
4. **NO reenvía el frame** → el wrapper nativo se destruye → la memoria se libera
Al no reenviar, el GC destruye el wrapper C++ y libera la memoria nativa. Pero el ArrayBuffer de JavaScript retiene el puntero — dangling pointer creado.
### 6. Detección de UAF
A partir del frame 201, cada 3 frames el worker:
1. Lee los primeros 16 bytes de cada buffer retenido
2. Si algún byte difiere de `0x41`, el allocator reutilizó esa memoria → **UAF confirmado**
3. Reescribe `0x41` sobre el buffer (write primitive sobre heap ajeno)
Este ciclo de lectura/escritura sobre memoria liberada causa corrupción progresiva del heap hasta que Firefox crashea el tab (equivalente a SIGSEGV reportado en el advisory).
## Resultados esperados
### Versión vulnerable (Firefox < 146)
```
[0.4s] ✓ getUserMedia concedido — ICE modo 1 activo
[0.4s] ✓ ¡CONEXIÓN ICE ESTABLECIDA!
[0.5s] ▶▶▶ ¡PRIMER FRAME ENCODED RECIBIDO! ◀◀◀
[0.5s] Leak #0: 1219B → 41414141414141414141414141414141
[2.7s] Leak #49: 1497B → 41414141414141414141414141414141
[9.8s] Leak #199: 1870B → 41414141414141414141414141414141
[9.9s] 200 ArrayBuffers retenidos → memoria nativa YA liberada
[9.9s] → Dangling pointers activos, esperando reuso…
[TAB CRASH — heap corruption]
```
El crash del tab confirma corrupción de heap: la escritura de `0x41` sobre memoria reasignada a otros objetos (vtables, DOM nodes) causa un acceso a memoria inválido en el proceso content.
### Versión parcheada (Firefox ≥ 146)
```
✓ Buffer[0] detached correctamente — fix activo
ArrayBuffer detached — versión parcheada ✓
```
El `DetachData()` en el destructor invalida el ArrayBuffer antes de liberar la memoria nativa, eliminando el dangling pointer.
## Estructura del proyecto
```
├── poc-cve-2025-14321.html # PoC funcional (código fuente legible)
├── poc-cve-2025-14321-obfuscated.html # PoC ofuscado (XOR + shuffle + anti-devtools)
└── README.md # Este archivo
```
## El parche
Mozilla corrigió la vulnerabilidad en Firefox 146 agregando `DetachData()` en todos los destructores y teardown paths de `RTCEncodedFrameBase`.
Commit: https://hg-edge.mozilla.org/mozilla-central/rev/1051067f6e83
## Mitigación
- Actualizar Firefox a la versión 146 o superior
- Actualizar Firefox ESR a la versión 140.6 o superior
## Disclaimer
⚠ **SOLO PARA PROPÓSITOS EDUCATIVOS Y DE INVESTIGACIÓN**
Este PoC demuestra la existencia de la vulnerabilidad hasta el punto de corrupción de heap (crash). No implementa heap shaping, ASLR bypass, ni técnicas de hijack necesarias para ejecución de código. Su propósito es exclusivamente la verificación y comprensión del CVE en entornos controlados.
## Referencias
- CVE: CVE-2025-14321
- Blog post: https://aisle.com/blog/firefox-webrtc-encoded-transforms-uaf-via-undetached-arraybuffer-cve-2025-14321
- Advisory: MFSA 2025-92 · Bug 1992760
- Mozilla commit: https://hg-edge.mozilla.org/mozilla-central/rev/1051067f6e83
## Créditos
- Descubierto por: Igor Morgernstern, AISLE Research Team
- Fecha de reporte: 2025-10-06
- Fecha de parche: 2025-11-19
- Fecha de publicación: 2025-12-09