CVE-2018-4338: Triggering an Information Disclosure on macOS Through a Broadcom AirPort Kext

October 24, 2018 | The ZDI Research Team

Moving from userland to executing code with elevated permissions is key to a successful exploit. This is true for Pwn2Own entries, TIP submissions, or live malware. To escape a modern sandbox, attackers and researchers need to know quite a bit about memory layout. Otherwise, their exploits are left randomly spraying the heap in hopes of finding the right memory address. This is one reason why information disclosure bugs have garnered so much attention over the last few years. While the name may lead some to believe personal information is being disclosed, it’s often detailed information about the memory layout that these exploits target.

Recently, a submission to the ZDI program showed how macOS had just this type of information disclosure vulnerability. Reported by Lee @ SECLAB, Yonsei University, the flaw exists within the handling of the Broadcom AirPort kext. If you’re not familiar with them, kext files (short for kernel extension) serve as drivers for macOS and are analogous to DLLs in Windows. Now that a patch is available, Lee’s write-up and analysis deserves a closer look.

The Setup

This specific vulnerability is only available on systems with Wi-Fi is enabled. While this machine state is largely ubiquitous, there are times where it may be disabled. To get around this, it is possible to use a script to turn on Wi-Fi. An attacker could use the dlsym function to /System/Library/PrivateFrameworks/Apple80211.framework/Apple80211, which yields Apple80211Open, Apple80211BindToInterface, and Apple80211Close functions. You can trigger core function with the following flow:

Picture1.png

The Vulnerability

Put simply, this vulnerability allows an attacker to obtain a kernel address for privilege escalation in the Apple OS X local environment. The root cause resides in AirPort.BrcmNIC.kext, which does not check the input value and causes an Out Of Bounds (OOB) read.

The bug occurs because the setOFFLOAD_NDP function does not check the input value. This means the stack value by OOB Read is stored in the ol_nd_hostip variable. Attackers can read the ol_nd_hostip variable by using getOFFLOAD_NDP function.

The Exploit

Since we know the bug occurs in the AirPort_BrcmNIC::setOFFLOAD_NDP function, we just need to get the value stored in the ol_nd_hostip variable. Looking again at the offending function:

As you can see from the setOffloadNdp function, inp is a local variable of this function. The old_nd_hostip variable stores value up to 0x40 bytes in size, and if the value is 0, correction is possible. Therefore, since the return address is inp + 0x68, it is saved by running the loop seven times. You can then leak the stack value using the getOffloadNdp function.

When executed, the Proof of Concept (PoC) code should produce the following output:

Conclusion

If you’re looking to test this for yourself, the PoC should work on macOS 10.13 and prior. While this can’t be used to execute code on its own, an attacker can leverage this in conjunction with other vulnerabilities to execute code in the context of the kernel. It also shows how finding the right memory location is an important part of an exploit chain.

We’ll be back with other great submissions in the future. Until then, follow the team for the latest in exploit techniques and security patches.