Buffer Overflows in C
Vulnerabilities, Attacks, and Mitigations |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
main(int argc, char* argv[])
)
void operation(int array[]) { int length = sizeof(array) / sizeof(array[0]); for (int i=0; i<length; i++) { // Operate on array[i] } }
array
is a parameter and, so, is a
pointer typesizeof(array)
is the size of an
int *
, not the size of the array-1
in an array of non-negative
integers)char
and
wchar_t
'\0'
)gets()
gets()
to read characters (until it reaches a
newline or end-of-stream character)char line[81]; gets(line);
strcpy()
strcpy()
int main(int argc, char* argv[]) { char file_name[65]; char *temp; temp = argv[1] ? argv[1] : ""; strcpy(file_name, temp); }
strcat()
strcat()
to append a source string to
a target stringsprintf()
sprintf()
to create a (formatted) stringchar line[81]; sprintf(line, "%2d: %s\n", i, user_input);
sprintf()
assumes that the buffer it is passed
is large enough and the attacker might provide a string that
is too long (i.e., longer than 80 - 2 - 2 - 1 = 75
characters in this example)strncpy()
to copy the first
n
characters
from the source to the target when the source contains
n
or more characters (which results in a non-null
terminated string)strlen()
uses the null character to determine the
length of the string so any function that uses
strlen()
will have problemsstrcpy()
) iterate until
a null character is encountered so will have problems
char a[10], b[10]; strncpy(a, "0123456789", 10); // a will not be null-terminated strcpy(b, a); // b will probably overflow
... char buffer[BUFFER_SIZE]; long value = ...; long* p = ...; strncpy(buffer, argv[1], length); // Potential overflow into p *p = value; // Assign value to the address pointed to by p ...
... static int value = ...; static char buffer[BUFFER_SIZE]; static void (*f)(int i); f = &some_function; strncpy(buffer, argv[1], length); // Potential overflow into f (void)(*f)(value); // Execute the code pointed to by f ...
#include <stdio.h> #include <string.h> char eid[9]; // 8 characters plus '\0' int grade; int main(int argc, char* argv[]) { // Initialize strcpy(eid, "bernstdh"); grade = 100; printf("EID: %8s Grade: %d\n", eid, grade); // Copy user input into the eid strcpy(eid, "bernstdh \x08\x08"); // 0x08 is ASCII backspace printf("EID: %8s Grade: %d\n", eid, grade); }
Address of eid: 0x0804a030
Address of grade: 0x0804a024
eid
only requires 9 bytes, space
actually exists for 12 (for alignment reasons)