Detecting past and present intrusions through
Download
Report
Transcript Detecting past and present intrusions through
Detecting past and present
intrusions through vulnerabilityspecific predicates
Ashlesha Joshi, Sam King,
George Dunlap, and Peter Chen
University of Michigan
Motivation
vulnerability
introduced
vulnerability
discovered
patch
released
time
• Software contains bugs, including flaws that may
be exploited by an attacker
• Some time passes before vendor becomes
aware of bug
• Software vendors try to release patches quickly
2
Motivation
vulnerability
introduced
vulnerability
discovered
patch
released
patch
applied
time
• Users don’t always apply patches quickly
– Concerns about unstable patches
– Unacceptable downtime
• Can I somehow protect my system before
I install the patch?
3
Motivation
vulnerability
introduced
patch
released
patch
applied
time
• Was this vulnerability triggered on my
machine in the past?
4
Predicates
• Patch writer knows exactly what conditions
during program execution indicate
triggering of vulnerability
• Use this knowledge to write exploitgeneric, vulnerability-specific predicates
that check these conditions
– No false positives or false negatives
5
An example
1
char *str = some_string;
2
int
length = strlen (str);
3
char buf [BUFSIZE];
4
strcpy(buf,str);
// D’oh!
Predicate:
(length >= BUFSIZE)
6
Approach
“past”
vulnerability
introduced
Using replay, detect
if vulnerability was
triggered in past
“present”
patch
released
patch
applied
time
Monitor ongoing execution to
detect and respond to attempts
to trigger vulnerability
7
Goals
The system must…
1. Not perturb the target software
2. Work for both OS and application-level
vulnerabilities
3. Allow predicates to be installed dynamically
4. Allow predicates to be written easily
5. Have low overhead
8
Challenge #1: Where do predicates
execute?
application
application
predicate
engine
operating system
hardware
predicate
engine
predicate
engine
OS
hardware
9
IntroVirt structure
predicates
application
application
guest OS
state
control
predicate
engine
intrusions
detected
VMM
host OS
hardware
10
Challenge #2: Semantic gap
Problem: VMM exposes guest state at the wrong
level of abstraction
– It gives us registers, memory locations, disk blocks, …
– We want program variables, files, …
1
2
3
uid = getuid();
// forget to check group membership
perform privileged action
Predicate
– Perform missing authentication, e.g., read /etc/group
11
Bridging the semantic gap
• How could the programmer write this predicate?
– Determine memory location where uid is stored; if
page not resident, read from disk; read value of uid;
traverse guest OS file system structures to see if
/etc/group in file cache, if so, read from memory; if
not, traverse FS structures to see which disk blocks
contain it, then read blocks from disk; …
– i.e., emulate guest functionality
• Our solution: call guest code
– Leverages existing guest code that does what we
want
– Here, we cause the guest itself to read the file and
check group membership
12
Challenge #3: Avoiding
perturbations to target state
• Calling guest functions perturbs target
• Solution: use checkpoint and restore
– Take a checkpoint before changing guest
state
– Restore to checkpoint after predicate
execution
• Also protects from (buggy) predicates that
modify guest state incorrectly
13
Challenge #4: Preemptions
between the predicate and the bug
1
if (access(file, W_OK)) {
Predicate:
2
unlink(file);
(!access(file, W_OK))
3
}
relink(file);
relink(file);
• Check in line 1 should be atomic with use
in line 2
14
Predicate refresh
• Detect and respond to race
– “Predicate refresh”
– Observation: in uniprocessors, a scheduling
event must occur before any other process
can run
– Re-execute predicate on scheduling events to
detect relevant changes in state
15
Predicate engine functionality
• Translate symbolic information from guest
– Parse debugging information
• Allow predicates to control guest execution
– Breakpoints
• Read guest state
• Call guest functions
– Manipulate guest stack and registers
• Checkpoint and restore
• Guarantee safety
16
Predicates for applications
• Need additional support for application
predicates
– Processes are created and destroyed
– Shared libraries can be mapped in different
locations of application address space
– Memory pages are not always resident
• Use kernel predicates in fork, exec, exit,
mmap, try_to_swap_out
17
Predicate for CAN-2003-0961
Actual Patch:
if((addr + len) > TASK_SIZE || (addr + len) < addr)
return –EINVAL;
Predicate:
registerBreak(“mmap.c:1044:begin”, brkEventHandler);
void brkEventHandler() {
unsigned long addr = readVar(“addr”);
unsigned long len = readVar(“len”);
if((addr+len) > TASK_SIZE || (addr+len) < addr) {
cout << “brk bug triggered” << endl;
}
}
18
“find” race condition
find /tmp –atime +3 –exec rm –f – {} \;
“identify old file”
“delete old file”
• Run as root
• Delete all files in /tmp that haven’t been
accessed in past 3 days (“old files”)
• Problem: file pointed to by filename may
change between time of identification and
time of deletion
19
“find” predicate
find /tmp –atime +3
“identify old file”
–exec rm –f – {} \;
“delete old file”
Save inode number of file
1. Get inode # of file
2. Compare with saved
inode #
3. Enable predicate refresh
Predicate refresh
Ensure the inode # of the file stays the same
20
Experience
• Wrote predicates for 20 real vulnerabilities (Linux
kernel, bind, emacs, gv, imapd, OpenSSL, php,
smbd, squid, wu-ftpd, xpdf)
– Easy to write once vulnerability is understood
– Length and complexity comparable to patch
– Most are simple, e.g., just read a few variables
• Overhead for most predicates is less than 10%
– Many predicates are on infrequently executed code
paths
– Frequently executed predicates are simple and fast
– Checkpoint/restore adds 5ms
21
Usage
• Vendors distribute predicates along with patches
• Users can install and run in past and present
• For past attacks
– Alert user; take corrective measures
• For present attacks, lots of possibilities
– Alert, kill process, halt machine, drop offending
connection, imitate patch, install patch, …
– For anything other than “alert”, you must trust the
predicate
22
Limitations and future work
• Predicates change timing
• Software breakpoints
• Current implementation only works on
native code
• Only works for uniprocessors
– ReVirt
– Predicate refresh
• Predicates must be written by hand
23
Related work
• VM introspection [Rosenblum97]
• VM introspection for intrusion detection
[Garfinkel03]
• Shield [Wang04]
• Vigilante [Costa05]
24
Conclusions
• Vulnerability-specific predicates detect
triggering of software vulnerabilities
• IntroVirt predicate engine
– Simple to write general-purpose predicates
– No perturbations in state
• Alert users about past attacks
• Detect and respond to attacks in the
present
25