提交 cd1060ed 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!269 CVE-2020-14364安全漏洞公告

Merge pull request !269 from lijiajie128/usbCVE
+++
title = "CVE-2020-14364 QEMU USB数组越界读写问题"
date = "2020-09-01"
tags = ["Qemu", "CVE", "USB", "Buffer overflow", "Patch"]
archives = "2020-09"
author = "Jiajie Li"
summary = "关于CVE-2020-14364的漏洞描述、分析以及针对性的解决方案"
+++
# 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系统命令!
代码分析
----
```c++
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;
}
```
```c++
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大小之后,也没有对其进行更改,这使得其中被污染的数据依旧可以完成之后的越界读写功能。
影响性分析
----
1. 影响范围
QEMU 1.x 至今的QEMU的版本源代码之中均存在该漏洞,其中也包括了openEuler社区之前所使用的QEMU的代码。
2. 触发条件
触发该漏洞需要虚拟机至少连接有一个usb设备,而多数情况下libvirt会默认为虚拟机配置USB设备。
漏洞修复方法
----
根据360给出的修复方案,当检测到setup_len非法之后,将s->setup_len清零表示丢弃buffer中的USB请求,同时将USB的状态设置为SETUP_STATE_ACK,重新开始接受其他请求。补丁内容为:
```c
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软件包:
* [漏洞SA](https://cve.openeuler.org/#/infoDetails/openEuler-SA-2020-1061)
* [aach64架构qemu软件包]([qemu-4.1.0-17.oe1.aarch64.rpm](https://repo.openeuler.org/openEuler-20.03-LTS/update/aarch64/Packages/qemu-4.1.0-17.oe1.aarch64.rpm))
* [x86架构qemu软件包](https://repo.openeuler.org/openEuler-20.03-LTS/update/x86_64/Packages/qemu-4.1.0-17.oe1.x86_64.rpm)
* 升级qemu软件包
* rpm -Uvh qemu-*.rpm
* 升级完成之后查看qemu软件包的release号码,当release号大于等于17表示漏洞修复成功。
* rpm -qi qemu-4.1.0
```
Name : qemu
Epoch : 2
Version : 4.1.0
Release : 17.oe1
Architecture: aarch64
Install 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
====
1. OpenEuler社区对此漏洞采取了什么措施?
社区相关人员得知漏洞之后,立刻制作出了相对应的补丁,并且第一时间将补丁合入社区相关分支之中。
2. 如何获取该漏洞的具体复现场景?
可以参考360在ISC2020第八届互联网安全大会上的分享:
* https://isc.360.com/2020/detail.html?vid=108
* https://www.anquanke.com/post/id/215405
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册