160 likes | 170 Views
This article explains what buffer overflow is, the various types of attacks related to buffer overflows, and defensive programming techniques to prevent them. It also discusses vulnerable function calls and provides examples of code that can lead to buffer overflow vulnerabilities.
E N D
Buffer Overflow Exploits CS-480b Dick Steflik
What is a buffer overflow? • Memory • global static • heap • malloc( ) , new • Stack • non-static local variabled • value parameters • Buffer is a contiguously allocated chunk of memory • Anytime we put more data into a data structure than it was designed for.
Side Effects • The side effects of a buffer overflow may cause: • the program may work strangely • the program may fail • the program may continue without any noticeable problems
Side Effects Depend on: • How much data was written past the end of the buffer • What data (if any) are overwritten • Whether the program attempts to read data that are overwritten • What data ends up replacing the memory that gets overwritten
Three Basic Attacks • Overrun a static buffer • hurts data but little to no exposure for loss of control • Stack smashing • place attack code in memory, find some sloppy use of the runtime stack, use stack to transfer control to attack code • Heap overflow • much harder to exploit as there isn’t usually a mechanism to gain control
Defensive Programming • The C Standard library has a number of highly susceptible function calls: • gets( ) - reads data from stdin until eof or a newline character • strcpy( ) - copies a string into a buffer, number of chars copied depend on length of source string
strcpy() if you know the size of the destination buffer: if (strlen(src) >= dst_size {/* throw an error */ } else { strcpy(dst, src); } - or - strncpy(dst, src, dst_size-1); dst[dst_size -1] = ‘\0’; /* just to be safe */ -or- /* allocate the destination buffer when you need it */ dst = (char *)malloc(strlen(src) +1); srtcpy(dst, src)
strcat( ) /* same as srtcpy( ) but cancatenates source string to end of a buffer */ /* safer alternative is to use strncat( ) ; still need to insure you don’t */ /* overrun the destination buffer */ strncat(dst, src, dst_size - strlen(dst) -1);
sprintf( ) & vsprintf( ) /* usually used for formatting text but can accidentally cause a buffer overrun */ void main(int argc, char **argv) { char usage[1024]; sprintf(usage, “USAGE: %s -f flag [arg1]\n” , argv[0]); /* this program could easily be subverted by: */ void main( ) { exec1(“/path/to/previous/program”, << really long string here >> , NULL); }
sprintf( ) & vsprintf( ) /* There is no really portable way around this problem, sometimes a snprintf( ) */ /* is provided that lets you specify max number of characters to copy: */ void main(int argc , char **argv) { char usage[1024]; char format_string = “USAGE: %s -f flag [arg1]\n” snprintf(usage, 1024, format_string, argv[0]); } /* asafer way is to specify a precision for each argument */ void main (int argc , char **argv) { char usage[1024]; sprintf(usage, “USAGE: %.1000s -f flag [arg1]\n” , argv[0]); }
scanf( ), sscanf( ), fscanf( ), vfscanf( ) /* these are likewise poorly designed, in this case destination buffers can overflow */ void main(int argc , char **argv) { char buffer[256]; sscanf(argv[0] , %s , &buffer); } /* if the word being scanned is bigger than the buffer size it will overflow, fix the */ /* problem by specifying a precision for the arguement: */ void main(int argc , char **argv) { char buffer[256]; sscanf(argv[0] , “%255s” , &buffer); }
streadd( ) , strecpy( ) strecpy() copies the input string, up to a null byte, to the output string, expanding non-graphic characters to their equivalent C-language escape sequences (for example, \n, \001). This means that to avoid a possible overflow the destination must be 4x bigger than the source streadd() is identical to strecpy(), except that it returns the pointer to the null byte that terminates the output.
strtrns( ) strtrns() transforms string and copies it into result. Any character that appears in old is replaced with the character in the same position in new. The new result is returned. void main(int argc, char **argv) { char lower[ ] = “abcdefg....xyz”; char upper[ ] = “ABCDEFG....XYZ”; char *buffer; if argc <2 { printf(“USAGE: %s arg\n”, argv[0]); return 0; } buffer = (char *)malloc(strlen(argv[1]+1); strtrns(argv[1], lower, upper , buffer); printf(“%s\n” , buffer); }
functions to be wary of: gets( ) strcpy( ) strcat( ) sprintf( ) scanf( ) sscanf( ) fscanf( ) vfscanf( ) vsscanf( ) streadd( ) strecpy( ) strtrns( ) realpath( ) syslog( ) getopt( ) getopt_long( ) getpass( ) getchar( ) fgetc( ) getc( ) read( ) bcopy( ) fgets( ) memcpy( ) snprintf( ) strccpy( ) strcadd( ) strncpy( ) vsnprintf( )