CVE-2024-0517分析心得

CVE-2024-0517分析心得

XiaozaYa 看雪学苑 2024-05-19 17:59

Error Fold Allocations in VisitFindNonDefaultConstructorOrConstruct
这个漏洞发生在MaglevGraphBuilder::VisitFindNonDefaultConstructorOrConstruct
函数中,考虑之前分析的CVE-2023-4069
也是发生在该函数中,所以打算把该漏洞也分析了。该漏洞主要发生在折叠分配时,未考虑内存空间分配与初始化之间的操作可能导致触发gc
,从而导致UAF。

还是从patch(https://chromium.googlesource.com/v8/v8/+/78dd4b31847ab1f5b06ef3d8742a9f3835fb6919%5E%21/#F0)入手:

可以看到补丁代码非常简单,就是添加了个ClearCurrentRawAllocation
函数:

该函数的功能为将current_raw_allocation_
指针清空。

这里补丁代码打在了TryBuildFindNonDefaultConstructorOrConstruct
函数中,其上层调用链为:

而VisitFindNonDefaultConstructorOrConstruct
其实我们在之前分析CVE-2023-4069
时就详细分析过,其主要就是处理FindNonDefaultConstructorOrConstruct
节点的,但是这里还是放一下代码分析吧:

这里会先调用TryBuildFindNonDefaultConstructorOrConstruct
尝试进行图创建:

可以看到这里我们可以将其分为快速路径和慢速路径,快速路径主要就是利用new_target.initial
直接进行对象创建,慢速路径则退回到内建函数FastNewObject
,这里我们主要看快速路径,快速路径为【1】->【2】->【3】
,而【3】
也是漏洞代码所在处,所以需要满足以下条件:

◆1、TryGetConstant(this_function)

◆2、TryGetConstant(new_target)

◆3、new_target.initial.constructor === target

这里想要到达想要到达漏洞逻辑,得绕过这三个判断,前面两个还是之前的方式插入CheckValue
节点绕过,第三个就不多说了,new_target
是派生构造函数即可,或者顶层默认构造函数也????,比较简单。

最后为分配对象的语句如下,也是漏洞代码所在处:

然后跟进BuildAllocateFastObject
,看其是如何创建对象的:

这里可以看到分配空间调用了ExtendOrReallocateCurrentRawAllocation
函数,其会尝试折叠分配:

先来说下什么是折叠分配?顾名思义,当我们在进行内存分配时,可能每次分配一小块内存,比如下面场景:

而多次分配内存可能是一个比较耗时的行为,于是编译器在静态分析阶段,会尝试进行分配折叠优化:

这里就避免了多次内存分配,但在动态类型语言中,可能会出现一些问题,比如在JavaScript
中,内存是由gc
进行管理的,在V8
中,没有被root object
直接或间接引用的对象被标记为死对象,在触发gc
时会被回收。所以考虑如下场景:

而如果此时发生分配折叠优化:

这里的问题就是在分配完空间后,只对obj1
的部分进行了初始化,而obj2
的初始化则是在后面,那么如果在初始化obj2
之前触发了gc
,那么此时current_raw_allocation_+0x10
这后面的内存就会被回收掉,如果我们此时分配对象占据这块内存,后面do something2
时,仍然使用current_raw_allocation_+0x10
,则导致UAF。
让我们回到该漏洞分析中,通过上面的分析我们可以知道:

◆在创建this
对象时,保留了current_raw_allocation_
指针,所以如果后面存在内存分配,则可能发生分配折叠

poc
如下:

这里先来看下Maglev IR

调试分析下:

this
对象的地址为0x2bca002ba4d5
,instance_size = 12
,与Maglev IR
图是吻合的:

然后程序就crash
了:

从调用栈中的函数名称可以知道,明显触发了gc
,而这里rsi
的值为一个—
地址,所以发生内存访问错误。这里我们来看下this
对象下方的内存:

这里我们换个角度看:0x2bca002ba4d5-1 = this_addr
==>o_addr = this_addr+12

看到这里其实就明白了,最开始分配了 84 字节的空间,减去this
对象占据的头 12 字节的空间,还剩下 72 字节的空间,这 72 字节其实就是包含了o
对象本身的空间和其elements
占据的空间。而这段空间在o
对象初始化之前在gc
的过程中被释放了,然后又被其它对象占据了,所以在o
初始化这段空间时就发生了UAF
,即把其它对象内容给覆盖了,所以后面的rsi
为0x2bca3ff19999 = 0x2bca00000000 + 0x3ff19999
,这里的0x3ff19999
就是1.1
的头 4 字节。

todo

笔者感觉这个漏洞想要稳定利用还是比较困难的,因为我们无法精准控制gc
,并且也无法精确控制释放后的内存被哪个对象占据。后面看看别人的expliot
吧,主要是这里的gc
搞得我很烦。

后续:

写利用写了两天,但是还是没写出来,gc
后似乎拿不到指定的内存,主要是victim
始终在this
对象的上方,不知道为啥,看参考文章说其应该在下方。然后不想在继续浪费时间了,后面有灵感了再回来写利用,暂时留个坑。失败的exploit

如有读者能够写出稳定的利用,希望不吝赐教。

通过分析该漏洞,学习到了分配折叠优化,目前已经通过复现漏洞学习了编译的如下常见优化方式:

◆常量折叠

◆公共子表达式消除

◆数组边界检查消除

◆逃逸分析

◆分配折叠

总的来说还是不错的,弥补了自己对编译器知识的匮乏,希望后面能够学到更多有趣的编译器漏洞。

参考

Google Chrome V8 CVE-2024-0517 Out-of-Bounds Write Code Execution

(https://blog.exodusintel.com/2024/01/19/google-chrome-v8-cve-2024-0517-out-of-bounds-write-code-execution/)

看雪ID:XiaozaYa

https://bbs.kanxue.com/user-home-965217.htm

*本文为看雪论坛优秀文章,由 XiaozaYa 原创,转载请注明来自看雪社区

# 往期推荐

1、Windows主机入侵检测与防御内核技术深入解析

2、BFS Ekoparty 2022 Linux Kernel Exploitation Challenge

3、银狐样本分析

4、使用pysqlcipher3操作Windows微信数据库

5、XYCTF两道Unity IL2CPP题的出题思路与题解

球分享

球点赞

球在看

点击阅读原文查看更多