Unleashing Use-Before-Initialization Vulnerabilities in the Linux Kernel Using Targeted Stack Spraying
Download: Paper (PDF)
Date: 27 Feb 2017
Document Type: Reports
Associated Event: NDSS Symposium 2017
A common type of memory error in the Linux kernel is using uninitialized variables (uninitialized use). Uninitialized uses not only cause undefined behaviors but also impose a severe security risk if an attacker takes control of the uninitialized variables. However, reliably exploiting uninitialized uses on the kernel stack has been considered infeasible until now since the code executed prior to triggering the vulnerability must leave an attacker-controlled pattern on the stack. Therefore, uninitialized uses are largely overlooked and regarded as undefined behaviors, rather than security vulnerabilities. In particular, full memorysafety techniques (e.g., SoftBound+CETS) exclude uninitialized use as a prevention target, and widely used systems such as OpenSSL even use uninitialized memory as a randomness source.
In this paper, we propose a fully automated targeted stackspraying approach for the Linux kernel that reliably facilitates the exploitation of uninitialized uses. Our targeted stack-spraying includes two techniques: (1) a deterministic stack spraying technique that suitably combines tailored symbolic execution and guided fuzzing to identify kernel inputs that user-mode programs can use to deterministically guide kernel code paths and thereby leave attacker-controlled data on the kernel stack, and (2) an exhaustive memory spraying technique that uses memory occupation and pollution to reliably control a large region of the kernel stack. We show that our targeted stack-spraying approach allows attackers to reliably control more than 91% of the Linux kernel stack, which, in combination with uninitialized-use vulnerabilities, suffices for a privilege escalation attack. As a countermeasure, we propose a compiler-based mechanism that initializes potentially unsafe pointer-type fields with almost no performance overhead. Our results show that uninitialized use is a severe attack vector that can be readily exploited with targeted stack-spraying, so future memory-safety techniques should consider it a prevention target, and systems should not use uninitialized memory as a randomness source.