
Firefox의 RTCEncodedFrameBase에서 WebRTC Encoded Transforms를 통해 Use-After-Free 취약점을 시연하는 개념 증명으로, 힙 손상 및 잠재적 원격 코드 실행(RCE)을 가능하게 합니다.
Firefox의 RTCEncodedFrameBase 컴포넌트의 Use-After-Free (UAF) 취약점에 대한 PoC로, WebRTC Encoded Transforms API를 통해 익스플로잇 가능합니다.
CVE-2025-14321: RTCEncodedFrameBase의 소멸자가 프레임의 네이티브 메모리를 해제할 때 DetachArrayBuffer()를 호출하지 않습니다. 그 결과 JavaScript의 ArrayBuffer가 이미 해제된 메모리를 가리키는 포인터(dangling pointer)를 유지하여 Firefox content 프로세스의 힙에 대한 임의 읽기 및 쓰기가 가능합니다.
이 PoC는 Mozilla Firefox 145.0.1 및 Windows 10에서 테스트되었습니다.
Firefox는 NewArrayBufferWithUserOwnedContents()를 통해 인코딩된 비디오/오디오 프레임을 JavaScript ArrayBuffer로 노출합니다. 네이티브(C++) 프레임이 소멸될 때 ArrayBuffer의 백킹 메모리는 해제되지만, JavaScript의 ArrayBuffer는 분리(detach)되지 않습니다. 이는 소유권 불변식을 위반하여 댕글링 포인터를 생성합니다.
취약한 코드 (dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp):
// ❌ Destructor no desvincula el ArrayBuffer
RTCEncodedFrameBase::~RTCEncodedFrameBase() = default;
패치된 코드:
// ✅ Desvincula el ArrayBuffer antes de liberar memoria nativa
RTCEncodedFrameBase::~RTCEncodedFrameBase() {
DetachData();
}
new Uint8Array(buf)는 힙의 다른 객체에 재할당된 메모리의 데이터를 읽습니다.new Uint8Array(buf).fill(0x41)는 힙의 인접 객체(vtable, DOM 구조 등)를 손상시킵니다.이러한 프리미티브는 취약점을 입증하기에 충분합니다. 추가적인 힙 셰이핑을 통해 원격 코드 실행(RCE)으로 확장될 수 있습니다.
media.peerconnection.scripttransform.enabled = true
media.peerconnection.ice.loopback = true
media.peerconnection.ice.no_host = false
media.peerconnection.ice.relay_only = false
media.peerconnection.ice.proxy_only = false
⚠ 설정을 변경한 후 Firefox를 다시 시작하세요.
PoC는 getUserMedia()를 통해 카메라 접근을 요청하려고 시도합니다. ICE 환경설정이 올바르게 설정된 경우 이는 필수가 아닙니다. 그 역할은 Firefox를 RFC IP handling mode 1으로 승격시켜, 환경설정만으로는 충분하지 않은 시나리오에서 ICE 호스트 후보 생성을 보장하는 것입니다.
실제로는:
getUserMedia()가 프롬프트 없이 조용히 실패합니다(NotFoundError). media.peerconnection.ice.loopback = true 덕분에 ICE는 여전히 연결됩니다.Web Worker는 file://에서 작동하지 않습니다. HTTP로 제공하십시오:
python3 -m http.server 8080
취약한 Firefox에서 열기: http://localhost:8080/poc-cve-2025-14321.html
PoC는 카메라 접근을 요청하려고 시도합니다. 카메라가 있고 사용자가 수락하면 Firefox는 세션을 RFC IP handling mode 1으로 승격시킵니다. getUserMedia()가 실패하면(카메라 없는 VM, 권한 거부), PoC는 캔버스를 프레임 소스로 계속 진행합니다. media.peerconnection.ice.loopback = true가 활성화되어 있으면 ICE는 여전히 연결됩니다.
320×240 크기의 <canvas>가 생성되고 captureStream(30)을 통해 30fps 애니메이션을 만듭니다. 이는 예측 가능한 인코딩된 비디오 프레임을 생성합니다. ICE가 연결되고 카메라가 사용되면 PoC는 replaceTrack()을 통해 카메라 트랙을 캔버스 트랙으로 교체하고 카메라를 해제합니다.
표준 SDP 협상 및 트리클 ICE를 사용하여 두 개의 로컬 RTCPeerConnection (pc1 ↔ pc2)이 생성됩니다. 후보자들은 피어 간에 직접 교환됩니다.
RTCRtpScriptTransform이 SDP 협상 전에 pc1의 sender에 할당됩니다. 워커는 전송 파이프라인의 각 인코딩된 프레임을 가로챕니다.
처음 200개의 각 프레임에 대해 워커는:
frame.data를 추출합니다 (네이티브 메모리를 가리키는 ArrayBuffer)leaks[])new Uint8Array(buf).fill(0x41)재전송하지 않음으로써 GC는 C++ 래퍼를 소멸시키고 네이티브 메모리를 해제합니다. 그러나 JavaScript의 ArrayBuffer는 포인터를 유지합니다. — 댕글링 포인터가 생성됩니다.
201번째 프레임부터 3프레임마다 워커는:
0x41과 다르면, 할당자가 해당 메모리를 재사용한 것입니다 → UAF 확인됨0x41을 다시 씁니다 (다른 힙에 대한 쓰기 프리미티브)해제된 메모리에 대한 이 읽기/쓰기 주기는 Firefox가 탭을 충돌시킬 때까지 힙을 점진적으로 손상시킵니다 (권고에서 보고된 SIGSEGV에 해당).
[0.4s] ✓ Track inicial: canvas (fallback)
[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…
[ CRASH DE PESTAÑA — heap corruption]
참고: 카메라가 있고 권한이 부여되면 로그에
✓ getUserMedia concedido — ICE modo 1 activo가 표시되고 ICE 연결 후✓ Track reemplazado: cámara → canvas가 표시됩니다. 카메라가 없는 VM에서는 PoC가 프롬프트 없이 직접 캔버스를 사용합니다.
탭 충돌은 힙 손상을 확인합니다: 다른 객체(vtable, DOM 노드)에 재할당된 메모리에 0x41을 쓰면 content 프로세스에서 잘못된 메모리 액세스가 발생합니다.
✓ Buffer[0] detached correctamente — fix activo
ArrayBuffer detached — versión parcheada ✓
소멸자의 DetachData()는 네이티브 메모리를 해제하기 전에 ArrayBuffer를 무효화하여 댕글링 포인터를 제거합니다.
├── poc-cve-2025-14321.html # PoC funcional (código fuente legible)
└── README.md # Este archivo
Mozilla는 Firefox 146에서 RTCEncodedFrameBase의 모든 소멸자 및 해제 경로에 DetachData()를 추가하여 취약점을 수정했습니다.
Commit: https://hg-edge.mozilla.org/mozilla-central/rev/1051067f6e83
⚠ 교육 및 연구 목적으로만 사용
이 PoC는 힙 손상(충돌) 지점까지 취약점의 존재를 입증합니다. 힙 셰이핑, ASLR 우회, 코드 실행에 필요한 하이재킹 기술을 구현하지 않습니다. 목적은 통제된 환경에서 CVE의 검증 및 이해에만 있습니다.