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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2019-8601 — Эксплуатация исправленной уязвимости в JavaScriptCore | Kitploit
Инструменты/GitHubGitHub/badaccess11/cve-2019-8601
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийОбучение и ОбразованиеРазработка Полезной НагрузкиЭксплуатация Бинарных Файлов
GitHubbadaccess11/cve-2019-8601

CVE-2019-8601

Эксплуатация исправленной уязвимости в JavaScriptCore

Репозиторий
17346 лет назадЕщё не проверено

Популярное

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

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

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

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

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

Эксплуатация CVE-2019-8601

Это эксплойт для уязвимости WebKit, первоначально обнаруженной Fluoroacetate во время соревнования pwn2own в Ванкувере. Хотя я не обнаруживал эту ошибку, я написал этот эксплойт, чтобы развить свои навыки разработки эксплойтов. Оригинальное описание этого эксплойта находится здесь на сайте Zero Day Initiative. Хотя это описание очень хорошее и помогло мне понять уязвимость, оно написано с точки зрения человека, проверяющего уязвимость. Я обнаружил, что при попытке создать этот эксплойт с нуля отсутствуют некоторые ключевые детали, и я надеюсь восполнить некоторые пробелы, которые упустило описание ZDI, а также получить практические навыки по разработке сложного эксплойта с нуля.

Этапы эксплуатации

Эти этапы служат планом для достижения произвольного выполнения кода в JavaScriptCore (JSC), движке JavaScript для WebKit

  • Определить уязвимость
  • Вызвать уязвимость и аварийно завершить работу с включенным ASAN
  • Получить примитивы leakAddr и fakeObj
  • Повредить butterfly массива для получения примитивов чтения и записи
  • Использовать примитивы чтения и записи для достижения произвольного выполнения кода в JSC

Определение уязвимости

Уязвимость, которая будет эксплуатироваться, — это целочисленное переполнение, возникающее в коде, генерируемом JIT-компилятором DFG для WebKit. Это происходит конкретно в функции compileNewArrayWithSpread. Эта функция вызывается, когда код, использующий синтаксис распространения JavaScript для создания нового массива, JIT-компилируется DFG.

compileNewArrayWithSpread

Внутри JIT-компилированного кода сначала вычисляется размер массива. Это делается путём сложения длины каждого аргумента, переданного конструктору массива. При вычислении размера для каждого сложения проверяется наличие переполнения. После этого вызывается функция compileAllocateNewArray с длиной, вычисленной в этой функции.

compileAllocateNewArrayWithSize

Затем функция compileAllocateNewArray передаёт вычисленную ранее длину в emitAllocateButterfly.

emitAllocateButterfly

Функция emitAllocateButterfly затем сдвигает размер влево на 3 бита, что эквивалентно умножению на 8. Однако проверки на переполнение нет, и таким образом число, например, 0x20000001 может переполниться до 0x8.

Эта программа на C иллюстрирует данную уязвимость:

overflow-example2

overflow-example

Мы можем использовать эту уязвимость, чтобы обмануть движок JavaScript, заставив его думать, что мы выделили массив размером 0x20000001, хотя на самом деле выделили достаточно места только для 1 JSValue (8 байт). Это приведёт к получению примитива вне границ (OOB) для чтения и записи (R/W), который затем можно использовать для достижения произвольного чтения/записи и в конечном итоге удалённого выполнения кода (RCE).

  • Определить уязвимость

    Вызов уязвимости с помощью ASAN

Чтобы подтвердить наличие чтения за пределами границ, мы попытаемся вызвать эту уязвимость в сборке JSC с санитайзером адресов (ASAN).

Для этого из каталога WebKit можно выполнить следующие команды:```bash Tools/Scripts/set-webkit-configuration --asan Tools/Scripts/build-jsc --jsc--only --debug

Это создаст отладочную сборку JSC с включенным ASAN, что позволит нам проверить, удалось ли успешно вызвать уязвимость. Вот первая версия exploit.js```javascript
function jitMe(array){
  return [...array]
}

let dummy = [1.1]
for(let i = 0; i < 200; i++){
  jitMe(dummy);
}

let a = []

let len = 0x20000001                                                                     

for(let i = 0; i < len; i++){
  a[i] = 1.1 
}

jitMe(a)

При запуске я получаю следующую ошибку:

Program terminated with signal SIGKILL, Killed. The program no longer exists.

Моё предположение было, что при попытке выделить такой большой массив потребляется слишком много памяти. Чтобы подтвердить это, я добавил точку останова в JIT-код, вызвав m_jit.breakpoint() внутри compileNewArrayWithSpread, что добавляет инструкцию int3 в JIT-код.

После добавления точки останова я обнаружил, что она не срабатывает, и тогда решил протестировать длину 0x20001. Затем я понял, что код даже не компилируется, поэтому я добавил больше итераций для активации компилятора DFG.```javascript function jitMe(array){ for(let i = 0; i < 0x4000; i++){ let x = 1 + 1 } return [...array] }

let dummy = [1.1] for(let i = 0; i < 60; i++){ print(i) jitMe(dummy); }

let a = []

let len = 0x20000001

for(let i = 0; i < len; i++){ a[i] = 1.1 }

jitMe(a)

Тестирование программы как есть всё равно приводит к SIGKILL, однако при тестировании с меньшей длиной точка останова срабатывает. На данный момент мне всё ещё кажется, что у JSC заканчивается память при попытке обработать этот огромный массив.

Чтобы справиться с этим, я решил выделить меньший массив `a`, а затем использовать синтаксис spread, чтобы применить его несколько раз при создании повреждённого массива, что привело к следующему exploit.js```
function jitMe(array){
  for(let i = 0; i < 0x4000; i++){
    let x = 1 + 1
  }
  return [...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array]
}

let dummy = [1.1]
for(let i = 0; i < 100; i++){
  print(i)
  jitMe(dummy);
}

let a = []

let len = 0x20000010 / 0x10

for(let i = 0; i < len; i++){
  a[i] = 1.1
}

jitMe(a)

С помощью этого кода мы смогли достичь точки останова без SIGKILL! Как это часто бывает, исправление одной проблемы выявляет другую, и вместо этого мы получили SIGABORT... Используя команду gdb bt, мы видим, что была вызвана operationNewArrayWithSize, которая вызвала create.backtrace1

Кажется странным, что наш JIT-код вызывает operationNewArrayWithSize, и, вероятно, JIT-коду пришлось по какой-то причине перейти на медленный путь к движку JavaScript.

slowcases

В compileAllocateNewArrayWithSize мы видим, что действительно есть выход в operationNewArrayWithSize. Затем нужно выяснить, почему именно мы выходим на медленный случай.

В compileNewArrayWithSpread мы видим, что shouldConvertLargeSizeToArrayStorage установлен в false, и этот медленный путь не будет включён в скомпилированный код.compileNewArrayWithSpread2

Следовательно, логично, что медленный путь срабатывает где-то внутри emitAllocateJSObject

emitAllocateJSObject

emitAllocateJSObject вызывает emitAllocateJSCell, который, в свою очередь, вызывает emitAllocate.

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