0x00 漏洞原理
漏洞所在的函数
|
|
在这个函数中,使用switch case
来根据VDMA
的命令类型来调用相应的函数。
而在linux中,编译时候,编译器将会优化这一操作,将switch
修改为跳转表来进行跳转。
这边的switch优化的跳转表是一个二级跳转表,这就为TCOTOU攻击做了基础。
first:
.text:00000000000B957A cmp dword ptr [r12], 0Ah ; switch 11 cases
.text:00000000000B957F ja VBOXVDMACMD_TYPE_DEFAULT ; jumptable
00000000000B9597 default case
second:
.text:00000000000B9585 mov eax, [r12]
.text:00000000000B9589 lea rbx, vboxVDMACmdExec_JMPS
.text:00000000000B9590 movsxd rax, dword ptr [rbx+rax*4]
.text:00000000000B9594 add rax, rbx
.text:00000000000B9597 jmp rax ; switch jump
.rodata:0000000000185538 vboxVDMACmdExec_JMPS dd offset VBOXVDMACMD_TYPE_DEFAULT - 185538h
.rodata:0000000000185538 ; DATA XREF: vboxVDMACommand+1D9o
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DMA_PRESENT_BLT - 185538h ; jump table for switch statement
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER - 185538h
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DEFAULT - 185538h
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DEFAULT - 185538h
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DEFAULT - 185538h
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DEFAULT - 185538h
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DMA_NOP - 185538h
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DMA_NOP - 185538h
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DEFAULT - 185538h
.rodata:0000000000185538 dd offset VBOXVDMACMD_TYPE_DMA_NOP - 185538h
.rodata:0000000000185564 align 20h
关于TCOTOU,以下面的程序举个例子:
|
|
在file的fileExist=FALSE
时候才能调用open
读取,但是如果我们将程序视为一步一步的执行函数的时候,在if
这个check
过了后,我们假设有一分钟的时间程序才会执行open
,那么这时候有另外一个程序把file
这个指针修改为我们想要的open
的文件,这时候就相当于我们可以任意读取文件了。
而TCOTOU这个攻击技术就是在程序的这两个check
跟use
阶段之间的时间差中,用另外一个进程去修改指针,以此达到我们攻击的目的。
这样,这个漏洞的利用也就很明显了,因为是二级跳转表,同时程序的变量没有加上volatile
来标记,导致程序不会每次调用都检查变量的类型,只需要变量通过了check1时候,也就是检查是否是那11个case
时候,成功过了这个check
后,能够用另外一个进程修改掉这个变量的数值时候,并且计算可控地址跟第二级跳转表的offset
,控制程序的switch
流程跳转到可控区域后,就可以来执行我们事先布置好的shellcode
了。
另外,这个漏洞可以实现逃逸的原因是VBVA
是他在HGSMI
的基础上的,HGSMI
是通过视频的ram
缓存区实现的共享内存,vram
缓存区物理地址为0xE0000000
,所以可以通过这个缓存区去获取物理机权限。
而这个漏洞函数的地址就是在处理客户机传递给主机的视频DMA
命令的代码中。
0x01 漏洞利用
这个条件竞争的时间窗口比较小,在有着多个vcpu
的客户机时候,可以通过调整cpu
的亲和性来保证攻击程序占用的计算内存比系统本身计算内存多,以此达到能在这个条件竞争的时间窗口中稳定利用的目的。
而在寄存器中rax
由客户机控制,R8
、R12
和R15
存放的是指向崩溃期间HGSMI
缓冲区内的相关偏移量的指针。能寻找到一个jmp rax
的汇编,因此只要能控制rax
的值落到我们shellcode
的范围时候,就可以劫持程序来达到逃逸的目的。
RAX 0xdeadbeef
RBX 0x7fff8abf2538 ◂— rol byte ptr [rdx - 0xd], 1
RCX 0x7fff9c508ac0 —▸ 0x7ffff7e30000 ◂— 0x5
RDX 0xe7b
RDI 0xeeb
RSI 0x7fffdc022000 ◂— xor byte ptr [rax], al /* 0xffe40030; '0' */
R8 0x7fff89d20000 ◂— jmp 0x7fff89d20010 /* 0xb020000000eeb */
R9 0x7fff8ab06040 ◂— push rbp
R10 0x7fff9c50ad48 ◂— 0x1
R11 0x7fff9c508d48 ◂— 0x0
R12 0x7fff89d20078 ◂— 0xa /* '\n' */
R13 0xf3b
R14 0x7fff9c50d0e0 —▸ 0x7fff9c508ac0 —▸ 0x7ffff7e30000 ◂— 0x5
R15 0x7fff89d20030 ◂— 0xffffffdc0f3b0eeb
RBP 0x7fffba44dc40 —▸ 0x7fffba44dca0 —▸ 0x7fffba44dce0 —▸ 0x7fffba44dd00 —▸ 0x7fffba44dd50 ◂— ...
RSP 0x7fffba44db80 —▸ 0x7fffba44dbb0 —▸ 0x7fff9c508ac0 —▸ 0x7ffff7e30000 ◂— 0x5
RIP 0x7fff8ab26590 ◂— movsxd rax, dword ptr [rbx + rax*4]
► 0x7fff8ab26590 movsxd rax, dword ptr [rbx + rax*4]
0x7fff8ab26594 add rax, rbx
0x7fff8ab26597 jmp rax
之后,在条件竞争成功后,我们可以控制落到的伪跳转表中,寻找到能跳转到具有rwx
权限的vram
区域。(之前解释过,vram
区域也是跟客户机的共享内存区域,因此可以在这儿实现逃逸代码)
作者这边是通过VboxDD.so
区域中寻找到了一个能跳转到VRAM
区域的地方,并且把VRAM
区域其他地方设置为nop
,以保证能滑到shellcode
。
0x02 环境搭建
测试环境
- 主机系统:Ubuntu 16.04 Desktop x86_64
- 客户系统:Ubuntu 16.04 Desktop x86_64
- Vbox版本:5.2.6 r121009
安装相应版本virtualbox
根据https://www.voidsecurity.in/2018/08/from-compiler-optimization-to-code.html
原文作者使用的5.2.6
版本virtualbox
,从Virtualbox官网
下载版本号为5.2.6
的软件包,安装:
wget 'https://download.virtualbox.org/virtualbox/5.2.6/virtualbox-5.2_5.2.6-120293~Ubuntu~xenial_amd64.deb'
sudo dpkg -i virtualbox-5.2_5.2.6-120293_Ubuntu_xenial_amd64.deb
sudo apt-get -f install
安装完成:
安装虚拟机
从Ubuntu官网
下载Ubuntu 16.04 Desktop
镜像,并在virtualbox
中安装。
配置虚拟机
根据作者给出的exp
,首先需要给虚拟机分配至少2个CPU来使得条件竞争可能发生:
其次,需要将网络配置成
- 连接方式:桥接网卡
- 界面名称:(根据本机配置选择)
- 控制芯片:PCnet-FAST III(Am79C973)
- 混杂模式:拒绝
- MAC地址:(默认)
开启虚拟机,至少要保证安装好以下软件:
- gcc
- make
- git
- openssh-server
开启ssh
服务:
获取主机系统和客户系统在本地网络中的ip
地址:
并保证两者可以ping
通:
在虚拟机上,从github
上下载exp
:
git clone https://github.com/renorobert/virtualbox-cve-2018-2844
0x03 溢出过程
虚拟机开启监听6969端口(任意一个未封锁的端口)
主机系统通过ssh
连接虚拟机shell
通过虚拟机shell
编译exp
,并运行(exploit
参数填虚拟机ip
地址和虚拟机开启监听的端口)
运行exp
时,可以看到虚拟机会有一瞬间的灰屏
灰屏后,可以在虚拟机中看到有来自主机系统的连接。此时,虚拟机已逃逸,并利用shellcode
将主机的shell
传给了自己,使得虚拟机可以运行主机系统的shell
通过whoami
命令验证shell
是来自主机系统的
尝试在主机系统的桌面上添加文件
成功!
0x04 Exploit
https://github.com/renorobert/virtualbox-cve-2018-2844
0x05 Reference
[1] https://xz.aliyun.com/t/2658
[2] https://nvd.nist.gov/vuln/detail/CVE-2018-2844
[3] https://www.voidsecurity.in/2018/08/from-compiler-optimization-to-code.html