Buffer overflows ten years of attack and defence weakness-vulnerability warning-the black bar safety net

2007-02-06T00:00:00
ID MYHACK58:62200714109
Type myhack58
Reporter 佚名
Modified 2007-02-06T00:00:00

Description

In the past ten years, buffer overflow is a type of security vulnerability accounted for is the most common form. Even more serious is that buffer overflow vulnerabilities account for a remote network attack the majority of, this attack can be such that an anonymous Internet user have access to a host of part or all of the control! If you can effectively eliminate the buffer overflow vulnerability, a large part of the security threats can be mitigated. In this paper, we studied various types of buffer overflow vulnerabilities and attacks, and we also study a variety of means of Defense, these means are used to eliminate the vulnerabilities caused by the impact, including our own stack protection method. And then we have to consider how to ensure existing system functionality and performance under the same circumstances, how to use these methods to eliminate these security vulnerabilities.

A Foreword

In the past ten years, buffer overflow is a type of security vulnerability accounted for is the most common form. Even more serious is that buffer overflow vulnerabilities account for a remote network attack the majority of, this attack can be such that an anonymous Internet user have access to a host of part or all of the control! Due to this type of attack so that any person are likely to obtain host control, so it represents a class of extremely serious security threat.

Buffer overflow attacks have become a common security attacks means the reason is that the buffer overflow vulnerability too common, and easy to implement. Moreover, a buffer overflow becomes a remote attack the main means of the reason is that buffer overflow vulnerabilities give the attacker what they want everything: colonization into and execute attack code. Is cloned into the attack code with some permissions to run a buffer overflow vulnerability in the program, resulting in being attacked host control.

For example, in 1 9 9 8 year Lincoln laboratory used to assess theintrusion detectionthe 5 kinds of remote attacks, there is 3 kind of is based on the social engineering of a trust relationship, 2 types is the buffer overflow. And in 1 9 9 8 year CERT 1 3 proposal, there are 9 parts is the buffer overflow-related, in 1 9 9 9 years, at least half of the recommendations are, and buffer overflow. In Bugtraq survey, 2/3 of respondents believe that the buffer overflow vulnerability is a very serious security issue.

Buffer overflow vulnerability and attack with a variety of forms, we will in the second part of their description and classification. Accordingly means of Defence but also with those methods of attack and different, we'll put in the third part of the description, it content including for each type of attack effective Defense means. We also want to introduce a stack protection method, this method in the solution of buffer overflow vulnerabilities is very effective, and there is no sacrificial system compatibility and performance. In the fourth section, we are going to discuss a variety of Defence methods of the integrated use. Finally in Section V is our conclusions.

Second, the buffer overflow vulnerabilities and attacks

A buffer overflow attack aims to disrupt with certain privileges to run the program's features, this can allow the attacker to obtain the program control, if the program has sufficient permissions, then the entire host is controlled. In General, the attacker attacks the root program, and then perform similar to“exec(sh)”to execute code to gain root shell, but not like this. In order to achieve this objective, the attacker must achieve the following two goals:

1. In the program's address space to arrange the appropriate code.

2. By appropriately initializing registers and memory, allowing the program to jump to the we arrange the address space of the execution.

We according to both the target of buffer overflow attacks are classified. In 2. In Part 1, We will describe the attack code into the attacked program's address space(this is the“buffer”name of origin) it. In 2. Part 2, We introduce the attacker how to make a program of the buffer overflow, and the execution is transferred to attack code(This is the“overflow”comes in). In 2. Section 3, We introduce the integrated in 2. 1 and 2. Part 2 of the discussion of the code arrangement and the control program execution process of the technology.

2.1 in the program's address space to arrange the appropriate code for the method

There are two kinds of in the attack program address space in the arrangements for the attack code to the method:

Cloned into the law:

The attacker to the attacked program input a string, the program will put this string into the buffer. This string contains the data is available in this is attack of running on the hardware platform of the sequence of instructions. Here the attacker with the attacked program's buffers to store the attack code. Specific methods are the following two:

