Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2023-6702 — Уязвимость 1-day в Chrome Renderer: RCE через путаницу типов в асинхронном стеке вызовов (участие v8ctf) | Kitploit
Инструменты/GitHubGitHub/kaist-hacking/cve-2023-6702
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийCTFОбучение и ОбразованиеЭксплуатация Бинарных Файлов
GitHubkaist-hacking/cve-2023-6702

CVE-2023-6702

Уязвимость 1-day в Chrome Renderer: RCE через путаницу типов в асинхронном стеке вызовов (участие v8ctf)

Репозиторий
86972 лет назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Chrome Renderer 1day RCE через Type Confusion в Async Stack Trace (CVE-2023-6702)

Краткое описание

Эта уязвимость позволяла удаленному злоумышленнику выполнить произвольный код в процессе рендеринга Chrome.

В коде обработки асинхронных стековых трасс была недостаточная проверка типа. Это приводило к путанице типов (type confusion) между FunctionContext и NativeContext, что вызывало незаконный доступ к значению JSGlobalProxy->hash. С помощью heap spraying злоумышленник мог внедрить поддельный асинхронный кадр стека и построить примитив fakeobj. Используя примитив fakeobj, злоумышленник мог добиться произвольного выполнения кода в процессе рендеринга Chrome.

Вы можете ознакомиться с нашими слайдами с TyphoonCon 2024.

Поставщик / Продукт / Версия

  • Google Chrome
  • Уязвимые версии: до 120.0.6099.109
  • Исправленная версия: 120.0.6099.109

Хронология

  • 2020-05-13: Внесена ошибка - [Promise.any] Implment async stack traces for Promise.any
  • 2023-11-10: Сообщение об ошибке - Security: V8 Debug check failed: LAST_TYPE >= value
  • 2023-11-15: Исправление - [promises, async stack traces] Fix the case when the closure has run
  • 2023-12-12: Уведомление - https://chromereleases.googleblog.com/2023/12/stable-channel-update-for-desktop_12.html
  • 2024-01-12: Отправка v8CTF <-- Время, когда мы работали над этой уязвимостью
  • 2024-02-23: Раскрыт отчет об ошибке

Предыстория

Async Stack Trace

Асинхронность — одна из важнейших функций JavaScript. В прошлом было трудно отлаживать асинхронный код с помощью стеков ошибок, потому что асинхронные функции не захватывались в стеке ошибок. Приостановленные асинхронные функции хранятся в очереди обратных вызовов цикла событий, а не в стеке вызовов, поэтому стек ошибок не содержит асинхронной функции. Чтобы решить эту проблему, V8 предоставляет функцию "async stack trace" (по умолчанию начиная с V8 v7.3) для захвата асинхронной функции в стеке ошибок. ([v8 blog], [v8 docs])

Promise.all Resolve Element Closure

"Promise.all Resolve Element Closure" — это вспомогательная функция для разрешения входных промисов в функции Promise.all. Функция Promise.all принимает массив промисов и возвращает промис, который разрешается, когда все входные промисы будут разрешены. "Promise.all Resolve Element Closure" является обработчиком разрешения каждого входного промиса в функции Promise.all. Роль этой функции — разрешить входной промис и сохранить значение выполнения в результирующем массиве.

Есть два важных момента об этой функции:

  1. Это встроенная функция (intrinsic builtin), и она недоступна напрямую из JavaScript-кода.
  2. Её контекст используется как маркер для проверки, была ли функция выполнена. До вызова она имеет FunctionContext, а после вызова — NativeContext. (код V8)

Уязвимость

Класс ошибки: Путаница типов (type confusion) между FunctionContext и NativeContext

Детали уязвимости:

Уязвимость можно вызвать, захватив асинхронный стек вызовов с уже выполненной функцией "Promise.all Resolve Element Closure" или аналогичной встроенной функцией. В этом эксплойте в качестве примера используется функция "Promise.all Resolve Element Closure".

Когда в JavaScript-коде возникает ошибка, V8 захватывает стек ошибки из стека и добавляет асинхронные кадры стека из текущей микрозадачи. [1]

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

// Если --async-stack-traces включены и "текущая микрозадача" является
// PromiseReactionJobTask, мы пытаемся обогатить стек ошибок асинхронными кадрами.
if (v8_flags.async_stack_traces) {
    CaptureAsyncStackTrace(isolate, &builder);
}

Функция CaptureAsyncStackTrace [[2]] просматривает цепочку промисов и добавляет асинхронный кадр стека в соответствии с типом асинхронного вызова (например, await, Promise.all, Promise.any).

Ниже приведён фрагмент функции CaptureAsyncStackTrace, который обрабатывает случай 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);

    // Теперь заглядываем в контекст resolve element функции Promise.all(),
    // чтобы найти promise capability, который разрешается, когда все
    // одновременные промисы будут разрешены.
    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 (

При просмотре цепочки промисов, если reaction->fulfill_handler является встроенной функцией "Promise.all Resolve Element Closure", она добавляет кадр асинхронного комбинатора промисов в стек ошибок. Затем она переходит к следующему промису, обращаясь к function->context->capability->promise.

Проблема в том, что функция предполагает, что "Promise.all Resolve Element Closure" ещё не была выполнена. Если эта функция уже выполнена, контекст меняется с FunctionContext на NativeContext. Это приводит к путанице типов между FunctionContext и NativeContext в функции CaptureAsyncStackTrace.

Создание PoC:

Стратегия для вызова уязвимости следующая:

  1. Получить функцию "Promise.all Resolve Element Closure", которая является встроенной функцией.
  2. Явно вызвать функцию "Promise.all Resolve Element Closure", чтобы изменить контекст с FunctionContext на NativeContext.
  3. Установить функцию "Promise.all Resolve Element Closure" как обработчик выполнения промиса с новой цепочкой промисов.
  4. Вызвать ошибку в цепочке промисов и захватить асинхронный стек.

Для получения функции "Promise.all Resolve Element Closure" на уровне JS-скрипта я использовал синхронный паттерн разрешения промисов для Promise.all. Я позаимствовал этот паттерн из тестовых случаев test262.

После явного вызова функции, чтобы вызвать уязвимость, я использовал пример кода из [документации по zero-cost async stack trace][v8 docs] для подготовки новой цепочки промисов и установил встроенную функцию как обработчик выполнения одного из промисов.

Наконец, когда возникает ошибка, асинхронный стек захватывается с уже выполненной функцией "Promise.all Resolve Element Closure" в качестве обработчика выполнения, что приводит к путанице типов между FunctionContext и NativeContext.

Вот код PoC: poc.js

Эксплойт

(Термины «примитив эксплойта», «стратегия эксплойта», «техника эксплойта» и «поток эксплойта» определены здесь.)

Примитив эксплойта: примитив fakeobj

Стратегия эксплойта: Для построения примитива fakeobj из ошибки путаницы типов я использовал следующую стратегию:

Скачать инструмент