
Prova de conceito de exploit para bypass de autorização do BrowsingContext do Firefox (CVE-2026-4692), demonstrando mensagens IPC forjadas para definir InRDMPane e habilitar injeção privilegiada de eventos de toque na interface do usuário.
Prova de conceito para uma verificação de autorização ausente na sincronização
do campo BrowsingContext: um processo de conteúdo comprometido forja uma
mensagem PContent::CommitBrowsingContextTransaction definindo InRDMPane = true
no seu próprio BrowsingContext de nível superior, e o processo pai a aplica.
Alvo: Firefox 149.0a1 nightly @ 2fbc0748c4 (vulnerável, pré-correção), macOS arm64.
Corrigido no Firefox 149 — bug 2017643, commit a9279ce332ed ("Prevent toggling RDM
BrowsingContext flag from content processes"), que adiciona:
bool BrowsingContext::CanSet(FieldIndex<IDX_InRDMPane>, const bool&,
ContentParent* aSource) {
return XRE_IsParentProcess() && IsTop() && !aSource; // rejeita se vier de content
}
InRDMPane informa ao processo pai que a aba é um painel do Responsive Design Mode. O
pai confia nisso ao fazer hit-testing de eventos de toque sintetizados
(BrowserParent::RecvDispatchTouchEvent): eventos que nominalmente visam um painel RDM
podem atingir UI chrome privilegiada. Um processo de conteúdo comprometido
que define o flag pode então enviar eventos de toque com coordenadas negativas/fora do
conteúdo e clicar em UI privilegiada sem interação do usuário (veja o
repro.patch do relator no bug 2017643, que demonstra exatamente isso com uma
build corrigida). Este repositório demonstra a violação de limite habilitadora em si, com
uma forja de mensagem real — sem patches no código-fonte do navegador.
PContent::CommitBrowsingContextTransaction — tipo de mensagem 0x3a0137
(PContentMsgStart=58 << 16 | ordinal 311), roteamento MSG_ROUTING_CONTROL
(INT64_MAX), flags NOT_NESTED (0x001):
u64 bcid sentinela 235406151 ('aContext')
u64 0x0000000000800000 bitset modificado word0 (bit 23 = InRDMPane)
u64 0 bitset word1 (palavras do BitSet<84> são size_t = u64!)
u32 1 WriteBool(true)
u32 523371752 sentinela 'aTransaction'
u64 epoch (a verificação de epoch é apenas MOZ_ASSERT; compilada fora aqui)
u32 132121169 sentinela 'aEpoch'
A entrega reutiliza o caminho de envio do CVE-2026-74939: operator new →
IPC::Message::Message(routing, type, capacity, flags) → Pickle::WriteBytes →
MessageChannel::Send no canal PContent, dirigido a partir de JS via a primitiva
de chamada funcref do wasm (wasm-bytes.js, estágio 1 = CVE-2026-2796).
Log do lado do pai (MOZ_LOG=BrowsingContextSync:5) após ./irun:
D/BrowsingContextSync Transaction::Apply(#380000001, ipc): InRDMPane(false->true)
#380000001 é o BrowsingContext de nível superior do popup (id alocado pelo filho,
criado from IPC), e ipc marca a transação como originada por conteúdo.
Em uma build corrigida, a mesma mensagem falha na validação CanSet e é rejeitada.
Pré-requisitos: build Nightly vulnerável em /Users/sid/gecko-2766/obj-browser,
.venv com psutil, e o servidor de logging incluído em execução:
python3 srv.py > /tmp/srv4692.log 2>&1 & # serve este diretório em :8781
python3 forge_bctx.py # constrói bctx.bin/bctx.json
./irun # inicia + injeta + coleta evidências
a9279ce332ed (MFSA 2026-20, Firefox 149)../poc-cve-2026-74939)../poc-cve-2026-12295)| Arquivo | Finalidade |
|---|
bctx.html | Página PoC: calcula o id do BC do popup em tempo de execução, o insere na mensagem forjada e a envia |
forge_bctx.py | constrói bctx.bin/bctx.json (autoverificável), totalmente estático exceto o id do BC |
wasm-bytes.js | primitivas do estágio 1: R/W arbitrário, chamadas funcref |
mdrive2.py | harness marionette |
irun | execução instrumentada: lldb attach + evidência BrowsingContextSync |
srv.py | servidor web de logging para as páginas PoC (:8781) |
profile.user.js | prefs do perfil do Firefox (fission ativado, dump habilitado) |