1. The attacker does not have to achieve this purpose the overflow of any buffer, you can find enough space to place attack code

2. The buffer area may be provided in any place: stack(automatic variables), heap(dynamically allocated)static data area(initialized or uninitialized data)

The use of already existing code:

Sometimes,the attackers wanted the code already in the attack procedure, the attacker has to do is just to code to pass some parameters, and then make the program jump to our goal. For example, the attack code required to perform“exe("/bin/sh")”, and in libc in the library code executes“exec(arg)”, where arg so that a pointer to a string pointer parameter, then the attacker as long as the incoming argument pointer is modified to point to"/bin/sh", and then turned to the libc library in the corresponding instruction sequence.

2.2 the control program is transferred to the attack Code of the method

All of these methods are seeking to change the program execution flow, making it jump to the attack code. The most basic is the overflow of a no border checks or other weakness of the buffer zone, thus disturbing the program's normal execution order. By overflowing a buffer, an attacker can use a near-violent methods to rewrite the adjacent program space and skip the system check.

Here the classification of the reference is the attacker looking for a buffer overflow program space type. In principle can be any space. For example, the original Morris Worm used the fingerd program of the buffer overflow, and disrupt the fingerd to execute the file name. In fact, many of the buffer overflows is to use violent methods to seek to change the program pointer. Such procedures in different places is the program space of the break and the memory space of the positioning different.

The activation record(Activation Records) to:

Whenever a function call occurs, the caller will be on the stack left an activation record, it contains the end of the function when the return address. The attacker through the overflow of these automatic variables, so that the return address pointing to attack code. By changing the program of the return address when function call ends, the program jumps to the attacker to set the address, instead of the original address. This type of buffer overflow is called a“stack smashing attack”, so that the currently used buffer overflow attack.

Function pointers(Function Pointers): the

“void (* foo)()”declares a return value for void function pointer variable foo. A function pointer can be used to locate any address space, so an attacker only needs in any space within the function pointer found near one to be able to overflow the buffer, and then overflow the buffer to change the function pointer. In a moment, when the program through a function pointer when the function is called, program flow will press the attacker's intention to achieve! It's an attack example is in the Linux system under the superprobe program.

Long jump buffer(Longjmp buffers): the

In the C language contains a simple test/recovery system, known as setjmp/longjmp in. Mean in the test point set“setjmp(buffer)”with“longjmp(buffer)”to restore the checkpoint. However, if an attacker is able to enter the buffer space, then“longjmp(buffer)”is actually a jump to the attacker code. Like function pointers, like, longjmp buffer can point to anywhere, so an attacker needs to do is find the one for the overflow of the buffer. A typical example is the Perl 5.003, the attacker first enters to restore the buffer overflow of the longjmp buffer, and then induced to enter the recovery mode, This allows the Perl interpreter to jump to the attack code!

2.3 integrated code cloned into and process control technology

Now we study the integrated code cloned into and process control technology.

The most simple and common buffer overflow type of attack is in a string combination Code of proliferation and activation records. The attacker's positioning for the overflow of an automatic variable, then the program passes a very large string, in the trigger buffer overflow to change the activation record of the simultaneously cloned into the code. This is by Levy pointed out that the attack template. Because C is in the habit on only for the user and the parameters to open up a small buffer, so this exploits the instance is not in the minority.

