Beyond Stack Smashing: Recent Advances in Exploiting Buffer Overruns Jonathan Pincus

Download Report

Transcript Beyond Stack Smashing: Recent Advances in Exploiting Buffer Overruns Jonathan Pincus

Beyond Stack Smashing:
Recent Advances in Exploiting
Buffer Overruns
Jonathan Pincus
Microsoft Research
Brandon Baker
Microsoft
Carl Hartung
CSCI 7143: Secure Sensor Networks
Overview

Buffer Overruns


Basics
Techniques



Stack Smashing
Arc Injection
Pointer Subterfuge






Function-pointer Clobbering
Data Pointer Modification
Exception-handler Hijacking
VPTR Smashing
Heap Smashing
Conclusions
What is a Buffer Overrun?
When a program attempts to read or write
beyond the end of a bounded array (also
known as a buffer)
Typically, attackers use this to modify a
return address saved on the stack to point
to code residing in a stack buffer at a
known location
Examples

Stack Buffer Overrun
void f1a (void * arg, size_t len) {
char buff[100];
memcpy(buf, arg, len)
/* buffer overrun if len > 100 */
…
return
}

Heap Buffer Overrun
void f1b ( void * arg, size_t len){
char * ptr = malloc(100);
if (ptr == NULL_ return;
memcpy(ptr, arg, len);
/* buffer overrun if len > 100 */
…
return;
}
How does it work?
void function(char *str)
{
char buffer[16];
strcpy(buffer,str);
}
top of stack
buffer
[
sfp ret *str
][ ][ ][ ]
bottom of
stack
How does it work? – cont’d
int main (){
char large_string[256];
..fill ‘large_string’.
function(large_string);
}
top of stack
buffer
sfp ret *str
[sssssssssss][ssss][0xD8][….]
bottom of
stack
Stack Smashing
void f1a (void * arg, size_t len) {
char buff[100];
memcpy(buf, arg, len)
/* buffer overrun if len > 100 */
…
return
}


Attacker must provide a value for arg that contains an
executable payload and the address here the payload
will be loaded into memory (the address of buff).
Program control transferred to buff rather than return to
the calling procedure.
Stack Smashing -- Enhancements

Trampolining



If buff’s absolute address is not known ahead of time, an
attacker can use a program register R containing a value relative
to buff by first transferring control to a sequence of instructions
that indirectly transfers via R.
Find the address on the stack using instructions pop/pop/return
Separating payload (attacker’s code) from the buffer
overrun operation.


Storing code in an environment variable
Good for overrunning small buffers
Arc Injection


Attacker supplies data that, when a program
operates on that data, causes a desired (by the
attacker) effect.
Uses a stack buffer overrun to modify return
address to point to a location already in the
program’s address space.


Usually the system function in the C stdlib.
Useful when the program has non-executable
stacks
Pointer Subterfuge


Involves modifying a pointer’s value.
Many different attacks




Function-pointer Clobbering
Data Pointer Modification
Exception-handler Hijacking
VPTR Smashing
Function-pointer Clobbering

Modifying a function pointer to point to attackers
code.
void f3 (void * arg, size_t len){
char buff[100];
void (*f) () = …;
memcpy(buff, arg, len); /* buffer overrun */
f();
…return; }


Use overrun to set f to buff, and call will send
control to code in buff
Can combine with Arc to point F to system call.
Data-pointer modification
void f4(void * arg, size_t len){
char buff[100]; long val = …;
long *ptr = …;
extern void (*f)();
memcpy(buff, arg, len)
/* overrun! */
*ptr = val;
f();
…
return;}

Allows attacker to modify memory locations
 Can use *ptr = val to assign any 4 bytes of memory
Exception-handler hijacking

When an exception is generated, Windows examines a
linked list of exception handlers (registered by program
when it starts) and invokes one or more of them via
function pointers stored in the list. Because the list
entries are stored on the stack, it is possible to replace
the exception-handler function pointer with a buffer
overflow.

The known variations of this vulnerability are supposedly fixed in
WindowsXP SP2.
VPTR smashing

VTBL (associated with each class) is an array of
function pointers used at runtime to implement
dynamic dispatch.


Objects point to appropriate VTBL with virtual pointers
(VPTR) stored as part of the object’s header.
Replacing the VPTR with a pointer to an attacker
supplied VTBL transfers control when the next virtual
function is invoked.
Can apply to both stack and heap overruns
Heap smashing



Allocators keep headers for each heap block chained
together in a doublely linked list of allocated and freed
blocks.
If you have three adjacent blocks X, Y, Z; an overrun of X
into Y can corrupt pointers in Y’s header, and lead to
modification of arbitrary memory locations when Y is
freed.
More complicated because:



Attacker typically doesn’t know the heap block’s location ahead
of time
Difficult to predict when heap-free operation will occur.
Difficult (especially in with multiple threads) to predict whether
the next block has been allocated at time of overrun.
Conclusions


Buffer overruns are likely to be continued source of
potential vulnerabilities.
New techniques invalidate old assumptions:





Arc injection needs no injected code
Pointer subterfuge doesn’t overwrite return addresses
Heap smashing and pointer subterfuge show not just the stack
that’s vulnerable.
Developers need to be cautious of ‘assumptions’.
Arms race continues.