Section 3.4: Buffer Overflow Attack: Defense Techniques
Section 3.4: Buffer Overflow Attack: Defense Techniques
4:
Buffer Overflow Attack:
Defense Techniques
1
Acknowledgement
This lecture uses some contents from:
Dr. Erik Poll : software security
Dr. Dawn Song: CS161: computer security
Buffer Overflow Prevention
Buffer Overflow
Dr. Ninghui Li: CS426: Computer Security
2
Countermeasures
We can take countermeasures at different
points in time
before we even begin programming
during development
when testing
when executing code
to prevent, to detect – at (pre)compile
time or at runtime -, and to migitate
problems with buffer overflows
3
Preventing Buffer Overflow Attacks
Non-executable stack
Static source code analysis.
Run time checking: StackGuard, Libsafe,
SafeC, (Purify).
Randomization.
Type safe languages (Java, ML).
Detection deviation of program behavior
Sandboxing
Access control …
4
Prevention
Don’t use C or C++ (use type-safe language)
Legacy code
Practical?
Better programmer awareness & training
Building Secure Software, J. Viega & G. McGraw,
2002
Writing Secure Code, M. Howard & D. LeBlanc, 2002
19 deadly sins of software security, M. Howard, D
LeBlanc & J. Viega, 2005
Secure programming for Linux and UNIX HOWTO,
D. Wheeler, www.dwheeler.com/secure-programs
Secure C coding, T. Sirainen
www.irccrew.org/~cras/security/c-guide.html
5
Dangerous C system calls
source: Building secure software, J. Viega & G. McGraw, 2002
6
Secure Coding
7
Prevention – use better string libraries
there is a choice between using statically
vs dynamically allocated buffers
static approach easy to get wrong, and
chopping user input may still have unwanted
effects
dynamic approach susceptible to out-of-
memory errors, and need for failing safely
8
Better string libraries
libsafe.h provides safer, modified versions of eg strcpy
strlcpy(dst,src,size) and strlcat(dst,src,size) with size
the size of dst, not the maximum length copied.
Used in OpenBSD
glib.h provides Gstring type for dynamically growing
null-terminated strings in C
but failure to allocate will result in crash that cannot be
intercepted, which may not be acceptable
Strsafe.h by Microsoft guarantees null-termination and
always takes destination size as argument
C++ string class
data() and c-str()return low level C strings, ie char*, with result
of data()is not always null-terminated on all platforms...
9
Dynamic countermeasures
Protection by kernel
Non-executable stack memory (NOEXEC)
prevents attacker executing her code
Address space layout randomisation (ASLR)
generally makes attacker's life harder
E.g., harder to get return address place and injected
code address
Protection inserted by the compiler
to prevent or detect malicious changes to the
stack
Neither prevents against heap overflows
10
Bugs to Detect in Source Code Analysis
Some examples
• Crash Causing Defects • Uninitialized variables
• Null pointer dereference • Invalid use of negative values
• Use after free • Passing large parameters by value
• Double free • Underallocations of dynamic data
• Array indexing errors • Memory leaks
• Mismatched array new/delete • File handle leaks
• Potential stack overrun • Network resource leaks
• Potential heap overrun • Unused values
• Return pointers to local variables • Unhandled return codes
• Logically inconsistent code • Use of invalid iterators
11
Marking stack as non-execute
Basic stack exploit can be prevented by
marking stack segment as non-executable or
randomizing stack location.
Then injected code on stack cannot run
Code patches exist for Linux and Solaris
E.g., our olympus.eecs.ucf.edu has patched for stack
radnomization
Problems:
Does not block more general overflow exploits:
Overflow on heap, overflow func pointer
Does not defend against `return-to-libc’ exploit.
Some apps need executable stack (e.g. LISP
interpreters).
12
Randomization Techniques
For successful exploit, the attacker needs to
know where to jump to, i.e.,
Stack layout for stack smashing attacks
Heap layout for code injection in heap
Shared library entry points for exploits using
shared library
Randomization Techniques for Software
Security
Randomize system internal details
Memory layout
Internal interfaces
Improve software system security
Reduce attacker knowledge of system detail to thwart
exploit
Level of indirection as access control
13
Randomize Memory Layout (I)
Randomize stack starting point
Modify execve() system call in Linux
kernel
Similar techniques apply to randomize
heap starting point
Randomize heap starting point
Randomize variable layout
14
Randomize Memory Layout (II)
Handle a variety of memory safety
vulnerabilities
Buffer overruns
Format string vulnerabilities
Integer overflow
Double free
Simple & Efficient
Extremely low performance overhead
Problems
Attacks can still happen
Overwrite data
May crash the program
Attacks may learn the randomization secret
Format string attacks
15
Dynamic countermeasure: stackGuard
Solution: StackGuard
Run time tests for stack integrity.
Embed “canaries” in stack frames and
verify their integrity prior to function
return.
16
Canary Types
Random canary:
Choose random string at program startup.
Insert canary string into every stack
frame.
Verify canary before returning from
function.
To corrupt random canary, attacker must
learn the random string.
17
Canary Types
Additional countermeasures:
use a random value for the canary
XOR this random value with the return
address
include string termination characters in the
canary value (why?)
18
StackGuard implemented as a GCC
patch
Program must be recompiled
Low performance effects: 8% foR
Apache
Problem
Only protect stack activation record
(return address, saved ebp value)
19
Purify
A tool that developers and testers use
to find memory leaks and access
errors.
Detects the following at the point of
occurrence:
reads or writes to freed memory.
reads or writes beyond an array boundary.
reads from uninitialized memory.
20
Purify - Catching Array Bounds Violations
21
Further improvements
PointGuard
also protects other data values, eg function
pointers, with canaries
Higher performance impact than stackGuard
ProPolice's Stack Smashing Protection
(SSP) by IBM
also re-orders stack elements to reduce potential
for trouble
Stackshield has a special stack for return
addresses, and can disallow function
pointers to the data segment
22
Dynamic countermeasures
libsafe library prevents buffer overruns
beyond current stack frame in the
dangerous functions it redefines
Dynamically loaded library.
Intercepts calls to strcpy (dest, src)
Validates sufficient space in current stack
frame:
|frame-pointer – dest| > strlen(src)
If so, does strcpy.
23
Dynamic countermeasures
libverify enhancement of libsafe keeps
copies of the stack return address on the
heap, and checks if these match
24
None of these protections are perfect!
even if attacks to return addresses are
caught, integrity of other data other than the
stack can still be abused
clever attacks may leave canaries intact
where do you store the "master" canary value
a cleverer attack could change it
none of this protects against heap overflows
eg buffer overflow within a struct...
New proposed non-control attack
25
Summary
Buffer overflows are the top security
vulnerability
Any C(++) code acting on untrusted input is at
risk
Getting rid of buffer overflow weaknesses in C(+
+) code is hard (and may prove to be
impossible)
Ongoing arms race between countermeasures and
ever more clever attacks.
Attacks are not only getting cleverer, using them is
getting easier
26