Code cloned into and buffer overflow not necessarily have to be in on the action once completed. The attacker can be in one buffer is placed within the code, which can not overflow the buffer. Then, the attacker through the overflow another buffer to transfer the program pointer. This method is generally used to solve for the overflow of the buffer is not big enough(can't put down all of the Code)of the case.

If an attacker tries to use already-resident code instead of from the external cloned into the code, they usually have must put the code as a parameter. For example, in libc(almost all C programs have to it to connect)in the part of the code snippet will execute the“exec(something)”, where somthing is the parameter. The attacker then uses a buffer overflow to change the program parameters, and then use another buffer overflow causes the program pointer to the libc specific code.

III. Buffer overflow protection methods

There are currently four basic methods of protecting the buffer area from a buffer overflow attack and impact. In 3. 1 describes mandatory to write the correct code. In 3. 2 introduced by theOSso that the buffer is not performed, thereby preventing an attacker cloned into the attack code. This method effectively prevents many buffer overflow attacks, but the attacker doesn't have to be cloned into the attack code to implement a buffer overflow attack(see 2. Section 1), So this method still there are weaknesses. In 3. 3, we describe the use of the compiler's bounds checking to achieve a buffer zone of protection. This method makes buffer overflows impossible, to completely eliminate the buffer overflow threat, but the relative cost is relatively large. In 3. 4 We introduce an indirect method, this method in the program pointer fail before the integrity check. So although this method can not make all of the buffer overflow failure, but it actually prevents the vast majority of buffer overflow attacks, and be able to escape this method of protection of buffer overflow is also very difficult to achieve. Then in the 3. 5, We have to analyze this method of protection compatibility and performance advantages(with array bounds check).

3.1 writing correct code

Writing correct code is a very rewarding but time-consuming work, particularly as the preparation of the C language that has error-prone tendency of the program(such as a string of zeros at the end), this style is due to the pursuit of performance while ignoring the correctness of the traditional cause. Although it took a very long time so that people knew how to write a security program, has a security vulnerability of the program still appears. So people have developed some tools and techniques to help inexperienced programmers to write safe and correct procedures.

The easiest way is to use grep to search the source code prone to a vulnerability of library calls such as strcpy and sprintf calls, those two functions are not check the input parameter length. In fact, the various versions of the C standard library has such a problem exists.

In order to find some commonSuch as buffer overflow andoperating systemcompetitive conditions and other vulnerabilities, the code inspection group to check a lot of code. However, there are still slip through the net presence. Despite the use of strncpy and snprintf these alternative function to prevent a buffer overflow occurs, however, due to the write code questions, the will still have this situation happen. Such as the lprm program is the best example, though it adopted the Code of safety checks, but still have buffer overflow problems.

In order to deal with these problems, people developed a number of advanced Troubleshooting tools such as fault injection, etc. These tools aims by artificially randomly generating some of the buffer overflow to find the code for security vulnerabilities. There are some static analysis tools for detecting buffer overflow exists.

Although these tools help the programmer to develop more secure procedures, but because of C language features, these tools cannot identify all of the buffer overflow vulnerability. So, the debugging techniques can be used to reduce buffer overflow possible, and can not completely eliminate its presence. Unless the programmer can guarantee that his program is foolproof, otherwise still have to use the following 3. 2 to 3. 4 portion of the content to ensure the reliability of the program.

3.2 the non-implementation of the buffer zone

By making the attacked program's data segment address space is not executed, so that the attacker can not perform the reproductive into is to attack the program the input buffer of the code, this technique is referred to as the non-implementation of buffer technology. In fact, many old Unix systems are designed so, but recent Unix and MS Windows system due to achieve better performance and functions, often in a data segment dynamically into executable code. So in order to maintain program compatibility is impossible so that all of the program segment is not executed.

But we can set the stack segment is not executable, so that you can ensure maximum app compatibility. Linux and Solaris were released for the kernel patch. Because there is hardly any legitimate program will be in the stack stored in the code, this approach is hardly generated any compatibility problems, except on Linux in two special cases, then the executable code must be placed in the stack:

Signal transfer:

Linux by providing the process stack to release the code and then cause an interrupt to execute in the stack of code to implement the process of sending a Unix signal. Non-implementation of the buffer of the patch in the Send signal is to allow the buffer executable.

GCC online reuse:

The study found gcc in the stack area is placed in the executable code as an online reuse. However, to close this function does not cause any problems, only part of the function seems to not be used.

Non-execution of stack protection may be effective in dealing with the code is cloned into an automatic variable buffer overflow attacks, and for other forms of attack there is no effect(see 2. 1). The By a reference to a resident of the program pointer, you can skip this protection measures. Other attack may be used the code is cloned into the heap or static data segment to skip protection.

3.3 array bounds checking

Cloned into code to cause a buffer overflow is one aspect that disturbs the program execution process is another aspect. Unlike the non-implementation of buffer zone protection, the array bounds check is fully placed a buffer overflow of produce and attack. Thus, as long as the array can not be overflow, overflow attack does not arise. In order to implement array bounds checking, then all the pairs of read and write operations should be checked to ensure that the logarithm of the group operating in the correct range. The most direct method is to check all array operations, but you can usually employ some optimization techniques to reduce inspection times. Currently has the following several inspection methods:

3.3.1 the Compaq C compiler

Compaq company of the Alpha CPU developed C compiler(on the Tru64 Unix platform is the cc in the Alpha Linux platform is a ccc)supports a limited degree of border checks(use the-check_bounds parameters). These restrictions are:

Only the display of the array references are checked, such as“a[3]”will be checked, while“*(a+3)”is not.

Since all of the C array at the time of delivery is the pointer passed, so passed to the function the array will not be checked.

With a dangerous library function such as strcpy will not at compile-time bounds checking, even if is to specify the boundary check.

Since in the C language using pointer for array operations and the transfer is so Frequent, and therefore this limitation is very serious. Usually this boundary check is used to program the error-checking, but can not guarantee does not occur buffer overflow vulnerability.

3.3.2 Jones & Kelly: C of array bounds checking

Richard Jones and Paul Kelly developed a gcc patch, used to implement C Program complete array bounds checking. Since there is no change of the pointer of the meaning, so is the compiled program and the other gcc module has good compatibility. Further, they thus never have a pointer to the expression to export a“base”pointer, and then by checking the base pointer to detect the result of the expression is within the allowable range.

Of course, such a pay the performance cost is huge: for a frequent use of pointer programs such as vector multiplication, since the pointer is frequently used and so that the speed ratio of the original slow 3 0 times.

This compiler is currently very immature; some sophisticated programs(such as elm)is also not in the above compilation, the execution through. However, in one of its newer versions below, it can at least compile and run the ssh software encryption package. The realization of the performance to drop 1 2 times.

3.3.3 Purify: memory access check

Purify is a C Program while debugging to view the memory use of the tool rather than a dedicated Security Tool. Purify using the“object code insertion”technique to check all of the memory access. By using a Purify connection tool to connect, the executable code at the time of execution of an array of all references to ensure their legitimacy. This brings the performance on the loss to drop 3-5 times.

3.3.4 type-safe language

All the buffer overflow vulnerabilities stem from the C language is the lack of type safety. If only type-safe operations can only be allowed to perform, so it is impossible to appear on the variables of the forced operation. If, as a novice, it can be recommended to use a type-safe language such as Java and ML.

But as a Java execution platform the Java virtual machine is a C Program, so by attacking the JVM one way is to make the JVM buffer overflow. Therefore, in the system using the buffer overflow defensive techniques to the use of mandatory type-safety of the language can receive the unexpected effect.

3.4 program pointer integrity checking

Program pointer integrity checking and bounds checking by the slightly different. And prevent the program pointer is changed to a different, the program pointer integrity checking in the program the pointer is referenced before it detects the change. Therefore, even if an attacker successfully changes the program pointer, since the system previously detected a pointer change, so this pointer will not be used.

With array bounds checking, this method can not solve all of the buffer overflow problem; the use of other buffer overflow method you can avoid such detection. However, this method in the performance has great advantages, but also in compatibility is also very good.

Program integrity check generally there are three research directions. In 3. 4. 1 will introduce Snarskii for FreeBSD developed a custom energy by monitoring the cpu stack to determine a buffer overflow in libc in. In 3. 4. 2 will introduce our own stack protection method for the development of a compiler, it can be in the function call when the automatically generated integrity detection code. Finally in 3. 4. 3, we describe the ongoing development of the pointer protection method, this method is similar to the stack protection, which provides for all program pointer integrity protection. 3.4.1 handwritten stack monitoring

Snarskii for FreeBSD developed a custom energy by monitoring the cpu stack to determine a buffer overflow in libc in. This application complete with the hand a compilation of written, and only the protection of libc in the current active record function. This application has reached the design requirements, based on the libc library function attack has a very good Defense, but not Defense of other means of attack.

3.4.2 stack protection: the compiler generates a valid record integrity test

Stack protection is a method of providing a program pointer to the integrity check of the compiler technology, by examining the function of the activity record in the returned address to achieve. Stack protection as the gcc is a small patch in each function, adding the function to create and destroy code. Added a function to build the code actually in the stack, the function returns the address of the back plus some additional bytes. And when the function returns, it first checks this additional byte is to be altered. If occurred through a buffer overflow attack, then this attack is quite easy in function returns before it is detected.

However, if the attacker anticipate these additional bytes exist, and can be in overflow process in the same manner of manufacturing them, then he will be able to successfully jump over the stack to protect the detection. Typically, we have the following two options to deal with this deception:

Termination symbols:

The use of the C language in a termination symbol such as 0(null), CR, LF, AND -1(EOF), etc. not in the commonly used string functions, because these functions once you encounter these termination symbol, on the end of a function procedure.

Random symbols:

The use of a function call is generated when a 3 2-bit random number to achieve confidentiality, so that the attacker can not guess to the additional bytes of content. Moreover, each call, the additional bytes of the content are changed, it can not be predicted.

By checking stack integrity stack protection method is from Synthetix method of evolution. Synthetix method by using quasi-invariants to ensure that a particular variable is correct. These particular variables change program implementation can be unpredictable, and can only meet certain conditions in order to be changed. This variable we referred to as quasi-variables. Synthetix has developed some of the tools used to protect these variables.

The attacker through a buffer overflow in the change of the system can be treated as an illegal action. In some extreme cases, these quasi-invariants are likely to be illegally changed, it is you need stack protection to provide better protection.

Experimental data indicate that the stack protection for various system buffer overflow attacks have very good protection effect, and can maintain better compatibility and system performance. Subsequently, we use a stack protection method re-constructs a complete Linux system(Red Hat 5.1 in). Then we use the XFree86-3.3.2-5 and lsof vulnerability to attack, the results show that this system effectively defend against these attacks. These analyses show that the stack protection can be effective against current and future stack-based attacks.

Stack protected version of Red Hat Linux 5.1 has been in a variety of systems running on over the years, including a personal laptop, and workgroup file servers. From ourWeb servercan be obtained on this version, but also in our mailing list already with 5 of 5 members. Shows only one exception, this system and the original system work exactly the same, This indicates that the stack protection is not on the compatibility of the system constitute a significant impact.

We have used a variety of performance tests to measure stack protection performance. Mircobenchmarks the results indicate that in the function call, the stack protection increase system

Overhead. And in the network of the test(need to use the stack protection places), it indicates that this overhead is not very large.

Our first test object is SSH, which provides strong encryption and authentication, used to replace the Berkeleyr-series instruction. SSH uses software encryption, so the system bandwidth occupied by not more than, we use the network to copy a large file to test the bandwidth:

|

scp bigsource localhost: bigdest


The test results showed that: the stack protection almost does not affect the SSH network throughput performance.

The second test used the Apache Web server. If such a server exists a stack-based attack, then the attacker can easily obtain theWeb serverof the control, allowing the attacker to read the hidden content and the wanton tampering with the home page content. Meanwhile, theWeb serveris also for performance and higher bandwidth requirements of a server component.

We used WebStone for with and without stack protection the Apache Web serverwere tested.

And SSH the same, their performance is almost no difference. In the number of customers is less the case, with the protection of server performance than without the protection of slightly better, in the number of clients is more time, without the protection of the performance better. In the worst case, with the protection of the server than without protection to the difference between the 8%of the connected properties, and the average delay on holding the advantage. As before, we put these attributed to the influence of noise. Therefore, our conclusion is: stack protection on theWeb serversystem performance no significant impact.

3.4.3 pointer protection: the compiler generates program pointer integrity checking

In the stack to protect the design, The impact of the stack constituting the buffer overflow attacks the common one form. Someone speculated that the presence of a template to form these attacks(in 1 9 9 6 year of time). Since then, many simple exploits are found and patches, and a lot of the attackers to start with in the second part of the description of more General embodiments of the method buffer overflow attacks.

The pointer protection stack protection for this case of a promotion. Through all of the code pointer is placed after the additional bytes to test the pointer is called before the the legitimacy. If the test fails, will send an alarm signal, and exit the program execution, just like the stack protection in the act. This program has two points to note:

Additional bytes of the location:

Additional bytes of space is in a protected variable is assigned when allocated, while in protected byte initialization process is initialized. This poses a problem; in order to maintain compatibility, we do not want to change a protected variable size, so we cannot simply variables define the structure added an additional word. Also, the various types also have different additional number of bytes is.

Check additional bytes:

Each time the program pointer is referenced all the time to check additional bytes of integrity. This is also a problem; because“from accessor read”the compiler has no semantics; the compiler is more concerned about the use of pointers, and a variety of optimization algorithms tend to read from the memory into the variable.

Also with the different types of variables, the Read method also.

We have developed pointer protection of a prototype(still based on gcc), by an additional byte to the Protection a static assignment of a function pointer, but not for structure and array types. This plan is still far from complete. Once this project is finished, then use it and stack protection constitute the executable code will not be subject to buffer overflow attacks.

So far, only a small part of the use of a non-pointer variable the attack is able to escape the pointer protection detection. However, by the compiler forced to some variables adding additional bytes to achieve the detection, then you need a programmer yourself manually adding the appropriate protection.

3.5 compatibility and performance considerations

Program pointer integrity checking and bounds checking is compared, and can not prevent all buffer overflow problems. However, in the implementation of the performance and compatibility has considerable advantages:

Performance:

Border checks must be in each element of the array when the operation is complete once a check. By contrast, the program pointer check in only to be referenced when implementing the check. Whether in C or in C++, this flower in the program pointer references on the overhead is always better than an array of pointer references is small.

Application performance:

Bounds checking is the most difficult to achieve that in C language, it can determine the array boundaries. This is because in C, an array of concepts and General pointers to the mix. Since a pointer is a separate object, not with the specific boundary conditions of the Association, only one system of the machine word to store it, and identifies the boundary information of the data without storage. Therefore need a special method to recover these Information; an array of reference is not a simple pointer, but a pair of buffer description pointer to the group.

With existing code compatibility:

Some boundary checking method in order to with the existing code remains compatible with and in the performance of the system on the Get a loss. While others use other methods to achieve the purpose. Thus breaking the traditional C conversion rules, instead of generating a new class of C compiler that can only compile C of a sub-set, and some also can not use the pointer or the need for other changes.

IV. Effective combination

Here we study, the comparison in the second part of the description of the various exploits and in the third part of the description of the defense method, in order to determine what combination can completely eliminate the buffer overflow problem. But we didn't put the border checks included in the calculation, because it can effectively prevent all buffer overflows, but the overhead required is also amazing.

The most common buffer overflow form is to attack the activity record and then in the stack cloned into the code. This type of attack in 1 9 9 6 year a lot of records. Instead of the execution stack and stack protection method can be an effective Defense for this attack. Non-implementation of the stack can be defensive all the code is cloned into the stack attack, stack protection may be the defense all change the active record methods. These two methods compatible with each other, while the defence of a variety of possible attacks.

The rest of the attack can basically use the pointer protection method to defend, but in some special occasions need to use the manual to implement pointer protection. Automatic pointer protection required for each variable added additional bytes such that the pointer bounds checking in certain cases with advantage.

Most interestingly, the first buffer overflow vulnerability--the Morris worm used today all methods are not effective Defense of the method, but very few people used to, perhaps this method is too complex because of it.

Five. Conclusions

In this article, we describe in detail and analyze a buffer overflow attack and defence method. Since this attack is currently the common means of attack, so this aspect of the research work is meaningful and effective. The results of the study showed that a stack protection method and the non-implementation of the buffer method for the current the vast majority of attacks can be effectively Defense, the pointer protection method can be the rest of the attack for an effective Defense. The last statement is for the Morris worm attack, to date there is no effective means of Defense