车联网开源组件BusyBox漏洞分析及复现(CVE-2022-30065)

固件安全
2023-02-22 11:04
99181

背景

近日,国内多家安全实验室检测到了针对于智能网联汽车中使用都开源项目busybox漏洞,国外在2022年5月份报告了此漏洞,目前已经发布的CVE信息如下,信息中指出Busybox1.35-x版本中,awk应用由于use after free导致拒绝服务漏洞或可能获取代码执行权限。

image.png

漏洞原理

根据CVE发布信息公告来看,该漏洞属于堆溢出漏洞,具体漏洞类型为use after free。简单来说,use after free漏洞的形成过程如下,如果我们申请一块内存然后释放后,此时重新申请一块相同大小的内存,操作系统为了内存空间的管理方便,会将上一次释放掉的内存重新分配给我们。此时上一个申请的指针没有被清空,而且重新给内存赋值的话,就会影响第二次申请内存中的内容。use after free的本质为俩个指针同时指向同一块内存,而当一个chunk被free后,其中该chunk中的数据具有部分结构的控制作用,使用另一个指针修改控制结构的数据,程序控制流就会被改变。

示例如下,在下图源码中,我们使用指针chunk1指向了malloc分配了0x10字节的内存,随后在内存中拷贝"test1"字符串到内存中,此时打印出来的chunk1地址为0x8c71e260,里面的内容为test1。随后我们释放掉chunk1,此时使用chunk2指针指向malloc重新分配的0x10字节,然后在chunk2内存中写入"test2"字符串,打印出来chunk2的地址也是0x8c71e260。这时如果我们向chunk1指针指向的内存中写入"test3"字符串,打印chunk2里面的内容,我们就会发现明明没有修改chunk2的内容,但是打印时chunk2里面的内容却变了。

image.png

知道了漏洞的大概类型后,我们便可以进行简单分析。首先在busybox官网(https://busybox.net/downloads/)中,下载1.35.0版本和最新的1.36.0版本。根据CVE发布信息我们得知是awk应用程序存在漏洞,所以我们直接使用vimdiff比较俩个版本的awk.c文件。在vimdiff的比较中,我们发现在evaluate函数中的case XC(OC_MOVE)中进行了补丁更改。

image.png

打开1.35.0版本awk.c文件中未经patch处的对应代码块,该代码块位于evaluate函数中,在该case分支下,出现了CVE公告中提到的漏洞函数copyvar。由于此时我们对整个程序的架构和执行流程还不太清楚。我们先简单跟一下可能具有漏洞的具体情况,堆溢出的漏洞一般都发生在*alloc或free函数附近。use after free漏洞一般在free函数居多,我们接下来跟流程重点关注一下free函数。

image.png

进入查看发现clrvar对第一个参数进行操作,随后使用handle_special函数对dest进行处理。进入查看发现clrvar函数调用free函数对内存进行了释放。

image.png

上面的俩个函数都用到了var结构体,结构体定义如下:

image.png

接下来返回awk_main函数简单观察一下执行流程。发现程序首先进行一系列设置,指定了标准输入输出,随后使用awk_getline获取用户输入,并循环使用evaluate函数进行处理。

image.png

在evaluate函数中,首先调用nvalloc分配了2个var大小的堆内存。然后将该指针命名为了TMPVAR0。随后根据传入的op结构体信息循环处理。在循环处理中又使用switch case分支处理,在XC(OC_MOVE)中调用了我们分析的copyvar函数。

image.png

根据前面的流程分析和patch后的代码判断,如果我们输入数据可以控制L.v的指针指向tmpvars(TMPVAR0),那么这时用户修改的指针和系统自动分配的tmpvars都指向同一块内存,而在case XC(OC_MOVE)中,如果当其中一个指针指向的chunk被释放,而另一个指针指向chunk的内存继续使用时。修改被释放chunk的内存数据时,就会破坏free chunk list,从而导致堆溢出漏洞的产生。

漏洞分析

由于busybox多平台原因,为了方便调试,这里我选用靶场linux操作机进行操作。动态调试过程如下,在gdb调试后下断,并attach进程,断点信息如下。

image.png

直接按c运行,程序要求我们输入字符串,这里随意输入

image.png

程序直接断在了call free处,观察到RDI为空,我们不用管它。查看堆栈回溯发现程序是由awk_getline函数调用进行的,这里就是前面分析中awk_getline函数获取用户输入。

image.png

堆空间堆块排布信息如下,可以看到我们输入的"foo"字符串,堆内存结构此时还没有被破坏,我们继续往下调试。

image.png

调试过程中,释放的堆块信息比较复杂,我们使用bins命令查看当前free chunk list。

image.png

运行到了evaluate函数处,这里便是源码中使用nvalloc(xzalloc)函数分配tmpvars的堆内存。

image.png

这里直接断在了case XC(OC_MOVE)里面的copyvar函数,copyvar的第一个参数为L.v,第二个参数是R.v。这里L.v已经被修改成了tmpvars的指针,这样俩个指针同时指向了tmpvars的内存,后续会调用free函数进行释放。

image.png

si进入copyvar函数,运行到call clrvar处,这里的rdi即传入第一个参数的L.v的地址。clrvar会调用free函数进行释放。

image.png

运行后进入handle_special函数,后续流程较为复杂,直接在漏洞触发点getvar_i处下断点。运行后,断点停在了call getvar_i函数,我们跟入分析。

image.png

在getvar_i函数中,对0x55555585caa0指针指向chunk进行了修改(v->type)。

image.png

此时getvar_i函数中处理的v->type即为tmpvars free chunk的控制结构,函数这里直接对其进行了处理,导致堆结构的改变。

image.png

此时0x55555585caa0中数据0x55555585caf0被修改,原来的free chunk list已经被破环,修改后0x55555585caa0指向的下一个free chunk被修改为0x55555585c9f0。

image.png

当我们进行第二次输入字符串时,会继续对堆空间进行申请和释放。当申请到0x55555585c9f0地址处的chunk时,会对堆空间进行数据更改,导致程序崩溃。

image.png

0x55555585c9f0地址处已经被申请,此时chunk结构被破坏,gdb插件已经无法识别剩余内容空间的堆结构。

image.png

堆块标识被清空,所以无法找到对应堆块的起始位置,所以插件识别不了。

image.png
当继续往下调试时,程序崩溃。

image.png

下图为另一个poc测试出现的情况,这里面的topchunk标识被修改为0,当堆继续申请和释放时,程序同样会崩溃。

image.png

漏洞复现

下载好busybox后直接使用源码进行编译安装

make menuconfig
make
make install

image.png

使用已公开的poc进行测试,发现触发了漏洞。

image.png

由于busybox在不同系统中的编译使用,且不同系统编译后程序开启的保护也不同,那么这里获取执行权限的方式也不同。

总结

整体分析下来,该漏洞利用性不大,且获取执行权限的利用方式较为复杂,但因为其可能具有获取执行权限的情况,请使用busybox漏洞版本的各位用户尽快升级到最新版本。

-end

参与评论

0 / 200

全部评论 1

zebra的头像
学习大佬思路
2023-03-19 12:15
投稿
签到
联系我们
关于我们