confidence 2014: andreas bogk: preventing violation of memory safety in c/c++ software

36
TOP SECRET//HCS/SI/TK//ORCON/NOFORN Applying science to eliminate 100% of buffer overflows CONFidence, Krakow, 2014 Andreas Bogk, [email protected], @andreasdotorg

Upload: proidea

Post on 09-May-2015

221 views

Category:

Technology


2 download

DESCRIPTION

The hacker community has a lot of words for situations in which access to the wrong part of memory leads to an exploitable vulnerability: buffer overflow, integer overflows, stack smashing, heap overflow, use-after-free, double free and so on. Different words are used because the techniques to trigger the faulty memory access and to subsequently use that to gain code execution vary, but they all share a common root cause: violation of spatial and temporal memory safety. If one looks at the C/C++ standard, the situations that tend to be exploitable are “unspecified”. Usually, compiler writers take that as an excuse to cut corners, to gain that extra bit of performance in the benchmarks. Because, you know, who cares you’re exploitable when you make a mistake, look how fast it is! However, the standards also allow the compiler to introduce safety checks, to see whether access to a pointer actually touches the inside of an allocated object instead of the outside (spatial memory safety), and to make sure that the pointer being accessed actually points to an object that has been allocated, but not yet been freed again (temporal memory safety). Such compilers do exist, in the form of LLVM with specialized optimizer passes that introduce runtime safety checks. This talk will look into the details of the implementation, the performance impact, practical handling, and of course, whether it really delivers the promised 100% protection against buffer overflows.

TRANSCRIPT

Page 1: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Applying science to eliminate 100% of buffer overflows

CONFidence, Krakow, 2014Andreas Bogk, [email protected], @andreasdotorg

Page 2: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

The problem

void foo (char* arg) {

  char some[16];

  char* p = some;

  while (*p++ = *arg++);

}

Page 3: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

The problem: spatial memory safety

void foo (char* arg) {

  char some[16];

  char* p = some;

  while (*p++ = *arg++);

}

Page 4: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

The other problem

void bar (char* arg) {

  char* p = malloc(16);

  free(p);

  while (*p++ = *arg++);

  free(p);

}

Page 5: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

The other problem:temporal memory safety

void bar (char* arg) {

  char* p = malloc(16);

  free(p);

  while (*p++ = *arg++);

  free(p);

}

Page 6: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Existing approaches

● Use a safe language!

● Mitigations: ASLR, DEP, stack canaries

● Memory debugging tools:

– Valgrind

– gcc and llvm memory sanitizer

– SAFEcode

– Ccured

– SafeC

– Cyclone

– Etc...

Page 7: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

A word on notation

red.is­>compiler_generated(code);

black.is­>user_written(code);

Page 8: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Object-based approach

if (IsPoisoned(address)) {

  ReportError(address);

}

*address = ...;  // or: ... = *address;

Page 9: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Intrastructural safety

struct {

  char id[8];

  int account_balance;

} bank_account;

char* ptr = &(bank_account.id);

strcpy(ptr, "overflow...");

Page 10: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Pointer-based approach

● Every pointer represented by three words: pointer value, base, bound

● We call that a „fat pointer“

Page 11: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Meet SoftBoundCETS

● Santosh Nagarakatte, Jianzhou Zhao, Milo M. K. Martin, Steve Zdancewic; UPenn

● SoftBound: spatial safety

● CETS: temporal safety

● Uses disjoint fat pointers

● Proof of correctness (but caveat emptor)

● Implemented as LLVM optimizer pass

Page 12: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Meet SoftBoundCETS

● Source compatibility

● Complete coverage

● Separate compilation

● Low overhead

Page 13: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: instrumenting dereference

check(ptr, ptr_base, ptr_bound,

      sizeof(*ptr));

value = *ptr;

Page 14: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: implementation of check

void check(ptr, base, bound, size) {

  if ((ptr < base) 

      || (ptr + size > bound)) {

    abort();

  }

}

Page 15: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

„Beware of bugs in the above code; I have only proved it correct, not tried it.“

– Donald E. Knuth

Page 16: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: correct implementation of check

void check(ptr, base, bound, size) {

  if ((ptr < base) 

      || (ptr + size > bound)

      || (ptr + size < ptr)) {

    abort();

  }

}

Page 17: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: memory allocation

ptr = malloc(size);

ptr_base = ptr;

ptr_bound = ptr + size;

if (ptr == NULL) ptr_bound = NULL;

Page 18: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: stack allocation

int array[100];

ptr = &array;

ptr_base = &array[0];

