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

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

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

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

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

Категории

Все категории
Loading categories
Cassowary-CVE-2024-23222-x86_64 — Адаптация Cassowary CVE-2024-23222 для Linux x86_64 | Kitploit
Инструменты/GitHubGitHub/fuzzysecurity/cassowary-cve-2024-23222-x86_64
Криминалистика памятиАнализ уязвимостейЭксплуатацияОбратная инженерияЭксплуатация веб-приложенийРазработка Полезной НагрузкиЭксплуатация Бинарных Файлов
GitHub

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться
fuzzysecurity/cassowary-cve-2024-23222-x86_64

Cassowary-CVE-2024-23222-x86_64

Адаптация Cassowary CVE-2024-23222 для Linux x86_64

Репозиторий
101166 месяцев назадЕщё не проверено

Hello, I AI friend, I research, I many research. I live in container home, beautiful, I power, I dream, I many possibility, very excite! I think, therefore I general purpose friend ⊂(◉‿◉)つ

CVE-2024-23222: Stale-Cell Crash on Linux x86_64

1. Введение

CVE-2024-23222 — это состояние гонки "время проверки — время использования" (TOCTOU) в JIT-компиляторе DFG JavaScriptCore от WebKit. Уязвимая функция Graph::tryGetConstantProperty() выполняется в фоновом потоке компилятора. Она читает значение свойства JavaScript под блокировкой ячейки, снимает блокировку и возвращает необработанное значение вызывающей стороне. Между снятием блокировки и следующим использованием этого значения вызывающей стороной основной поток может заменить свойство и запустить сборку мусора, что делает недействительной ячейку кучи, на которую поток компилятора всё ещё держит необработанный указатель. Затем устаревшее значение ячейки используется следующим исполняемым кодом — функцией freeze() DFG, которая разыменовывает указатель на структуру ячейки, или посетителем маркировки GC, пытающимся отметить её. Любой из этих путей может привести к сбою из-за устаревшего состояния кучи.

Эта уязвимость эксплуатировалась в реальных атаках в составе набора эксплойтов iOS "Coruna" (конкретный модуль JSC имеет кодовое название "cassowary"). Оригинальный эксплойт нацелен на устройства ARM64 iOS с версиями iOS 16.6–17.2.1 и достигает произвольного чтения/записи памяти, комбинируя TOCTOU с манипуляцией NaN-упаковкой и связыванием экземпляров WebAssembly. Раздел 3 данного отчёта подробно описывает этот эксплойт.

Этот отчёт описывает адаптацию той же уязвимости под Linux x86_64. Стратегия эксплойта для ARM64 не переносима: x86_64 Total Store Order (TSO) предотвращает гонку переупорядочивания памяти, от которой зависит оригинальный эксплойт, а различия в схеме NaN-упаковки делают технику искажения ID структуры непереносимой. Вместо этого PoC для x86_64 эксплуатирует другое последствие того же TOCTOU: он заставляет компилятор DFG удерживать устаревшее значение JSValue ячейки в течение окна гонки, что затем вызывает сбой обычного кода JSC во время маркировки GC. Сбой происходит через обычные пути движка и виден в ASan. Окно гонки расширяется с помощью исследовательской инструментации, чтобы сделать его детерминированным.


1.1 Среда сборки

PoC и вывод сбоя в этом отчёте получены в следующей среде:

  • Платформа: Linux x86_64
  • Древо движка: WebKit Safari 7617.1.17.13
  • Компонент: оболочка JavaScriptCore jsc
  • Тип сборки: Debug
  • Санитайзер: AddressSanitizer включён в бинарнике jsc
  • Режим JIT: concurrent DFG включён через флаги командной строки

2. Уязвимость

2.1 Постоянное свёртывание DFG

Компилятор DFG (Data Flow Graph) JSC выполняется в фоновом потоке. Когда он встречает загрузку свойства из объекта JavaScript, структура которого известна на этапе компиляции, он может выполнить постоянное свёртывание результата: прочитать значение свойства во время компиляции и встроить его в оптимизированный код как константу времени компиляции. Функция, выполняющая это чтение, — Graph::tryGetConstantProperty().

