CERT Advisory CA-2001-16
John Chambers
jc at trillian.mit.edu
Wed Jul 4 10:42:23 EDT 2001
| Rookie question: How is it possible for a buffer overflow to allow
| access? Does the overflow automatically provide a shell? Or does it put
| the process in some debugging mode with remote privileges?
Simple (;-). A program consists of a mixture of code and data chunks,
and it's fairly common for linkers to intermix these in what is
essentially a random order. So a program's layout in memory may look
something like:
code1 data1 code2 data2 code3 data3
...|_______|__________|________|_____|_______|______|...
The code chunks are functions; the data chunks correspond to global
or static variables, typically belonging to the adjacent code chunks.
In cases like this, if the program were to copy more bytes into the
data2 chunk that there was space for, it would overwrite the initial
portion of code3. Then the next time that code3 is executed, its new
value would be run.
If this were just an ordinary data overwrite due to a program bug,
the garbaged code3 chunk would probably just bomb instantly, most
likely with an illegal instruction or a memory fault. If the data
written into data2 were to contain valid machine code, then the new
stuff in code3 wouldn't be junk, but would be the exploiter's code,
and it would run with whatever permissions the process happened to
have at the time.
The most common exploitable situation is a program that calls the
gets() routine. If you check with `man gets`, you'll see that it has
only a char* pointer to the place to put the next line of input, and
no way to give the size. So gets() overwrites as much memory as it
needs, until a newline is encountered. This was a major mistake in
the original C library, which has been cast in concrete by the POSIX
standard. Its use is usually a mistake, since the program has no
defense against input with a very long line. As long as there is no
newline in my code, I can send a big chunk of code to the process,
and gets() will happily overwrite memory with all of it.
This sort of exploit doesn't work on all hardware or with all
linkers. It's sometimes possible to segregate the code chunks and
make them read-only, which prevents them from being overwritten. But
not all hardware allows this, and even when it does, the linker
doesn't always do it correctly. In such cases, a bit of analysis of
the object file may turn up examples of input buffers immediately
followed by code chunks. A bit of testing will determine whether the
program has a proper bounds check on input to the buffer. If not,
then a carefully designed input file can contain just enough filler
text to fill the input buffer, followed by code that will be read
into the code chunk. It isn't easy, but it's possible.
-
Subcription/unsubscription/info requests: send e-mail with
"subscribe", "unsubscribe", or "info" on the first line of the
message body to discuss-request at blu.org (Subject line is ignored).
More information about the Discuss
mailing list