ptr_bound = ptr_base +

              sizeof(array);

Page 19: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: Pointer arithmetic

newptr = ptr + index;

// or &ptr[index]

newptr_base = ptr_base;

newptr_bound = ptr_bound;

Page 20: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: narrowing

struct { ... int num; ... } *n;

...

p = &(n­>num);

p_base = max(&(n­>num), n_base);

p_bound = min(p_base + sizeof(n­>num),

              n_bound);

Page 21: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: more narrowing

struct { ... int arr[5]; ... } *n;

...

p = &(n­>arr[2]);

p_base = max(&(n­>arr), n_base);

p_bound = min(p_base + sizeof(n­>arr), 

              n_bound);

Page 22: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: loading metadata

int** ptr;

int* new_ptr;

...

check(ptr, ptr_base, ptr_bound,sizeof(*ptr));

newptr = *ptr;

newptr_base = table_lookup(ptr)­>base;

newptr_bound = table_lookup(ptr)­>bound;

Page 23: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: storing metadata

int** ptr;

int* new_ptr;

...

check(ptr, ptr_base, ptr_bound, sizeof(*ptr));

(*ptr) = new_ptr;

table_lookup(ptr)­>base = newptr_base;

table_lookup(ptr)­>bound = newptr_bound;

Page 24: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: augmenting function calls

int func(char* s)

{ ... }

int value = func(ptr);

int func(char* s,void* s_base,void* s_bound)

{ ... }

int value = func(ptr, ptr_base, ptr_bound);

Page 25: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Spatial: loose ends

● Global variables

● Separate compilation and library code

● Memcpy()

● Function pointers

● Creating pointers from integers

● Arbitrary casts and unions

● Variable argument functions

Page 26: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Temporal: allocation

ptr = malloc(size);

ptr_key = next_key++;

ptr_lock_addr = allocate_lock();

*(ptr_lock_addr) = ptr_key;

freeable_ptrs_map.insert(ptr_key, ptr);

Page 27: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Temporal: free

if (freeable_ptrs_map.lookup(ptr_key) != ptr) {

  abort();

}

freeable_ptrs_map.remove(ptr_key);

free(ptr);

*(ptr_lock_addr) = INVALID_KEY;

deallocate_lock(ptr_lock_addr);

Page 28: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Temporal: dereference check

if (ptr_key != *ptr_lock_addr) { abort(); }

value = *ptr;

Page 29: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Temporal: pointer arithmetic

newptr = ptr + offset; 

// or &ptr[index]

newptr_key = ptr_key;

newptr_lock_addr = ptr_lock_addr;

Page 30: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Temporal: propagating metadata

int** ptr;

int* newptr;

if (ptr_key != *ptr_lock_addr) { abort(); }

newptr = *ptr;

newptr_key = table_lookup(ptr)­>key;

newptr_lock_addr = table_lookup(ptr)­>lock_addr;

Page 31: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Temporal: propagating metadata

int** ptr;

int* newptr;

if (ptr_key != *ptr_lock_addr) { abort(); }

(*ptr) = newptr;

table_lookup(ptr)­>key = newptr_key;

table_lookup(ptr)­>lock_addr = newptr_lock_addr;

Page 32: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Temporal: globals

int var; // global variable

ptr = &var;

ptr_key = GLOBAL_KEY;

ptr_lock_addr = GLOBAL_LOCK_ADDR;

Page 33: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Temporal: loose ends

● Threads. Shared state is evil. Zalgo, etc.

● Shared memory. Shared state... see above.

Page 34: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Own contribution

● Introduced two function attributes to control instrumentation process

● Ported SoftBoundCETS to FreeBSD

● Instrumented FreeBSD libc and executable startup code

● Deleted ton of now useless wrappers

● Goal: build all of FreeBSD world with safe memory access

● Status: PoC works!

Page 35: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Demo Time!

● Everybody loves a good demo!

● Sufficiently advanced technology is indistinguishable from a properly rigged fake.

Page 36: CONFidence 2014: Andreas Bogk: Preventing violation of memory safety in C/C++ software

TOP SECRET//HCS/SI/TK//ORCON/NOFORN

Thanks and references

● SoftBoundCETS: http://www.cs.rutgers.edu/~santosh.nagarakatte/softbound/

● SoftBoundCETS on FreeBSD: https://github.com/andreas23/freebsd/tree/softbounds

● Many thanks to Hannes Mehnert for joint work on FreeBSD port

● Many thanks to Santosh Nagarakatte, Milo M. K. Martin, Steve Zdancewic for answering questions and providing access to beta versions of code