21.03.2013 Views

Problem - Kevin Tafuro

Problem - Kevin Tafuro

Problem - Kevin Tafuro

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

All of the compiler-based solutions work in much the same way, although there are<br />

some differences in the implementations. They work by placing a “canary” (which is<br />

typically some random value) on the stack between the control flow information and<br />

the local variables. The code that is normally generated by the compiler to return<br />

from the function is modified to check the value of the canary on the stack, and if it<br />

is not what it is supposed to be, the program is terminated immediately.<br />

The idea behind using a canary is that an attacker attempting to mount a stacksmashing<br />

attack will have to overwrite the canary to overwrite the control flow information.<br />

By choosing a random value for the canary, the attacker cannot know what<br />

it is and thus be able to include it in the data used to “smash” the stack.<br />

When a program is distributed in source form, the developer of the program cannot<br />

enforce the use of StackGuard or ProPolice because they are both nonstandard extensions<br />

to the GCC compiler. It is the responsibility of the person compiling the program<br />

to make use of one of these technologies. On the other hand, although it is rare<br />

for Windows programs to be distributed in source form, the /GS compiler flag is a<br />

standard part of the Microsoft Visual C++ compiler, and the program’s build scripts<br />

(whether they are Makefiles, DevStudio project files, or something else entirely) can<br />

enforce the use of the flag.<br />

For Linux systems, Avaya Labs’ LibSafe technology is not implemented as a compiler<br />

extension, but instead takes advantage of a feature of the dynamic loader that<br />

causes a dynamic library to be preloaded with every executable. Using LibSafe does<br />

not require the source code for the programs it protects, and it can be deployed on a<br />

system-wide basis.<br />

LibSafe replaces the implementation of several standard functions that are known to<br />

be vulnerable to buffer overflows, such as gets( ), strcpy( ), and scanf( ). The<br />

replacement implementations attempt to compute the maximum possible size of a<br />

statically allocated buffer used as a destination buffer for writing using a GCC builtin<br />

function that returns the address of the frame pointer. That address is normally<br />

the first piece of information on the stack after local variables. If an attempt is made<br />

to write more than the estimated size of the buffer, the program is terminated.<br />

Unfortunately, there are several problems with the approach taken by LibSafe. First,<br />

it cannot accurately compute the size of a buffer; the best it can do is limit the size of<br />

the buffer to the difference between the start of the buffer and the frame pointer. Second,<br />

LibSafe’s protections will not work with programs that were compiled using the<br />

-fomit-frame-pointer flag to GCC, an optimization that causes the compiler not to<br />

put a frame pointer on the stack. Although relatively useless, this is a popular optimization<br />

for programmers to employ. Finally, LibSafe will not work on setuid binaries<br />

without static linking or a similar trick.<br />

In addition to providing protection against conventional stack-smashing attacks, the<br />

newest versions of LibSafe also provide some protection against format-string attacks<br />

84 | Chapter 3: Input Validation<br />

This is the Title of the Book, eMatter Edition<br />

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!