Show Notes

174 - A Huawei Hypervisor Vuln and More Memory Safety

A pretty straight forward stack-based overflow in ping on FreeBSD. It is a little interesting though in that there is one caveat this is teh vulnerable code:

static void
pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
{
    u_char *cp, *dp, l
	struct ip ip;
    /* ... */
	memcpy(&l, buf, sizeof(l));
	hlen = (l & 0x0f) << 2;
	memcpy(&ip, buf, hlen);
    /* ... */
}

This code is processing the IP header of an incoming packet. Thehlen variable is the length of the complete IP header, and it is based on the lower-nibble of the first byte from the user-controlledbuf. It then copies the header into the ip structure on the stack. The problem here is that struct ip is a “naked ip header.” it does not include space for any of the IP options that could be sent. The packet length hlen reads however reflects the full size including those optional parts. So if a packet has options, they will be copied onto the stack, beyond the allocated space.

On exploitation there are a couple considerations here:

  • As a network-attached program it is most likely going to be compiled with stack canaries so the classic technique would be difficult to pull-off here. However there are a lot of items on the local stack, so there is some potential to corrupt that data.
  • ping is a setuid binary, it will run as root, however it is in a capability sandbox, so its root but only with CAP_NET_RAW. So for a local attacker, it is a minor privilege escalation. Still something to be considered about with access to raw packets they can potentially mess with traffic on the system. For a remote attacker, this code path is in the response to a ping, so the victim would need to ping a malicious machine. Its concievable, but it is definitely an ask.

An interesting vulnerability in Huawei’s security hypervisor which Huawei devices use to protect the kernel integrity. The hypervisor provides logging capability, and allows the kernel to access the log buffers via shared memory that the kernel can map into it’s address space. Inside the log buffer there’s a control structure named log_buffer_t. This structure contains a pointer to the data as well as some other important data for managing the buffer. This pointer is entirely exposed and unprotected. When the hypervisor goes to log using that pointer, an attacker can make it point into hypervisor-exclusive memory and get out of bounds write. The data is not controlled where it’ll be a log string from the HV, but it’s enough to get a foothold.

They took advantage of this OOB write by smashing the stage 2 pagetable allocator and integer underflowing the heap offset value that’s used to ensure the allocator only returns hypervisor-exclusive memory. This then allows them to get an alloc from kernel-accessible memory (the shared memory) and get complete control over a stage 2 pagetable. Once they have this, it’s a matter of remapping hypervisor code pages as writable to the kernel and patching the HV.