TIED, Libsafeplus: Tools for Runtime Buffer Overflow Protection
Total Page:16
File Type:pdf, Size:1020Kb
TIED, LibsafePlus: Tools for Runtime Buffer Overflow Protection Kumar Avijit Prateek Gupta Deepak Gupta Department of Computer Science and Engineering Indian Institute Of Technology, Kanpur Email: {avijitk,pgupta,deepak}@iitk.ac.in Abstract In a buffer overflow attack, the attacker’s aim is to gain Buffer overflow exploits make use of the treatment of strings access to a system by changing the control flow of a pro- in C as character arrays rather than as first-class objects. gram so that the program executes code that has been care- Manipulation of arrays as pointers and primitive pointer fully crafted by the attacker. The code can be inserted in the arithmetic make it possible for a program to access memory address space of the program using any legitimate form of in- locations which it is not supposed to access. There have been put. The attacker then corrupts a code pointer in the address many efforts in the past to overcome this vulnerability by per- space by overflowing a buffer and makes it point to the in- forming array bounds checking in C. Most of these solutions jected code. When the program later dereferences this code are either inadequate, inefficient or incompatible with legacy pointer, it jumps to the attacker’s code. Such buffer overflows code. In this paper, we present an efficient and transparent occur mainly due to the lack of bounds checking in C library runtime approach for protection against all known forms of functions and carelessness on the programmer’s part. For ex- buffer overflow attacks. Our solution consists of two tools: ample, the use of strcpy() in a program without ensuring TIED (Type Information Extractor and Depositor) and Lib- that the destination buffer is at least as large as the source safePlus. TIED extracts size information of all global and au- string is apparently a common practice among many C pro- tomatic buffers defined in the program from the debugging in- grammers. formation produced by the compiler and inserts it back in the Buffer overflow exploits come in various flavours. The program binary as a data structure available at runtime. Lib- simplest and also the most widely exploited form of attack safePlus is a dynamic library which provides wrapper func- changes the control flow of the program by overflowing some tions for unsafe C library functions such as strcpy. These buffer on the stack so that the return address or the saved wrapper functions check the source and target buffer sizes us- frame pointer is modified. This is commonly called the “stack ing the information made available by TIED and perform the smashing attack” [3]. Other more complex forms of attacks requested operation only when it is safe to do so. For dy- may not change the return address but attempt to change the namically allocated buffers, the sizes and starting addresses program control flow by corrupting some other code point- are recorded at runtime. With our simple design we are able ers (such as function pointers, GOT entries, longjmp buffers, to protect most applications with a performance overhead of etc.) by overflowing a buffer that may be local, global or dy- less than 10%. namically allocated. Many common forms of buffer overflow attacks are described in [4]. 1 Introduction Due to the huge amount of legacy C code existing today, which lacks bounds checking, an efficient runtime solution Buffer overflows constitute a major threat to the security of is needed to protect the code from buffer overflows. Other computer systems today. A buffer overflow exploit is both solutions which have developed over the years such as man- common and powerful, and is capable of rendering a com- ual/automatic auditing of the code, static analysis of pro- puter system totally vulnerable to the attacker. As reported grams, etc., are mostly incomplete as they do not prevent all by CERT, 11 out of 20 most widely exploited attacks have attacks. A runtime solution is required because certain type been found to be buffer overflow attacks [1]. More than 50% of information is not available statically. For example, infor- of CERT advisories [2] for the year 2003 reported buffer over- mation about dynamically allocated buffers is available only flow vulnerabilities. It is thus a major concern of the comput- at runtime. However, most current runtime solutions are un- ing community to provide a practical and efficient solution to acceptable because they either do not protect against all forms the problem of buffer overflows. of buffer overflow attacks, break existing code, or impose too high an overhead to be successfully used with common ap- for unsafe C library functions. Each such wrapper function plications. An acceptable solution must tackle all of these checks the bounds of the destination buffer before performing problems. the actual operation. For dynamically allocated buffers, Lib- In this paper, we present a simple yet robust solution to safePlus maintains an additional runtime data structure that guard against all known forms of buffer overflow attacks. The stores information about the locations and sizes of all dynam- solution is a transparent runtime approach to prevent such at- ically allocated buffers. In contrast to other approaches which tacks and consists of two tools: TIED and LibsafePlus. Lib- are mainly compiler extensions, LibsafePlus does not require safePlus is a dynamically loadable library and is an extension source code access if the program is compiled with the -g to Libsafe [5]. LibsafePlus contains wrapper functions for un- option and is not statically linked with the C library. safe C library functions such as strcpy. A wrapper function determines the source and target buffer sizes and performs the required operation only if it would not result in an overflow. To enable runtime size checking we need to have additional type information about all buffers in the program. This is done by compiling the target program with the -g debugging option. TIED (Type Information Extractor and Depositor) is a tool that extracts the debugging information from a program binary and then augments the binary with an additional data structure containing the size information for all buffers in the Figure 1: Rewriting of the binary executable by TIED and program. This information is utilized by LibsafePlus to range runtime range checking by LibsafePlus check buffers at runtime. For keeping track of the sizes of dynamically allocated buffers, LibsafePlus intercepts calls to LibsafePlus is implemented as an extension to Libsafe [5]. the malloc family of functions. Our tools thus neither re- Libsafe is also a dynamically loadable library which pro- quire access to the source code (if it was compiled with the -g vides wrapper functions for unsafe C library functions such option) nor any modifications to the compiler, and are com- as strcpy(). However, Libsafe protects only against stack pletely compatible with legacy C code. The tools have been smashing attacks. Even for stack variables, Libsafe assumes found to be effective against all forms of attacks and impose a a safe upper bound on the size of a buffer instead of deter- low runtime performance overhead of less than 10% for most mining its exact size. Therefore, it is possible for the attacker applications. to change variables in the program that are next to the buffer The rest of the paper is organized as follows. We present in memory. Unlike Libsafe, our tools offer full protection an overview of our approach in Section 2. Section 3 de- against all forms of attack and determine the exact sizes of scribes the implementation of TIED and LibsafePlus. This all buffers. They have been tested extensively and have been is followed by a description of performance experiments and found to be effective against all forms of buffer overruns. Our results, in Section 4. Section 5 briefly discusses the related tools successfully prevented all the 20 different overflow at- work done in the area of buffer overflow protection. Section 6 tacks in the testbed developed by Wilander and Kamkar for concludes the paper. testing tools for dynamic overflow attacks [6], while the orig- inal Libsafe could only detect only 6 of the 20 attacks. 2 Basic approach In the following subsections, we describe in detail the de- sign of Libsafe and our extensions to it. We first describe in The steps in the protection of a program using TIED and Lib- Section 2.1, the protection mechanism used by Libsafe and safePlus are shown in Figure 1. The key idea here is to aug- then show in Section 2.2, how LibsafePlus extends the basic ment the executable with information about the locations and protection mechanism, to handle all forms of buffer overflow sizes of character buffers. To this end, the program source attacks. must be compiled with the -g option which directs the com- piler to dump debugging information regarding the sizes and 2.1 Runtime range checking by Libsafe types of all variables in the program in the generated exe- cutable binary. The next step is to rewrite the executable with The goal of Libsafe is to prevent corruption of the return ad- the required information as an additional data structure in the dresses and saved frame pointers on the stack in the event form of a separate read-only section of the executable. This of a stack buffer overflow. Libsafe does not guarantee pro- makes the information about buffer sizes available at runtime. tection against any other form of attack. To ensure that the The binary rewriting of the executable is done by TIED. Lib- frame pointers and the return addresses are never overwrit- safePlus is implemented as a dynamically loadable library ten, Libsafe assumes a safe upper bound on the size of stack that must be preloaded for a process to be protected.