Real-World Buffer Overflow Protection for Userspace & Kernelspace
Total Page:16
File Type:pdf, Size:1020Kb
Real-World Buffer Overflow Protection for Userspace & Kernelspace Michael Dalton, Hari Kannan, Christos Kozyrakis Computer Systems Laboratory Stanford University {mwdalton, hkannan, kozyraki}@stanford.edu Abstract Despite decades of research, the available buffer over- Despite having been around for more than 25 years, flow protection mechanisms are partial at best. These buffer overflow attacks are still a major security threat for mechanisms provide protection only in limited situa- deployed software. Existing techniques for buffer over- tions [9], require source code access [51], cause false flow detection provide partial protection at best as they positives in real-world programs [28, 34], can be de- detect limited cases, suffer from many false positives, re- feated by brute force [44], or result in high runtime over- quire source code access, or introduce large performance heads [29]. Additionally, there is no practical mechanism overheads. Moreover, none of these techniques are easily to protect the OS kernel from buffer overflows or unsafe applicable to the operating system kernel. user pointer dereferences. This paper presents a practical security environment Recent research has established dynamic information for buffer overflow detection in userspace and ker- flow tracking (DIFT) as a promising platform for detect- nelspace code. Our techniques build upon dynamic in- ing a wide range of security attacks on unmodified bina- formation flow tracking (DIFT) and prevent the attacker ries. The idea behind DIFT is to tag (taint) untrusted data from overwriting pointers in the application or operat- and track its propagation through the system. DIFT as- ing system. Unlike previous work, our technique does sociates a tag with every memory location in the system. not have false positives on unmodified binaries, protects Any new data derived from untrusted data is also tagged. both data and control pointers, and allows for practi- If tainted data is used in a potentially unsafe manner, cal hardware support. Moreover, it is applicable to the such as dereferencing a tagged pointer, a security excep- kernel and provides robust detection of buffer overflows tion is raised. The generality of the DIFT model has led and user/kernel pointer dereferences. Using a full sys- to the development of several software [31, 32, 38, 51] tem prototype of a Linux workstation (hardware and soft- and hardware [5, 10, 13] implementations. ware), we demonstrate our security approach in practice Current DIFT systems use a security policy based on and discuss the major challenges for robust buffer over- bounds-check recognition (BR) in order to detect buffer flow protection in real-world software. overflows. Under this scheme, tainted information must receive a bounds check before it can be safely deref- 1 Introduction erenced as a pointer. While this technique has been used to defeat several exploits [5, 10, 10, 13], it suf- Buffer overflows remain one of the most critical threats fers from many false positives and false negatives. In to systems security, although they have been prevalent practice, bounds checks are ambiguously defined at best, for over 25 years. Successful exploitation of a buffer and may be completely omitted in perfectly safe situ- overflow attack often results in arbitrary code execu- ations [12, 13]. Thus, the applicability of a BR-based tion, and complete control of the vulnerable application. scheme is limited, rendering it hard to deploy. Many of the most damaging worms and viruses [8, 27] Recent work has proposed a new approach for pre- use buffer overflow attacks. Kernel buffer overflows venting buffer overflows using DIFT [19]. This novel are especially potent as they can override any protection technique prevents pointer injection (PI) by the attacker. mechanisms, such as Solaris jails or SELinux access con- Most buffer overflow attacks are exploited by corrupt- trols. Remotely exploitable buffer overflows have been ing and overwriting legitimate application pointers. This found in modern operating systems including Linux [23], technique prevents such pointer corruption and does not Windows XP and Vista [48], and OpenBSD [33]. rely on recognizing bounds checks, avoiding the false positives associated with BR-based analyses. However, 2.1 Existing Buffer Overflow Solutions this work has never been applied to a large application, or the operating system kernel. Moreover, this technique Many solutions have been proposed to prevent pointer or requires hardware that is extremely complex and imprac- code corruption by untrusted data. Unfortunately, the so- tical to build. lutions deployed in existing systems have drawbacks that This paper presents a practical approach for prevent- prevent them from providing comprehensive protection ing buffer overflows in userspace and kernelspace using against buffer overflows. a pointer injection-based DIFT analysis. Our approach Canary-based buffer overflow protection uses a ran- identifies and tracks all legitimate pointers in the appli- dom, word-sized canary value to detect overwrites of cation. Untrusted input must be combined with a legiti- protected data. Canaries are placed before the begin- mate pointer before being dereferenced. Failure to do so ning of protected data and the value of the canary is ver- will result in a security exception. ified each time protected data is used. A standard buffer The specific contributions of this work are: overflow attack will change the canary value before over- writing protected data, and thus canary checks provide • We present the first DIFT policy for buffer overflow buffer overflow detection. Software implementations of prevention that runs on stripped, unmodified bina- canaries typically require source code access and have ries, protects both code and data pointers, and runs been used to protect stack linking information [16] and on real-world applications such as GCC and Apache heap chunk metadata [39]. Related hardware canary im- without false positives. plementations [21, 46] have been proposed to protect the stack return address and work with unmodified binaries. • We demonstrate that the same policy is applicable to However, buffer overflows may be exploited with- the Linux kernel. It is the first security policy to dy- out overwriting canary values in many situations. For namically protect the kernel code from buffer over- example, in a system with stack canaries, buffer over- flows and user-kernel pointer dereferences without flows may overwrite local variables, even function point- introducing false positives. ers, because the stack canary only protects stack link- ing information. Similarly, heap overflows can overwrite • We use a full-system DIFT prototype based on the neighboring variables in the same heap chunk without SPARC V8 processor to demonstrate the integra- overwriting canaries. Additionally, this technique may tion of hardware and software techniques for robust change data structure layout by inserting canary words, protection against buffer overflows. Our results are breaking compatibility with legacy applications. Canary- evaluated on a Gentoo Linux platform. We show based approaches also do not protect other memory re- that hardware support requirements are reasonable gions such as the global data segment, BSS or custom and that the performance overhead is minimal. heap allocation arenas. Non-executable data protection prevents stack or • We discuss practical shortcomings of our approach, heap data from being executed as code. Modern hard- and discuss how flaws can be mitigated using addi- ware platforms, including the x86, support this technique tional security policies based on DIFT. by enforcing executable permissions on a per-page basis. The remainder of the paper is organized as follows. However, this approach breaks backwards compatibility Section 2 reviews related work. Section 3 summarizes with legacy applications that generate code at runtime the Raksha architecture and our full-system prototype. on the heap or stack. More importantly, this approach Section 4 presents our policy for buffer overflow protec- only prevents buffer overflow exploits that rely on code tion for userspace applications, while Section 5 extends injection. Rather than injecting new code, attackers can the protection to the operating system kernel. Section 6 take control of an application by using existing code in discusses weaknesses in our approach, and how they can the application or libraries. This form of attack, known be mitigated with other buffer overflow prevention poli- as a return-into-libc exploit, can perform arbitrary com- cies. Finally, Section 7 concludes the paper. putations and in practice is just as powerful as a code injection attack [43]. Address space layout randomization (ASLR) is a 2 Related Work buffer overflow defense that randomizes the memory lo- cations of system components [34]. In a system with Buffer overflow prevention is an active area of research ASLR, the base address of each memory region (stack, with decades of history. This section summarizes the executable, libraries, heap) is randomized at startup. A state of the art in buffer overflow prevention and the standard buffer overflow attack will not work reliably, shortcomings of currently available approaches. as the security-critical information is not easy to locate in memory. ASLR has been adopted on both Linux whether tagged input can ever be validated by applica- and Windows platforms. However, ASLR is not back- tion code. wards compatible with legacy code, as it requires pro- Most DIFT