Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2023-6702 — Chrome Renderer 1day RCE via Type Confusion em Async Stack Trace (submissão v8ctf) | Kitploit
Ferramentas/GitHubGitHub/kaist-hacking/cve-2023-6702
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebCTFAprendizado e EducaçãoExploração de Binários
GitHubkaist-hacking/cve-2023-6702

CVE-2023-6702

Chrome Renderer 1day RCE via Type Confusion em Async Stack Trace (submissão v8ctf)

Ver Repositório
8697há 2 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

RCE 1day no Renderer do Chrome via Type Confusion em Async Stack Trace (CVE-2023-6702)

Resumo

Esta vulnerabilidade permitiu que um atacante remoto executasse código arbitrário dentro do processo renderizador do Chrome.

Havia uma verificação de tipo insuficiente no código de manipulação de rastreamento de pilha assíncrono. Isso leva a uma confusão de tipo entre FunctionContext e NativeContext, causando acesso ilegal ao valor JSGlobalProxy->hash. Com heap spraying, o atacante conseguiu injetar um frame de pilha assíncrono falso e construir a primitiva fakeobj. Usando a primitiva fakeobj, o atacante conseguiu alcançar execução de código arbitrário no processo renderizador do Chrome.

Você pode verificar nossos slides do TyphoonCon 2024.

Fornecedor / Produto / Versão

  • Google Chrome
  • Versões Afetadas: anteriores a 120.0.6099.109
  • Versão Corrigida: 120.0.6099.109

Linha do Tempo

  • 2020-05-13: Bug Introduzido - [Promise.any] Implment async stack traces for Promise.any
  • 2023-11-10: Relatório de Bug - Security: V8 Debug check failed: LAST_TYPE >= value
  • 2023-11-15: Patch - [promises, async stack traces] Corrige o caso quando a closure já foi executada
  • 2023-12-12: Aviso - https://chromereleases.googleblog.com/2023/12/stable-channel-update-for-desktop_12.html
  • 2024-01-12: Submissão v8CTF <-- O momento em que trabalhamos nesta vulnerabilidade
  • 2024-02-23: Relatório de bug divulgado

Contexto

Rastreamento de Pilha Assíncrono

Assíncrono é uma das características mais importantes em JavaScript. No passado, era difícil depurar código assíncrono com pilha de erros porque funções assíncronas não eram capturadas na pilha de erros. Funções assíncronas suspensas são armazenadas na fila de callbacks do loop de eventos, não na pilha de chamadas, portanto a pilha de erros não contém a função assíncrona. Para resolver esse problema, o V8 fornece o recurso "async stack trace" (por padrão desde V8 v7.3) para capturar funções assíncronas na pilha de erros. ([v8 blog], [v8 docs])

Closure de Elemento de Resolução do Promise.all

"Promise.all Resolve Element Closure" é uma função auxiliar para resolver as promessas de entrada na função Promise.all. A função Promise.all recebe um array de promessas e retorna uma promessa que resolve quando todas as promessas de entrada são resolvidas. O papel da função é resolver a promessa de entrada e armazenar o valor de cumprimento no array de resultados.

Há 2 pontos a serem observados sobre a função:

  1. É uma função intrínseca interna (builtin) e não é diretamente acessível a partir do código JavaScript.
  2. O contexto da função é usado como um marcador para verificar se a função foi executada ou não. Ela tem FunctionContext até ser chamada, e então tem NativeContext depois de ser chamada. (v8 code)

A Vulnerabilidade

Classe do bug: Confusão de tipo entre FunctionContext e NativeContext

Detalhes da vulnerabilidade:

A vulnerabilidade pode ser desencadeada ao capturar um rastreamento de pilha assíncrono com a função "Promise.all Resolve Element Closure" já executada ou funções intrínsecas semelhantes. Neste exploit, usei a função "Promise.all Resolve Element Closure" como exemplo.

Quando um erro é lançado no código JavaScript, o V8 captura a pilha de erros da pilha e anexa os frames de pilha assíncronos da microtarefa atual [1].

CallSiteBuilder builder(isolate, mode, limit, caller);
VisitStack(isolate, &builder);

// If --async-stack-traces are enabled and the "current microtask" is a
// PromiseReactionJobTask, we try to enrich the stack trace with async
// frames.
if (v8_flags.async_stack_traces) {
    CaptureAsyncStackTrace(isolate, &builder);
}

A função CaptureAsyncStackTrace [2] percorre a cadeia de promessas e anexa o frame de pilha assíncrono de acordo com o tipo de chamada assíncrona (ex.: await, Promise.all, Promise.any).

Abaixo está o trecho da função CaptureAsyncStackTrace que lida com o caso Promise.all:

} else if (IsBuiltinFunction(isolate, reaction->fulfill_handler(),
                                Builtin::kPromiseAllResolveElementClosure)) {
    Handle<JSFunction> function(JSFunction::cast(reaction->fulfill_handler()),
                                isolate);
    Handle<Context> context(function->context(), isolate);
    Handle<JSFunction> combinator(context->native_context()->promise_all(),
                                isolate);
    builder->AppendPromiseCombinatorFrame(function, combinator);

    // Now peak into the Promise.all() resolve element context to
    // find the promise capability that's being resolved when all
    // the concurrent promises resolve.
    int const index =
        PromiseBuiltins::kPromiseAllResolveElementCapabilitySlot;
    Handle<PromiseCapability> capability(
        PromiseCapability::cast(context->get(index)), isolate);
    if (!IsJSPromise(capability->promise())) return;
    promise = handle(JSPromise::cast(capability->promise()), isolate);
} else if (

Ao percorrer a cadeia de promessas, se reaction->fulfill_handler for a função interna "Promise.all Resolve Element Closure", ele anexa o frame de combinador de promessa assíncrona à pilha de erros. Em seguida, move-se para a próxima promessa acessando function->context->capability->promise.

O problema é que a função assume que a função "Promise.all Resolve Element Closure" ainda não foi executada. Se a função "Promise.all Resolve Element Closure" já foi executada, o contexto é alterado de FunctionContext para NativeContext. Isso leva a uma confusão de tipo entre FunctionContext e NativeContext na função CaptureAsyncStackTrace.

Criando o PoC:

A estratégia para acionar a vulnerabilidade é a seguinte:

  1. Obter a função "Promise.all Resolve Element Closure" que é uma função intrínseca interna.
  2. Chamar explicitamente a função "Promise.all Resolve Element Closure" para alterar o contexto de FunctionContext para NativeContext.
  3. Definir a função "Promise.all Resolve Element Closure" como um manipulador de cumprimento de uma promessa em uma nova cadeia de promessas.
  4. Lançar um erro na cadeia de promessas e capturar o rastreamento de pilha assíncrono.

Usei o padrão de resolução síncrona de promessas para Promise.all para obter a função "Promise.all Resolve Element Closure" no nível do script JS. Peguei o padrão dos casos de teste test262.

Após chamar explicitamente a função, para acionar a vulnerabilidade, usei o código de exemplo no [documento de rastreamento de pilha assíncrono de custo zero][v8 docs] para preparar uma nova cadeia de promessas e definir a função intrínseca interna como um manipulador de cumprimento de uma das promessas.

Finalmente, quando o erro é lançado, o rastreamento de pilha assíncrono é capturado com a função "Promise.all Resolve Element Closure" já executada como manipulador de cumprimento, levando a uma confusão de tipo entre FunctionContext e NativeContext.

Aqui está o código PoC: poc.js

O Exploit

Baixar ferramenta