
Dev encadeia três bugs do V8 e compromete o Chrome do v8CTF
Um pesquisador encadeou três falhas públicas do V8 contra a build exata do Chrome usada no v8CTF, o desafio contínuo de exploração do Google, e recuperou uma flag real da infraestrutura da empresa. O exploit escapou da sandbox de heap do V8 e atingiu controle nativo do renderer, mas não rendeu os US$ 10 mil: era um n-day, com confiabilidade abaixo dos 80% exigidos.
O alvo e as regras
No v8CTF, o Google mantém um Chrome fixo em sua infraestrutura: após uma prova de trabalho, o participante envia uma URL e o navegador precisa imprimir /flag/flag. O alvo era o Chrome for Testing 150.0.7871.46 em Linux x86-64, com V8 15.0.245.13 - a exatidão importa, porque layouts, offsets e gadgets mudam entre builds próximos.
O Chrome rodava com --no-sandbox: a sandbox de processo estava desativada pelo desafio, mas permaneciam a sandbox de heap do V8 e o isolamento externo (kCTF e nsjail). O autor escapou da sandbox do V8, não da sandbox de processo nem do jail externo.
As regras reservam US$ 10 mil a submissões elegíveis: só a primeira cadeia por bug inicial, normalmente só a primeira por versão implantada (0-days isentos), e sucesso mínimo de 80%.
Três bugs que se completavam
O CVE-2026-15903, bug do compilador otimizador, perdia uma suposição de inteiro seguro ao reduzir valores a 32 bits, e o String.prototype.charCodeAt podia ler fora da string. Sem os auxílios do shell d8, o autor treinou as funções com milhares de eventos de DOM e usou a leitura fora dos limites como oráculo de endereços, apoiado em 64 referências repetidas ao mesmo objeto. O bug dava o endereço, não a escrita.
O CVE-2026-15776 fazia o lastIndex de RegExp cruzar o maior Smi, 1073741823: o valor virava um HeapNumber, mas um caminho rápido o tratava como Smi e a referência old-to-young não era registrada. Coletas menores reciclavam o número com o ponteiro do RegExp ainda válido; com pulverização de alocações, o slot era retomado como um array falso, dando leitura e escrita na gaiola de 4 GB. A base foi o trabalho público de Salvatore Gulizia (Serotav).
Restava a sandbox do V8, que mantém ponteiros nativos fora da gaiola. A saída foi um problema conhecido de JSPI e da JS Dispatch Table: o builtin WasmResume e sua entrada na tabela podiam discordar sobre a limpeza da pilha, deslocando o slot de retorno. Com um receiver forjado e um gadget pop rsp; ret, a pilha nativa migrou para uma alocação grande preparada antes.
Cada estágio precisou de marcadores observáveis, e a leitura e escrita só valeram após uma ida e volta completa de valores. Para vencer o ASLR, o autor corrompeu o comprimento de uma ExternalString sem tocar no handle protegido, expondo uma vtable do binário do Chrome. O ROP final reutilizou open64, read e write presentes no binário, mantendo o W^X: o Chrome headless imprimiu a flag v8CTF{1785916837:02b9910f32b5064c14c693a910748736031da940}.
Por que não houve prêmio
Dois impedimentos independentes. Primeiro, era um n-day: os bugs iniciais eram de outros pesquisadores, e a planilha pública do Google já registrava um n-day da M150 confirmado em 13 de julho, antes da captura em 5 de agosto. Segundo, a confiabilidade: 1 em 5 execuções locais limpas no pacote final e 5 em 10 num lote por túnel, condições mantidas separadas. Notas antigas diziam 3/5, mas os logs brutos registram 1/5. Capturar a flag prova explorabilidade, não vitória.
LLMs como apoio, não atalho
O ChatGPT (modelo Sol) ajudou a navegar código, desenhar experimentos e redigir código; outros modelos pesquisaram alternativas e contestaram afirmações. Não houve prompt que devolvesse um exploit pronto: o ciclo era experimento, quase sempre falha, e repetição. Os modelos eram úteis e, com regularidade, confiantemente errados - inventavam layouts de objetos e tratavam crashes alheios como progresso. O saldo: otimismo com pesquisa assistida por IA, ceticismo com alegações de exploit sem logs.
O que permanece
O V8 vive além da aba do navegador - Node.js, Electron, isolates multi-locatário e WebViews - e a cadeia exata não compromete esses ambientes. Lições do autor: fixar o binário exato, provar um primitivo por vez, tratar toda alocação pós-corrupção como hostil, separar a revelação de endereços do controle de fluxo e contar cada falha - repetir até a flag aparecer não diz nada sobre confiabilidade.