y g
play

y g sws1 1 Attacking the stack Thanks to SysSec and Int. Secure - PowerPoint PPT Presentation

Security bug of the week (in iOS and OS X) y g sws1 1 Attacking the stack Thanks to SysSec and Int. Secure Systems Labs at Vienna University of Technology for some of these slides sws1 2 2 Attacking the stack g We have seen how the


  1. Security bug of the week (in iOS and OS X) y g sws1 1

  2. Attacking the stack Thanks to SysSec and Int. Secure Systems Labs at Vienna University of Technology for some of these slides sws1 2 2

  3. Attacking the stack g We have seen how the stack works. N Now: let’s see how we can abuse this. l t’ h b thi We have already seen how malicious code can deliberately do strange We have already seen how malicious code can deliberately do “strange things” , and manipulate memory anywhere on the heap and stack. Now: let’s see how benign, but buggy code can be manipulated into doing strange things using malicious input We’ll use two techniques for this 1. buffer overflows 2. format strings attacks sws1 3

  4. Abusing the stack g Goals for an attacker 1 1. l leaking data ki d t 2. corrupting data 3. 3. corrupting program execution corrupting program execution This can be 3a) crashing 3b) doing something more interesting In CIA terminology : breaking In CIA terminology : breaking 1. confidentiality of data 2. 2. integrity of data integrity of data 3. integrity of program execution 4. availability (if data is destroyed or program is crashed) sws1 4

  5. 5 Format string attacks sws1

  6. Format strings attacks g • Format strings were discovered (invented?) in 2000 • They provide a way for an attacker to leak or corrupt memory. • Not such a big problem as buffer overflows, as possibilities for format string attacks are easy to spot and remove • Still, a great example of how some harmless looking code can turn out to be vulnerable, and exploitable by an attacker who supplies out to be vulnerable, and exploitable by an attacker who supplies malicious input sws1 6

  7. Leaking data g int main( int argc, char** argv) i t int pincode = 1234; i d 1234 printf(argv[1]); } This program echoes the first program argument. sws1 7

  8. Aside on main(int argc, char** argv) argc is the numbers of arguments, argv are the argument values. argv has type is a char**, so *argv has type char* (ie a string) **argv has type char and using pointer arithmetic argv[i] has type char* , ie a strings yp , g g [ ] argv[i][j] has type char , so effectively argv is an array of strings, or a 2-dimensional array of char ’s ff ti l i f t i 2 di i l f ’ h Note • argv[0] is the name of the executable, so argv[1] is the first real argument • • char** argv can also be written as char **argv char** argv can also be written as char **argv sws1 8

  9. format strings for printf g printf( ”j is %i.\n” , j); // %i t // %i to print integer value i t i t l printf( ”j is %x in hex.\n” , j); // %x to print 4-byte hexadecimal value // p y ”j is %i ” is called a format string Other printing functions, eg snprintf , also accept format strings. Any guess what printf(”j is %x in hex”); p ( j ); does ? It will print the top 4 bytes of the stack sws1 9

  10. Leaking data with format string attack g g int main( int argc, char** argv) i t int pincode = 1234; i d 1234 printf(argv[1]); } This program may leak information from the stack when given malicious input , namely an argument that contains special control characters which are interpreted by printf characters , which are interpreted by printf Eg supplying %x%x%x as input will dump top 12 bytes of the stack g pp y g p p p y sws1 10

  11. Leaking data from memory g y printf( ”j is %s.\n” , str); // %s to print a string, ie a char* // % t i t t i i h * Any guess what printf(”j is %s in hex”); does ? It will interpret the top of the stack as a pointer (an address) and will print the string allocated in memory at that address and will print the string allocated in memory at that address Of course, there might not be a string allocated at that address, and Of course, there might not be a string allocated at that address, and printf simply prints whatever is in memory up to the next null terminator sws1 11

  12. Corrupting data with format string attack g g int j; char* msg; ... h * printf( ”how long is %s anyway %n” , msg, &j); %n causes the number of characters printed to be written to j, here it will write 20+length(msg) Any guess what Any guess what printf(”how long is this %n”); does ? It interprets the top of the stack as an address, and writes a value there sws1 12

  13. Example malicious format strings g Interesting inputs for the string str to attack printf(str) • %x%x%x%x%x%x%x%x will print bytes from the top of the stack will print bytes from the top of the stack • %s will interpret the top bytes of the stack as an address X, and then prints the string starting at that address A in memory, ie. it dumps all memory from A up to the next null terminator all memory from A up to the next null terminator • %n will interpret the top bytes of the stack as an address X, and then writes the number of characters output so far to that address sws1 13

  14. Example really malicious format strings y g An attacker can try to control which address X is used for reading from memory using %s or for writing to memory using %n reading from memory using %s or for writing to memory using %n with specially crafted format strings of the form • \xEF\xCD\xCD\xAB %x %x ... %x %s With the right number of %x characters, this will print the string located at address ABCDCDEF • \xEF\xCD\xCD\xAB %x %x ... %x %n With the right number of % With the right number of %x characters, this will write the number of characters this will write the number of characters printed so far to location ABCDCDEF The tricky things are inserting the right number of %x , and choosing an interesting address sws1 14

  15. stack layout for printf y printf(”blah blah %i %i”, a, b) Recall: string is written upwards %i %i blah blah .... 2nd %i: print this value b 1 t %i 1st %i: print this value i t thi l a pointer to string sws1 15

  16. stack layout for really malicious strings y y g printf(“\xEF\xCD\xCD\xAB %x %x ... %x %s”); With the right number of % With the right number of %x characters, this will print the string characters this will print the string located at address ABCDCDEF %s %x %x %x use this as address for %s EF CD CD AB 3rd %x: print this value 3 d % i t thi l 2nd %x: print this value 1 t % 1st %x: print this value i t thi l pointer to string sws1 16

  17. 17 buffer overflows sws1

  18. Buffer overflows It is easy to make mistakes using arrays or strings • when using array indices we can go outside the array bounds, eg in eg in buffer[i]= c; • when copying strings into arrays this can also happen char buf[8]; sprintf(buf, ”password”); sprintf(buf ”password”); // Does this fit? // Not including the implicit null terminator ! // g p sws1 18

  19. Buffer overflows void vulnerable(char *s){ char msg[10] = "hello"; h [10] "h ll " char buffer[10]; strcpy(buffer, s); // copy s into buffer py( , ); // py } void main( int argc, char** argv) { vulnerable(argv[1]); // argv[1] is first command line argument // argv[1] is first command line argument } What can go wrong here? sws1 19

  20. Buffer overflows to corrupt data or crash By supplying a long argument, the buffer overflows, which can • corrupt data t d t buffer will overflow into other variables on the stack if is too long • crash the program crash the program Why and when exactly does the program crash? The buffer overrun corrupts administration on the stack, esp. • the return address • the stored frame pointer the stored frame pointer Returning from vulnerable causes a segmentation fault if these values point to places outside the correct data segment. sws1 20

  21. Buffer overflow to change a program g g Can attacker do something more interesting than crashing? Yes, supplying a value for ret which will do something interesting Y l i l f t hi h ill d thi i t ti sws1 21

  22. recall: the stack stack Stack during call to f int i frame for for main main(int i){ char *msg =”hello”; char *msg g f(); f(); print (“%i”, i); int return value } return address return address int f(){ saved frame pointer frame pointer stack char p[20]; frame frame int j; for gets(p); f() // NEVER USE gets!! char p[ ] p[ ] return 1; } int j stack pointer sws1 22

  23. recall: the stack stack Stack during call to f int i frame for for main main(int i){ char *msg =”hello”; char *msg g f(); f(); print (“%i”, i); int return value } return address return address int f(){ saved frame pointer stack char p[20]; frame frame int j; for gets(p); f() // NEVER USE gets!! char p[ ] p[ ] return 1; } int j sws1 23

  24. Corrupting the stack (1) g ( ) stack What if we overrun p int i frame for for t to set return address t t dd main to point inside p? char *msg g When f returns, int return value execution will resume corrupted ret corrupted ret with what is written in p , saved frame pointer interpreted as machine stack code code frame frame for f() char p[ ] p[ ] int j sws1 24

Recommend


More recommend