DARK中文网
  • 首页
  • American pepe中文网
  • 首页
  • American pepe中文网

栏目分类

  • American pepe中文网

热点资讯

  • 华尔街大多头预测:年底前标普500指数升至6300点,比特币突破10万美元
  • 突发!新冠病毒新变体突袭,FLiRT正在全美国迅速传播,多国告急!世卫组织紧急出手
  • chrome v8漏洞CVE-2023-2033分析-二进制漏洞-看雪-安全社区|安全招聘|ka
  • 小品词构成的动词短语
  • 图表全释:十年来A股曾经的十倍股现在怎么样了?

American pepe中文网

chrome v8漏洞CVE-2023-2033分析-二进制漏洞-看雪-安全社区|安全招聘|kanxue.com
发布日期:2025-01-04 16:29    点击次数:155
chrome v8漏洞CVE-2023-2033分析 作者: coolboy 前言 这篇文章比较深入的介绍了v8漏洞CVE-2023-2033成因、原理、利用细节以及v8 sandbox对利用的缓解效用。介绍过程中会提及较多源码片段,结合源码享用风味更佳。与此同时提供了原创完整可用exp,这是笔者在其他地方没有找到的。这是一个系列文章,本文是第六篇。前五篇: 第一篇:chrome v8漏洞CVE-2021-30632浅析 第二篇:chrome v8漏洞CVE-2021-37975浅析 第三篇:chrome v8漏洞CVE-2023-3420浅析 第四篇:chrome v8漏洞CVE-2020-16040浅析 第五篇:chrome v8 issue 1486342浅析 POC 先试为快。 编译v8 POC 执行./out/x64.release/d8 poc.js将会得到一个sh(由于并行编译,成功率80%左右),如下: 漏洞分析 有漏洞的版本执行这段代码将得到hole,而打过补丁的版本将得到undefine。hole是什么呢?hole是一个v8实现的内部的值,不应该暴露给js。如果暴露给js,那么将会导致漏洞。更多hole的解释,参考can-anyone-explain-v8-bytecode-ldathehole。下面,将详细分析hole是如何泄露到js中的。 globalThis 什么是globalThis?完整信息可以参考MDN文档globalThis。简单的讲,它是一个对象,代表了一个集合,这个集合包含了所有的全局对象:属性、函数、变量等。申明一个全局变量obj,它也可以通过globalThis.obj来访问,两者是等价的。 Error Error.captureStackTrace(globalThis) 这是一个非标准的JS api的调用,为globalThis对象添加stack属性。调用console.log(globalThis.stack)将会打印调用堆栈。Error.prepareStackTrace是一个回调函数,在globalThis.stack发生修改操作的时候被调用。参考preparestacktrace hole泄露过程 代码1处调用defineProperty对globalThis.stack属性进行修改,此时优先调用prepareStackTrace回调函数,当回调函数执行完之后继续执行defineProperty操作。 调用deleteProperty,删除回调函数,防止代码2处调用时对stack做修改时进行无限递归。 调用Reflect.deleteProperty,将stack属性从globalThis对象中移除。Error.captureStackTrace创建属性时,默认属性的configurable值为true,因此此处deleteProperty可以成功。 调用Reflect.defineProperty又重新定义stack属性,此时stack属性的configurable值被重新赋值为false,value被赋值为1. stack = undefined; stack的value从1被定义为undefined。 代码3处重复调用rGlobal,触发jit优化,将对rGlobal函数做优化。 sleepSync(2000); 睡眠2秒钟 此时回调函数执行完毕,接着执行1处代码后续操作,将globalThis.stack的configurable设置为true。 4处代码得益于1处代码修改了configurable为true,因此可以delete成功。 4处代码delete并没有导致rGlobal解优化,此时globalThis.stack为hole,于是h0le[0]变为了hole泄露给js了。上述过程中,看似平平无奇,实则内藏玄机。还有下面几个问题需要回答。 globalThis可以替换成其他全局对象吗? 答案是不能。将globalThis替换成global_obj,上述代码将打印undefined。为什么呢?我们对比查看两份代码rGlobal的jit汇编。 左右两边分别对应globalThis及global_obj。 globalThis.stack jit优化之后,变成了对PropertyCell的直接访问,PropertyCell对应属性的值,直接就是stack的值。 global_obj.stack jit优化之后,变成了LoadICTrampoline函数调用,这个函数的作用是对global_obj对象,进行stack属性索引。 这两者的差别将导致4处代码delete globalThis.stack执行之后,一个返回hole,另外一个返回undefinedglobalThis和global_obj,两者都是全局对象,为什么导致了jit优化代码的不同呢?经过一番调试了,找到了原因。 ReduceNamedAccess 函数调用发生在jit编译的InliningPhase阶段(关于更多jit知识,可以查看前面几篇系列文章,或者其他公开文档)。参考注释可知,节选出来的代码做了一个优化,对于xxx.stack这样的属性访问,如果xxx是一个global proxy,即globalThis,那么globalThis.stack访问将被转换为对stack全局变量的直接访问。而global_obj.stack进不了这个分支,将进入到其他分支,被优化成对LoadICTrampoline函数的调用。 2处代码的作用是什么? 这两行代码产生了下面的效用: 给globalThis对象增加了stack属性 stack属性的configurable值为false stack属性的value为1 将stack赋值为undefined,由于undefined(NULL)和1(SMI)属于不相同的类型,于是stack的cell_type为PropertyCellType::kMutable。(关于这部分知识,参考CVE-2021-30632关于PropertyCellType的介绍)总结一下,给globalThis对象增加stack属性,同时stack的configurable为false,且value类型为kMutable。这都是为了通过上面调用的ReduceGlobalAccess函数的检查,见下面代码: 满足“stack的configurable为false,且value类型为kMutable”这两个条件才不会进入到dependencies()->DependOnGlobalProperty的调用,而这个函数的作用是,当stack的值发生变化时,将对当前函数进行解优化。回顾前面的代码: 至此,我们可以回答这个问题了。2处代码的作用就是给stack设置一个合适的值,使得DependOnGlobalProperty函数不被调用,从而在delete globalThis.stack执行的时候不对rGlobal函数做解优化(deopt)。 通过给d8传递参数--trace-deopt可以观察到解优化的日志,可以自行修改configurable为true进行观察。 1处代码执行时stack的configurable已经被回调置为false,为何configurable还能被修改为true? 如上代码,delete obj.abc和第二次Reflect.defineProperty调用都会失败。因为configurable已经被置为false了。那么为什么1处代码在configurable已经为false的情况下,对configurable置为true仍然可以成功呢? 通过lldb调试d8,得到下面的调用堆栈: GetPropertyDescriptorWithInterceptor函数获取了当前stack属性,存放在desc中。 Object::GetProperty(it).ToHandle 函数调用将触发Error.prepareStackTrace回调。 也就是说执行回调前,v8已经将先前的stack属性缓存在desc变量中了。 GetOwnPropertyDescriptor 获取先前的stack属性,存入current变量,并且调用Error.prepareStackTrace注册的回调 ValidateAndApplyPropertyDescriptor通过current做configurable是否为true的判断,从而决定configurable是否可以修改总结一下: Error.captureStackTrace定义了stack,此时stack默认configurable为true。 调用Reflect.defineProperty 意图修改configurable为true。下面将Reflect.defineProperty的内部动作进一步拆解。 此时优先获取configurable的值,并且缓存进current变量。 然后执行回调Error.prepareStackTrace,将configurable修改为false(目的是为了优化代码不被解优化)。 根据current变量进行判断,current变量中configurable为true,因此可以做任意修改。 最后Reflect.defineProperty将configurable从false修改为true。 sleepSync(2000)的作用是什么,可以不要或者睡眠其他时间吗? 在d8的release编译模式下,jit编译是同步进行的。rGlobal循环1万次,在某次(比如6000)执行之后,v8会开启一个新的线程对rGlobal函数进行编译,编译成功之后通知主线程,下一次执行就直接执行编译之后的代码。这个时机可能是9000次,也有可能到程序结束也得不到执行。因此这里睡眠2秒钟或者更长时间,等待编译结束。保证下一次执行的时候,是执行的jit代码。 POC详解 POC介绍一下跟此漏洞相关的地方。剩余的部分跟对象内存布局相关,可以通过

上一篇:小品词构成的动词短语
下一篇:图表全释:十年来A股曾经的十倍股现在怎么样了?
    友情链接:

Powered by DARK中文网 @2013-2022 RSS地图 HTML地图

Copyright Powered by365建站 © 2013-2024