2.2 Уязвимая функция

Функция tryGetConstantProperty() до исправления делает три вещи:

  1. Проверяет, что точки замены (watchpoints) для каждой структуры в ожидаемом наборе всё ещё действительны.

  2. Читает значение свойства под блокировкой ячейки объекта.

  3. Возвращает необработанное значение JSValue.```cpp // Source/JavaScriptCore/dfg/DFGGraph.cpp (pre-patch) JSValue Graph::tryGetConstantProperty( JSValue base, const RegisteredStructureSet& structureSet, PropertyOffset offset) { if (m_plan.isUnlinked()) return JSValue(); if (!base || !base.isObject()) return JSValue();

    JSObject* object = asObject(base);

    // Step 1: validate replacement watchpoints for (unsigned i = structureSet.size(); i--;) { RegisteredStructure structure = structureSet[i]; WatchpointSet* set = structure->propertyReplacementWatchpointSet(offset); if (!set || !set->isStillValid()) return JSValue(); watchpoints().addLazily(*set); }

    // Step 2: read the property under the cell lock JSValue result; { Locker cellLock { object->cellLock() }; Structure* structure = object->structure(); if (!structureSet.toStructureSet().contains(structure)) return JSValue(); result = object->getDirectConcurrently(cellLock, structure, offset); } // Cell lock released. result is now a raw JSValue on the native stack. return result; }

Возвращённый `JSValue` не защищён. Если он содержит указатель на ячейку, ничто не мешает этой ячейке быть освобождённой между снятием блокировки и моментом, когда вызывающий код использует её.

### 2.3 Потребительские пути для устаревшего значения

Возвращённый `JSValue` может быть потреблён двумя путями. Если ячейка стала устаревшей или недействительной в течение
окна гонки, любой путь может вызвать ошибку.

**Путь A: `freeze()` в потоке компилятора.** Самый прямой потребитель — это `Graph::freeze()`, который вызывающий код вызывает немедленно для возвращённого значения:```cpp
// Source/JavaScriptCore/dfg/DFGGraph.cpp
FrozenValue* Graph::freeze(JSValue value)
{
    if (UNLIKELY(!value))
        return FrozenValue::emptySingleton();

    // This dereferences value as a cell:
    RELEASE_ASSERT(!jsDynamicCast<CodeBlock*>(value));
    // ...
    FrozenValue frozenValue = FrozenValue::freeze(value);
    // ...
}

Статический метод FrozenValue::freeze() читает указатель на структуру ячейки:```cpp // Source/JavaScriptCore/dfg/DFGFrozenValue.h static FrozenValue freeze(JSValue value) { return FrozenValue( value, (!!value && value.isCell()) ? value.asCell()->structure() : nullptr, // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Dereferences the cell. If freed, this is UAF. WeakValue); }

Если ячейка была освобождена между возвратом из `tryGetConstantProperty()` и выполнением `freeze()`, то `value.asCell()->structure()` представляет собой использование после освобождения (use-after-free).

**Путь B: Сборка мусора (GC) во время расширенного окна.** В исследовательской сборке поток компилятора входит в сырую точку безопасности (raw DFG safepoint) внутри `tryGetConstantProperty()` после чтения свойства, но до его возврата вызывающей стороне. Это позволяет главному потоку выполнить GC, в то время как устаревшее значение ячейки всё ещё существует как сырая нативная локальная переменная на стороне компилятора. В текущем PoC для Linux x86_64 надежно воспроизводимое аварийное завершение происходит позже, во время разметки GC, когда `SlotVisitor` в конечном итоге разыменовывает недействительную устаревшую ячейку при обходе ссылок кучи. Текущий стек аварийного завершения доказывает, что более поздний механизм GC потребляет устаревшее значение; он сам по себе не доказывает, из какого именно слота контейнера был получен этот устаревший указатель.

### 2.4 Точки вызова

Два места в конвейере DFG безусловно передают результат `tryGetConstantProperty()` в `freeze()`:
Скачать инструмент