buffer overflow defenses
play

Buffer overflow defenses Deian Stefan Some slides adopted from - PowerPoint PPT Presentation

CSE 127: Computer Security Buffer overflow defenses Deian Stefan Some slides adopted from Nadia Heninger, Kirill Levchenko, Stefan Savage, and Stephen Checkoway Today: mitigating buffer overflows Lecture objectives: Understand how to


  1. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  2. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  3. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp Figured out size of buffer!

  4. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaf41 parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  5. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaf41 parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  6. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaf42 parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  7. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaf42 parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  8. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  9. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  10. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadc41fe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  11. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadc41fe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  12. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  13. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  14. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  15. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp

  16. Perfect for brute forcing • Forked process has same saved ret memory layout and contents as saved ebp 0xbadcaffe parent, including canary values! %ebp 0x41414141 • The fork on crash lets us try 0x41414141 different canary values 0x41414141 %esp Figured out size of canary!

  17. Buffer overflow mitigations • Avoid unsafe functions (last lecture) • Stack canaries • Separate control stack • Memory writable or executable, not both (W^X) • Address space layout randomization (ASLR)

  18. Separate control stack Problem: Control data is stored next to data Solution: Bridge the implementation and abstraction gap: 
 separate the control stack User stack arg i+1 Control stack arg i %ebp local 1 saved ret local 2 saved ebp %esp %esp’

  19. Safe stack Problem: Unsafe data structures stored next to control Solution: Move unsafe data structures to separate stack Safe stack arg i+1 arg i Unsafe stack saved ret saved ebp %ebp &i local var buf local var %esp’ %esp

  20. How do we implement these? • There is no actual separate stack, we only have linear memory and loads/store instructions • Put the safe/separate stack in a random place in the address space ➤ Location of control/stack stack is secret

  21. How do we defeat this? Find a function pointer and overwrite it to point to shellcode!

  22. Buffer overflow mitigations • Avoid unsafe functions (last lecture) • Stack canaries • Separate control stack • Memory writable or executable, not both (W^X) • Address space layout randomization (ASLR)

  23. W^X: write XOR execute • Goal: prevent execution of shell code from the stack • Insight: use memory page permission bits ➤ Use MMU to ensure memory cannot be both writeable and executable at same time • Many names for same idea: ➤ XN: eXecute Never ➤ W^X: Write XOR eXecute ➤ DEP: Data Execution Prevention

  24. Recall our memory layout kernel user stack shared libs runtime heap static data segment text segment unused

  25. Recall our memory layout kernel user stack rw shared libs rx runtime heap rw static data rw segment text segment rx unused

  26. Recall our memory layout kernel user stack rw saved ret saved ebp shared libs rx %ebp buf[0-3] runtime heap rw %esp static data rw segment text segment rx unused

  27. Recall our memory layout kernel shellcode user stack rw hijacked ret shared libs rx %ebp runtime heap rw %esp static data rw segment text segment rx unused

  28. Recall our memory layout kernel shellcode user stack rw hijacked ret shared libs rx %ebp runtime heap rw %esp static data rw segment text segment rx unused

  29. W^X tradeoffs • Easy to deploy: No code changes or recompilation • Fast: Enforced in hardware ➤ Downside: what do you do on embedded devices? • Some pages need to be both writeable and executable ➤ Why?

  30. How can we defeat W^X? • Can still write to return address stored on the stack ➤ Jump to existing code • Search executable for code that does what you want ➤ E.g. if program calls system(“/bin/sh”) you’re done ➤ libc is a good source of code (return-into-libc attacks)

  31. Normal system() call &cmd saved ret %esp

  32. Redirecting control flow to system() • We redirected control flow in previous lecture to baz() saved ret saved ebp • Calling system() is the same, %ebp buf[4-7] but need to have argument to buff[0-3] %esp string “/bin/sh” on stack

  33. saved ret saved ebp %ebp buf[4-7] buff[0-3] %esp

  34. saved ret ???? %ebp %esp

  35. &system ???? %ebp %esp

  36. &cmd &exit &system ???? %ebp %esp

  37. “/bin/sh” &cmd &exit &system ???? %ebp %esp

  38. “/bin/sh” &cmd &exit &system ???? %ebp %esp mov %ebp, %esp leave = pop %ebp

  39. “/bin/sh” &cmd &exit &system ???? %esp, %ebp mov %ebp, %esp leave = pop %ebp

  40. %ebp ???? “/bin/sh” &cmd &exit &system %esp ???? mov %ebp, %esp leave = pop %ebp

  41. %ebp ???? “/bin/sh” &cmd &exit &system %esp ???? ret = pop %eip

  42. %ebp ???? “/bin/sh” &cmd &exit %esp &system ???? %eip &system ret = pop %eip

  43. To system this looks like a normal call “/bin/sh” arg0 &cmd saved ret &exit %esp

  44. But I want to execute shellcode, not just call system() !

  45. Can we inject code?

  46. Can we inject code?

  47. Can we inject code? • Just-in-time compilers produce data that becomes executable code • JIT spraying: ➤ 1. Spray heap with shellcode (and NOP slides) ➤ 2. Overflow code pointer to point to spray area

  48. What does JIT shellcode look like?

  49. What does JIT shellcode look like?

  50. What does JIT shellcode look like?

  51. Buffer overflow mitigations • Avoid unsafe functions (last lecture) • Stack canaries • Separate control stack • Memory writable or executable, not both (W^X) • Address space layout randomization (ASLR)

  52. ASLR kernel user stack • Traditional exploits need precise addresses ➤ stack-based overflows: shellcode shared libs ➤ return-into-libc: library addresses • Insight: Make it harder for attacker to runtime heap guess location of shellcode/libc by static data randomizing the address of different segment memory regions text segment unused

Recommend


More recommend