Bug class genocide Applying science to eliminate 100% of buffer - - PowerPoint PPT Presentation

bug class genocide
SMART_READER_LITE
LIVE PREVIEW

Bug class genocide Applying science to eliminate 100% of buffer - - PowerPoint PPT Presentation

Bug class genocide Applying science to eliminate 100% of buffer overflows Hackito Ergo Sum, 2014 Andreas Bogk, @andreasdotorg TOP SECRET//HCS/SI/TK//ORCON/NOFORN The problem void foo (char* arg) { char some[16]; char* p = some; while (*p++


slide-1
SLIDE 1

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

Bug class genocide

Applying science to eliminate 100% of buffer overflows

Hackito Ergo Sum, 2014 Andreas Bogk, @andreasdotorg

slide-2
SLIDE 2

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

The problem

void foo (char* arg) { char some[16]; char* p = some; while (*p++ = *arg++); }

slide-3
SLIDE 3

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++); }

slide-4
SLIDE 4

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); }

slide-5
SLIDE 5

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); }

slide-6
SLIDE 6

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... – –

slide-7
SLIDE 7

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

A word on notation

red.is->compiler_generated(code); black.is->user_written(code);

slide-8
SLIDE 8

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

Object-based approach

if (IsPoisoned(address)) { ReportError(address); } *address = ...; // or: ... = *address;

slide-9
SLIDE 9

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...");

slide-10
SLIDE 10

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“
slide-11
SLIDE 11

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
slide-12
SLIDE 12

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

Meet SoftBoundCETS

  • Source compatibility
  • Complete coverage
  • Separate compilation
  • Low overhead
slide-13
SLIDE 13

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

Spatial: instrumenting dereference

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

slide-14
SLIDE 14

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

Spatial: implementation of check

void check(ptr, base, bound, size) { if ((ptr < base) || (ptr + size > bound)) { abort(); } }

slide-15
SLIDE 15

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

slide-16
SLIDE 16

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(); } }

slide-17
SLIDE 17

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;

slide-18
SLIDE 18

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);

slide-19
SLIDE 19

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

Spatial: Pointer arithmetic

newptr = ptr + index; // or &ptr[index] newptr_base = ptr_base; newptr_bound = ptr_bound;

slide-20
SLIDE 20

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);

slide-21
SLIDE 21

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);

slide-22
SLIDE 22

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;

slide-23
SLIDE 23

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;

slide-24
SLIDE 24

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);

slide-25
SLIDE 25

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
slide-26
SLIDE 26

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);

slide-27
SLIDE 27

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

Temporal: dereference check

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

slide-28
SLIDE 28

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;

slide-29
SLIDE 29

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);

slide-30
SLIDE 30

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;

slide-31
SLIDE 31

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;

slide-32
SLIDE 32

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;

slide-33
SLIDE 33

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

Temporal: loose ends

  • Threads. Shared state is evil. Zalgo, etc.
  • Shared memory. Shared state... see above.
slide-34
SLIDE 34

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!
slide-35
SLIDE 35

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

Demo Time!

  • Everybody loves a good demo!
  • Sufficiently advanced technology is

indistinguishable from a propery rigged demo.

slide-36
SLIDE 36

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