
Escalada de privilegios IPDL de contenido a padre en Firefox (N-day, bug 2054416): PDocumentChannel falsificado con RemoteTypeOverride -> ubicación de proceso privilegedabout, mediante inyección de la ruta de envío de mojo-port desde un proceso de contenido comprometido
Prueba de concepto para una evasión del sandbox en Firefox 149.0a1 nightly (2fbc0748c4,
anterior al parche). Un proceso de contenido comprometido falsifica un mensaje IPDL que hace que el
parent cargue una página en un proceso privilegiado (privilegedabout).
Esta es la evasión del sandbox de etapa 2, diseñada para encadenarse después de una RCE en el proceso de contenido (p. ej., CVE-2026-2796).
El proceso padre deserializa un nsDocShellLoadState de los mensajes IPDL
content→parent. La versión vulnerable no rechaza un campo RemoteTypeOverride
establecido por content, por lo que content puede elegir en qué tipo de proceso
termina una navegación.
El parche (commit 3ec5c71b41bb, "Validate RemoteTypeOverride") hace que el
constructor de nsDocShellLoadState rechace cualquier override en una carga iniciada por content.
Cuando se respeta el override — carga de documento de about:blank, contexto de nivel superior —
IsolationOptionsForNavigation establece el tipo remoto de la carga al valor del override,
y la página se coloca en un proceso privilegiado. Se viola el límite del sandbox.
El override viaja en PNecko::PDocumentChannel, un mensaje que todo proceso de contenido
envía en cada carga de documento (DocumentChannelCreationArgs.loadState es un
nsDocShellLoadState).
La entrega es la parte interesante: las escrituras directas al socket de IPC se descartan silenciosamente, porque los mensajes IPDL viajan ahora sobre puertos mojo. En su lugar, el PoC impulsa la ruta de envío real desde JavaScript mediante llamadas nativas (usando la primitiva funcref de CVE-2026-2796):
operator new — asigna un bloque de heap para el IPC::MessageIPC::Message::Message(routing, type, capacity, flags) — ctor de placementPickle::WriteBytes — añade el payload falsificadoMessageChannel::Send en el canal PContent — el frame mojo, el enrutamiento de puertos
y los números de secuencia se manejan de forma nativaEl payload (construido por forge.py) lleva RemoteTypeOverride = "privilegedabout",
URI about:blank, un principal nulo y valores filtrados en tiempo de ejecución (BrowsingContext id,
TriggeringRemoteType).
./irun
Los logs del lado del padre (MOZ_LOG=ProcessIsolation:5,DocumentChannel:5) muestran el
cambio de proceso al proceso privilegiado:
V/ProcessIsolation using remote type override (privilegedabout) for load
I/ProcessIsolation Process Switch: Changing Remoteness from 'webIsolated=http://127.0.0.1' to 'privilegedabout'
3ec5c71b41bb "Validate RemoteTypeOverride"| Archivo | Propósito |
|---|
privesc.html | Página PoC, se ejecuta dentro del proceso de contenido comprometido |
forge.py / forge.json | construye el mensaje IPDL falsificado (autoverificable) |
wasm-bytes.js | primitivas de etapa 1: lectura/escritura arbitraria, llamadas funcref |
mdrive.py / mdrive2.py | harness de marionette para lanzar y controlar Nightly |
irun | ejecución instrumentada: lldb adjunto al padre + evidencia MOZ_LOG |
profile.user.js | preferencias del perfil de Firefox (fission activado, dump habilitado) |
parse_dc.py | analizador byte-exacto de mensajes DocumentChannel capturados |
scan_sentinels.py / extract_fields.py | escáneres de mapas de campos para capturas |