With a simple search on your favorite search engine, you'll soon see how much computer security damage and/or failure is caused by a so-called buffer overflow. For example, the following is from the November 3, 2000 Risk of Volume 21st, issue 9th:
Date: thu,2000 November 2 17:57:09 PST from: "Peter G. Neumann" <[email protected]> theme: The plight of air traffic control October 19, 2000, Hundreds of aircraft landing or delaying software problems in the Los Angeles Air traffic control system because of an aircraft. The reason is attributed to the Mexican controller input 9 (instead of 5) characters Flight description data, which causes a buffer overflow. October 23, 2000, a computer failure in the Fremont Regional Center, California State, led to the loss of all flight plans of the North California State and Nevada west; The system does not work after maintenance until night. As a result, the FAA has suspended the installation of a new software upgrade in the ATC system until further notice. [Source: Various sources of news]
This is a good example because I will show you how simple it is to prevent-poor programmers just can't spare time to be thorough. First, I'll try to explain what a buffer overflow is in a non-technical term. Then I'll show you some simple C code.
When programmers write code, they often have to allocate buffers to hold incoming data. The data can come from files on disk, or from the keyboard input from the operator. The reason they must formally allocate such memory is that the program cannot simply occupy any memory they need; They must "request" permission from the host. The computer is responsible for memory management, so the memory associated with one program does not "jump" memory from another program. It's not going to be good.
When writing such code, programmers have to spend time thinking about the size of the data and how much memory is needed. In many cases, their work can be mitigated by allowing their code to dynamically allocate memory. This is usually done with tools such as malloc()
. If programmers do not think their buffers are relative to the size of their data, then a buffer overflow can occur.
Simply put, at this point, a buffer overflow may occur when the data destined for a particular buffer is larger than the memory allocated to the buffer.
Getting a bit more language specific...
in the C language, a buffer overflow can cause so-called undefined behavior . That's exactly what it sounds: anything that could happen. No one knows what will happen. Sometimes, it may crash the program. Other times, it may not produce the results you expect at all. Other times, it could lead to hundreds of flights grounded while the ATC system restarts. Very often, in a simple program, nothing happens. But the key point to understand is that the behavior is undefined-anything can happen. Now let's take a look at some sample code:
#include <stdio.h> #define Buffer_size 16int Main (empty) { char fName [buffer_size]; printf ("Please enter your name:"); scanf ("%s", fName); printf ("hello,%s \ n", fName); return 0;}}
This is a valid ANSI C code that will be compiled on various platforms. Let's take a look at the core part of the program and discuss its functionality:
Char fName [buffer_size];
This defines a string of size buffer_size, in which case it is 16. To be correct, this string will contain a maximum of 15 characters and a null character, because a string is defined as null-terminated.
printf ("Please enter your name:");
This line simply prompts the operator to enter his/her name.
scanf ("%s", fName);
This will accept input from the operator and populate it with the string we defined earlier.
printf ("hello,%s \ n", fName);
Finally, we only print a greeting to the operator.
Trying out the example
Here is a simulation that runs our sample program:
$./name Please enter your name: John Hello, John $
Great work, isn't it? Using this method, this program will work without defects as long as you need it. But what if a curious operator came and decided that his name needed a ' LKASDJFKLASJDFKLJSADFIWOJEHFIOAJHDSOFJAKLSJDF ' Day? Let's take a look at:
$./name Please enter your name: LKASDJFKLASJDFKLJSADFIWOJEHFIOAJHDSOFJAKLSJDF Hello: LKASDJFKLASJDFKLJSADFIWOJEHFIOAJHDSOFJAKLSJDF segment Fault (core dump) $
What happened? Well, we tell the program that we will provide a string of no more than 16 characters (actually, 15 plus a null). We have just provided 45 characters. Simple math tells us that 45 is definitely more than 16, we just created a buffer overflow -our data overflows the buffers we have allocated to it. Recall that this behavior is undefined in C. We were lucky-our program simply went through a segmentation error (Segfault). In the Unix world, this usually means that we have access to memory that we do not have allocated to us. On another computer or platform, many other things can happen because the behavior is undefined.
So what can a programmer do?
Well, a direct idea is simply to increase BUFFER_SIZE
. If you take a look /usr/include/stdio.h
, there is one BUFSIZ 1024
for you to use. Should you use it? Perhaps not, as a person, innocent or not, may overflow at some point. Because the input is not checked, this is almost guaranteed to occur eventually.
Fortunately, C programmers have a tool defined in the ANSI C standard to solve this particular problem: enterfgets()
Function fgets()
is designed to prevent the extension from exceeding the input of the memory allocated to it. By design, it guarantees this. Let's take a look at our revised code using our new function:
#include <stdio.h> #define Buffer_size 16int Main (empty) { char fName [buffer_size]; printf ("Please enter your name:"); Fgets (Fname,sizeof (fName), stdin); printf ("hello,%s \ n", fName); return 0;}}
by using fgets()
, we promise not to overflow our buffers. Let's take a look at a sample run:
$./fname Please enter your name: Kildalla Little Bit about Buffer overflows Hello, xx$
Note that there are two blank lines in the output. This is because fgets()
a newline character is preserved. get rid of it and leave it to the programmer for an exercise. Anyway, let's take a look at what happens to our curious operators:
$./fname Please enter your name: Laksdfjklajdfkljdsafkljasdklfjkwjeifjwio Hello, laksdfjklajdfkl$
this time we passed in a 40-character name. As promised, fgets()
It only took 15 words to multibyte over--that's what we wanted.
Summary
I hope I've been able to prove how easy it is to cause all sorts of damage on a poorly written computer. I hope I have shown how easy it is to use simple programming techniques to prevent such things.
If you look at the security-related sites, you will find that quite a few security compromises are caused by buffer overflows. Some are so simple-refer to the ATC shutdown at the top of this article. I guess in this case overflow just because the programmer didn't think of validating the input in some way. I am sure that the Mexican controller means no harm, but imagine what might happen if/someone has bad intentions to work here. Other conditions are caused by a buffer overflow associated with socket programming such as the Network Service daemon. An example of a network service daemon might be a Web server. Vulnerabilities involving such programs are particularly dangerous because they often result in the misappropriation of privileged and/or managed accounts. In fact, this exact loophole is what causes the 1987 Internet worm called Robert Morris a guy to build a rogue program in the use of this fingerd
program. He can then gain root access on the host.
A Little Bit about Buffer overflows