1 / 31

Buffer Overflow

Buffer Overflow. Introduction. On many C implementations, it is possible to corrupt the execution stack by writing past the end of an array. Known as smash the stack. It can cause return from the routine to jump to a random address.

gerard
Télécharger la présentation

Buffer Overflow

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Buffer Overflow

  2. Introduction • On many C implementations, it is possible to corrupt the execution stack by writing past the end of an array. • Known as smash the stack. • It can cause return from the routine to jump to a random address. • Attackers can control the program flow by sending carefully crafted set of input.

  3. Process Memory Organization Lower Memory addresses Text Data Stack Higher Memory addresses Process Memory Regions

  4. Text region • Fixed by the program • Includes code (instructions) • Read only • Data region • Contains initialized and uninitialized data • Static variables are stored here. • Stack region • LIFO

  5. Stack is used to • Dynamically allocate the local variables used in functions. • Pass parameters to the functions. • Return values from the function. • Stack pointer (SP) points to the top of the stack. • The bottom of the stack is at a fixed address. • Consists of logical stack frames that are pushed when calling a function and popped when returning. • Frame pointer (FP) points to a fixed location within a frame.

  6. Let’s see an example • After gcc –S –o example1.s example1.c • Call function is translated to pushl $3 pushl $2 pushl $1 call function

  7. Its pushes the 3 arguments backwards into the stack. • The instruction ‘call’ will push the IP onto the stack. • Procedure prolog pushl %ebp movl %esp, %ebp subl $20, %esp

  8. pushes the FP onto the stack. • Copies the current SP onto EBP, make it the new FP. • Allocates space for the local variables by subtracting their size from SP. • Memory can only be addressed in multiples of the word size. • 5 byte buffer take 8 bytes (2 words). • 10 byte buffer take 12 bytes (3 words). • SP is subtracted by 20

  9. buffer2 buffer1 sfp ret a b c Stack

  10. Buffer Overflows • Result of stuffing more data into a buffer than it can handle. • See the following example: • It copies a string without bounds checking by using strcpy() instead of strncpy(). • Copy the contents of *str into buffer[] until a null character is found.

  11. Buffer[] (16 bytes) is much smaller than *str (256 bytes). • All 250 bytes after buffer in the stack are being overwritten with character ‘A’ (0x41) • Include SFP, RET and even *str. • The return address becomes 0x41414141. • That’s why you get segmentation error when the function returns. buffer sfp ret *str Stack

  12. What is the trick? • Buffer overflow allows us to change the return address of a function. • Add 12 to buffer[]’s address (return address). • Skip pass the assignment to the printf call.

  13. By using a similar technique, a hacker can change the return address, so that the flow control will pass to his code. • The code will be run under the username of the owner of the program. • Usually a shell will be run. • Read the article by Aleph One, to see how the shell code is obtained. • Here is an example to test the shell code.

  14. Writing an Exploit • Suppose we want to “overflow” this program. • Create a program to put the overflow string in an environment variable. • The program takes as parameters a buffer size and an offset from its own stack. • Guess the position of the buffer we want to overflow.

  15. The problem is we need to guess the exactly where the address of our code will start. • A way to increase our chances • Pad the front of our overflow buffer with NOP instructions. • Fill half of the buffer with NOP. • Place the code in the middle. • Then follow it with the return addresses.

  16. If the return address points anywhere in the string of NOPs, they will just get executed until they reach our code. • Further improvement. • Put the code in another place. • The environment variable contains pointer to another environment variable that contains the code. • The environment variables are stored on the stack when the program is started.

  17. If vulnerable is owned by root, we can access the root account. • Trial [mhwong]$ ./exploit4 768 using address: 0xbffff9d8 [mhwong]$ ./vulnerable $RET bash# whoami root bash# Hacker: “Ha! Ha! Ha! …I am the root now!!”

  18. Advanced Buffer Overflow Techniques • Pass through filtering • Programs may filter some characters or converts characters into other characters. • It is much more difficult to write an exploit program, as the normal shell code cannot pass through the filter. • For example, program may convert small letters into capital letters.

  19. Solution • Modify the shell code so that it doesn’t contain small letters. • E.g. \x2f\x62\x69\x6e\x2f\x73\x68 ( /bin/sh) is converted to \x2f\x12\x19\x1e\x2f\x23\x18 • Change the characters back when the shellcode is executed. • Add \0x50 to \x62, \x69, \x6e, and \x68.

  20. Change uid • As programs run with root permission are dangerous, some programs may • Call seteuid(getuid()) at start. • Calls seteuid(0) when needed. #include<string.h> #include<unistd.h> int main(int argc,char **argv) { char buffer[1024]; seteuid(getuid()); if(argc>1) strcpy(buffer,argv[1]); }

  21. One may think that “strcpy(buffer,argv[1])” is OK, as the hacker can only get his own shell. • In fact, the hacker can insert a code which calls setuid(0) in the shellcode to get the root shell. setuid(0); code ---------------------------------------------------------------------------- char code[]= "\x31\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\xb0\x17" /* movb $0x17,%al */ "\xcd\x80"; /* int $0x80 */ ----------------------------------------------------------------------------

  22. Break chroot • If the vulnerable program is chrooted, you can access only chrooted directory. #include<string.h> #include<unistd.h> int main(int argc,char **argv) { char buffer[1024]; chroot("/home/ftp"); chdir("/"); if(argc>1) strcpy(buffer,argv[1]); }

  23. If you can execute the code below, you can break chroot. • Compile and disassemble the above program and then get the shellcode. main() { mkdir("sh",0755); chroot("sh"); /* many "../" */ chroot("../../../../../../../../../../../../../../../../"); }

  24. Open socket • Overflow the buffer in daemon. • Create a shellcode that do the following steps. • Execute a shell • Open a socket • Connect your standard I/O

  25. Techniques of Avoiding Buffer Overflow • Modern Programming Languages • Most modern programming languages are essentially immune to this problem. • Automatically resize arrays. E.g. Perl, Java • Detect and prevent buffer overflows.E.g. Ada95, Java • C language provides no protection against such problems. • C++ can be easily used in ways to cause this problem.

  26. Careful Use of C/C++ Library Functions • avoid using functions that do not check bounds, unless the bounds will never get exceeded. • Avoid strcpy(3), strcat(3), sprintf(3) and gets(3). • These functions can be replaced with strncpy(3), strncat(3), snprintf(3) and fgets(3). • Strlen(3) should be avoided unless you can guarantee that there will be a terminating NUL character.

  27. Static and dynamically allocated buffer • Fix length buffer may be exploitable. • Attacker sets up a really long string. • When the string is truncated, the final result will be what the attacker wanted. • Dynamically (re-)allocate all strings instead of using fixed-size buffers is recommended. • Must be prepared for dynamic allocation to fail. • Designed to be fail-safe when memory is exhausted.

  28. Use newer libraries. • Newer libraries for C include the strlcpy(3) and strlcat(3). • Take full size of the destination buffer as a parameter. • Guarantee to NUL-terminate the result. • Strlcpy copies up to size-1 characters from the NUL-terminated string src to dst and NUL-terminates the result. • The strlcat function appends the NUL-terminated string src to the end of dst. It will append at most size-strlen(dst) –1 bytes, and NUL-terminates the results.

  29. Compilation solutions in C/C++ • Newer compilers perform bounds-checking. • But it is not wise to depend on this technique as your sole defense. • Only provide partial defense against buffer overflows. • Non-executable user stack area • It is possible to modify the kernel of any OS so that the stack segment is not executable. • However, attackers can simply force the system to call other “interesting” locations already in the program.

  30. Avoid installing set-user-id programs • Program is not running suid root. • User cannot achieve greater access levels. • However, you never know who is going to take your program and set the suid bit on the binary. • It is also possible that users of your software with no privileges at all. That means any successful buffer overflow attack will give them more privileges.

  31. Reference • Aleph One, “Smashing The Stack for Fun and Profit”, Phrack 49 Volume 7, Issue 49, File 14 of 16. • Taeho Oh, “Advanced buffer overflow exploit”.

More Related