Full Report
In my previous blog post I dug into a general overview of the KASAN implementation in XNU. This post goes more in depth in detecting kernel uninitialized information leaks using it (no 0days dropped here :)). Kernel Information Leaks to userland are a common problem and can be used to leak confidential information or disclose kernel memory addresses which are typically used to bypass KASLR. An example of this type of vulnerability is CVE-2017-13868.
Analysis Summary
# Vulnerability: Kernel Uninitialized Information Leak Detection in XNU using KASAN
## CVE Details
- CVE ID: N/A (Focus is on a detection mechanism, mentions CVE-2017-13868 and CVE-2015-5864 as examples of the class of bug being discussed.)
- CVSS Score: N/A
- CWE: CWE-908: Use of Initialized Memory
## Affected Systems
- Products: XNU kernel (Apple operating systems using KASAN instrumentation, typically debug/development builds)
- Versions: Versions where KASAN is implemented and configured to check for leaks (specifically referencing `TYPE_LEAK` checks).
- Configurations: Requires running an instrumented kernel build with KASAN enabled, specifically setting the boot argument `kasan=0x0800` (which corresponds to `KASAN_ARGS_CHECK_LEAKS`).
## Vulnerability Description
The blog post details how the Kernel Address Sanitizer (KASAN) implementation within the XNU kernel attempts to detect uninitialized information leaks (where uninitialized memory allocated with the `KASAN_UNINITIALIZED_HEAP` pattern `0xbe` is copied to user space).
1. **Allocation Poisoning:** Kernel memory allocated via `kasan_alloc` has uninitialized regions filled with `0xbe`.
2. **Leak Check on Copyout:** During kernel-to-userland copies (e.g., via `copyout`), the `kasan_check_uninitialized` function is called upon loading data (`__asan_loadN`).
3. **Detection Logic:** This function scans the copied buffer for the `0xbe` pattern. If the number of consecutively found `0xbe` bytes (`max_count`) meets or exceeds a configurable `leak_threshold`, `kasan_report_leak` is invoked.
4. **Reporting:** Leaks are reported, potentially causing a panic if the leak size exceeds a fatal threshold or revealing memory contents (including kernel addresses, bypassing KASLR).
This post focuses on enabling and observing this built-in detection mechanism, rather than exploiting a new flaw.
## Exploitation
- Status: The described mechanism is a **detection tool**, not a vulnerability itself. The underlying vulnerability exploited is an **Uninitialized Information Leak** (e.g., CVE-2017-13868, CVE-2015-5864).
- Complexity: Varies depending on the underlying leak vulnerability, but the process of *triggering the KASAN detection* is based on reproducing the conditions of that leak.
- Attack Vector: Typically **Local** or **Sandbox Escape** (for kernel leaks), depending on the specific system call wrapper (e.g., IOConnectCallMethod) being targeted.
## Impact
The impact relates to the underlying Uninitialized Information Leak:
- Confidentiality: **High** (Kernel memory addresses can be leaked, bypassing KASLR).
- Integrity: **Low** (No direct modification implied, though configuration changes could lead to integrity issues).
- Availability: **Low** (A fatal KASAN report if `leak_fatal_threshold` is hit, leading to a kernel panic).
## Remediation
### Patches
No specific patches for the KASAN detection logic are mentioned as needed; the article discusses leveraging *existing* instrumentation. Remediation requires patching the **root cause vulnerability** (the uninitialized memory usage) that allows the leak to occur in the first place.
### Workarounds
1. **Disabling Leak Checks:** If debugging is complete, disabling the specific check via boot arguments:
* Remove `kasan=0x0800` (or corresponding bit) from `boot-args`.
2. **Standard KASAN Configuration:** Ensuring KASAN is run with appropriate settings if debugging is preferred over production deployment.
3. **Kernel Hardening:** Ensure standard protections (like KASLR) are enabled if KASAN is not being run.
## Detection
- **Required Configuration:** To activate the leak detection feature:
sudo nvram boot-args="-v keepsyms=1 debug=0x2444 kasan=0x0800 kcsuffix=kasan"
- **Detection Methods and Tools:**
* **KASAN Reporting:** Monitoring kernel logs (via `printf` in handlers or kernel panics) for messages generated by `kasan_report_leak`.
* **DTrace Scripting (Recommended for targeted hunting):** Using a DTrace script to hook into the detection routine:
dtrace
kasan::kasan_check_uninitialized:leak_detected {
printf ("kasan leak at 0x%p of size %u, offset %u leak size %u repr: %s ",arg0,arg1,arg2,arg3,stringof(arg4));
tracemem(arg0, 512);
stack()
}
* **Fuzzing:** Modifying fuzzers targeting I/O Kit or syscall interfaces to look for output containing the `0xbe` fill pattern if they interact with areas known to use potentially uninitialized buffers being copied out.
## References
- Vendor Advisories: N/A (This is an internal research mechanism being documented).
- Relevant links:
* Example of a similar class vulnerability: hxxps://bazad.github.io/2018/03/a-fun-xnu-infoleak/ (CVE-2017-13868)
* Example of a heap info leak vulnerability: hxxps://github.com/jndok/tpwn-bis/blob/master/poc-1/pwn.m#L25 (CVE-2015-5864)