CVE-2020-14364 QEMU USB数组越界读写问题
CVE-2020-14364 QEMU USB数组越界读写问题
漏洞描述
QEMU(quick emulator)是一款由Fabrice Bellard等人编写的免费的可执行硬件虚拟化的开源托管虚拟机。其与Bochs,PearPC类似,但拥有高速(配合KVM),跨平台的特性。QEMU通过动态的二进制转换,模拟CPU,并且提供一组设备模型,使其能够运行多种未修改的客户机OS。通过QEMU与KVM一起使用,可以实现以接近本地速度来运行虚拟机,被广泛应用到虚拟化和云计算场景中。
近日360公司发现QEMU USB控制器模拟源代码hw/usb/core.c之中存在数组越界读写的问题,攻击者可以利用该漏洞获得qemu用户的执行权限进而实现完整的QEMU虚拟机逃逸。(CVE-2020-14364)
漏洞分析
- 经过分析,该漏洞存在于USB控制器模拟代码usb_process_one中,s->setup_len未经验证就赋值可能会引入的数组越界读写的风险 。由于libvirt启动的虚拟机默认会有配置有usb设备,而任何usb控制器(如uhci,ehci,xhci)与usb设备(如usb-tablet,usb-mouse等)之间交互都会经过core.c文件中的usb_process_one函数,因此理论上只要虚拟机有使用usb设备都存在漏洞攻击的风险。 此外,usb_process_one函数中可能进入的两个分支do_parameter和do_token_setup均存在该问题,即:在检查最终需要使用的数组长度前已经提前设置了该数组长度(s->setup_len)。
- 该漏洞的影响后果非常严重,因为攻击者可以利用该漏洞实现任意地址读取和写入,从而获得qemu进程的所有权限从而实现虚拟机逃逸,实现恶意代码执行攻击。此外,如果qemu进程处于root用户组那么攻击者就可以完整获得操作系统的控制权进而执行任意linux系统命令!
代码分析
static void do_token_setup(USBDevice *s, USBPacket *p)
{
int request, value, index;
if (p->iov.size != 8) {
p->status = USB_RET_STALL;
return;
}
usb_packet_copy(p, s->setup_buf, p->iov.size);
s->setup_index = 0;
p->actual_length = 0;
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; //先对s->setup_len赋值
if (s->setup_len > sizeof(s->data_buf)) { // 后对setup_len进行合法性校验
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
return;
}
static void do_parameter(USBDevice *s, USBPacket *p)
{
int i, request, value, index;
for (i = 0; i < 8; i++) {
s->setup_buf[i] = p->parameter >> (i*8);
}
s->setup_state = SETUP_STATE_PARAM;
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; //先对s->setup_len赋值
s->setup_index = 0;
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
if (s->setup_len > sizeof(s->data_buf)) { // 后对setup_len进行合法性校验
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
return;
}
通过代码可以看到:do_token_setup以及do_parameter两个函数中,都在对s->setup_len做检查之前就设置了具体内容,并且当s->setup_len超出预定buffer大小之后,也没有对其进行更改,这使得其中被污染的数据依旧可以完成之后的越界读写功能。
影响性分析
- 影响范围 QEMU 1.x 至今的QEMU的版本源代码之中均存在该漏洞,其中也包括了openEuler社区之前所使用的QEMU的代码。
- 触发条件 触发该漏洞需要虚拟机至少连接有一个usb设备,而多数情况下libvirt会默认为虚拟机配置USB设备。
漏洞修复方法
根据360给出的修复方案,当检测到setup_len非法之后,将s->setup_len清零表示丢弃buffer中的USB请求,同时将USB的状态设置为SETUP_STATE_ACK,重新开始接受其他请求。补丁内容为:
Subject: [PATCH] hw/usb/core.c fix buffer overflow
Store calculated setup_len in a local variable, verify it,
and only write it to the struct (USBDevice->setup_len) in case it passed the
sanity checks.
This prevents other code (do_token_{in,out} function specifically)
from working with invalid USBDevice->setup_len values and overruning
the USBDevice->setup_buf[] buffer.
Store
Fixes: CVE-2020-14364
Signed-off-by: Gred Hoffman <kraxel@redhat.com>
---
hw/usb/core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 5abd128b..12342f13 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -144,6 +144,8 @@ static void do_token_setup(USBDevice *s, USBPacket *p)
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
+ s->setup_len = 0;
+ s->setup_state = SETUP_STATE_ACK;
return;
}
@@ -277,6 +279,8 @@ static void do_parameter(USBDevice *s, USBPacket *p)
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
+ s->setup_len = 0;
+ s->setup_state = SETUP_STATE_ACK;
return;
}
--
解决方案
下载openEuler发布最新的qemu软件包:
升级qemu软件包
- rpm -Uvh qemu-*.rpm
升级完成之后查看qemu软件包的release号码,当release号大于17表示漏洞修复成功。
rpm -qi qemu-4.1.0
Name : qemu Epoch : 2 Version : 4.1.0 Release : 18.oe1 Architecture: aarch64 Install category: blog
date: Mon 10 Aug 2020 04:53:20 PM CST Group : Unspecified Size : 19468602 License : GPLv2 and BSD and MIT and CC-BY Signature : RSA/SHA1, Thu 09 Jul 2020 11:52:58 AM CST, Key ID d557065eb25e7f66 Source RPM : qemu-4.1.0-14.oe1.src.rpm Build Date : Thu 09 Jul 2020 11:44:23 AM CST Build Host : obs-worker-004 Packager : http://openeuler.org Vendor : http://openeuler.org URL : http://www.qemu.org ```
FAQ
- OpenEuler社区对此漏洞采取了什么措施? 社区相关人员得知漏洞之后,立刻制作出了相对应的补丁,并且第一时间将补丁合入社区相关分支之中。
- 如何获取该漏洞的具体复现场景? 可以参考360在ISC2020第八届互联网安全大会上的分享:
- https://isc.360.com/2020/detail.html?vid=108
- https://www.anquanke.com/post/id/215405