Slide 1

Slide 1 text

Context-aware Failure-oblivious Computing as a Means of Preventing Buffer Overflows Manuel Rigger, Daniel Pekarek, Hanspeter Mössenböck Johannes Kepler University Linz, Austria Session 4A. Software Security. 29. August, NSS 2018, Hong Kong

Slide 2

Slide 2 text

Problem: Buffer Overflows in C • Buffer overflows have disastrous consequences • Arbitrary-code execution • Denial-of-service 2 2011 CWE/SANS Top 25 Most Dangerous Software Errors (http://cwe.mitre.org/top25/) Ranking Error #1 SQL Injection #2 OS Command Injection #3 Classic Buffer Overflow

Slide 3

Slide 3 text

Problem: Buffer Overflows in C 3 char buf[MAX]; ... strncpy(buf, src, MAX); int length = strlen(buf); ...

Slide 4

Slide 4 text

Problem: Buffer Overflows in C 3 char buf[MAX]; ... strncpy(buf, src, MAX); int length = strlen(buf); ... What could go wrong?

Slide 5

Slide 5 text

Background: Strings in C 4 A valid C string ends with a \0 character

Slide 6

Slide 6 text

Background: Strings in C 5 N S S _ 2 0 1 8 \0

Slide 7

Slide 7 text

Background: Strings in C 6 N S S _ 2 0 1 8

Slide 8

Slide 8 text

Problem: Buffer Overflows in C 7 N S S _ 2 0 1 8 \0 MAX > strlen(buf) char buf[MAX]; ... strncpy(buf, src, MAX); int length = strlen(buf); ...

Slide 9

Slide 9 text

Problem: Buffer Overflows in C 7 N S S _ 2 0 1 8 \0 MAX > strlen(buf) MAX = 3 N S S char buf[MAX]; ... strncpy(buf, src, MAX); int length = strlen(buf); ...

Slide 10

Slide 10 text

Problem: Buffer Overflows in C 7 N S S _ 2 0 1 8 \0 MAX > strlen(buf) MAX = 3 N S S char buf[MAX]; ... strncpy(buf, src, MAX); int length = strlen(buf); ... buf is no longer NULL-terminated!

Slide 11

Slide 11 text

N S S Example: strlen() 8 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; }

Slide 12

Slide 12 text

N S S Example: strlen() 8 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; }

Slide 13

Slide 13 text

N S S Example: strlen() 8 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; } 3252

Slide 14

Slide 14 text

Existing Work 9 Most existing approaches instrument the program to detect errors and terminate execution

Slide 15

Slide 15 text

Existing Work 10 LLVM’s AdddressSanitizer (Serebryany 2011) SoftBound (Nagarakatte 2009) Intel MPX’s based bounds instrumentation (Oleksenko 2018)

Slide 16

Slide 16 text

N S S Example: LLVM’s AddressSanitizer 11 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; }

Slide 17

Slide 17 text

N S S Example: LLVM’s AddressSanitizer 11 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; }

Slide 18

Slide 18 text

N S S Example: LLVM’s AddressSanitizer 11 size_t strlen(const char *str) { size_t len = 0; while (*str != '\0') { len++; str++; } return len; } ==16497==ERROR: AddressSanitizer: stack-buffer- overflow on address 0x7ffc59c0ef63 READ of size 1 at 0x7ffc59c0ef63 thread T0 #0 0x4e7442 in strlen /home/manuel/test.c:10:12 #1 0x4e7392 in main /home/manuel/test.c:5:5

Slide 19

Slide 19 text

Existing Work 12 What about systems with high-availability requirements?

Slide 20

Slide 20 text

Idea 13 Idea: Mitigate the error and continue execution while minimizing the chance of incorrect execution

Slide 21

Slide 21 text

Idea 13 Idea: Mitigate the error and continue execution while minimizing the chance of incorrect execution Useful in a production environment!

Slide 22

Slide 22 text

Contributions • Context-aware Failure-oblivious Computing • Implementation on top of three bug-finding tools • Evaluation • Effectiveness • Performance 14

Slide 23

Slide 23 text

Approach 15

Slide 24

Slide 24 text

Approach 16 Context-aware Failure-oblivious Computing

Slide 25

Slide 25 text

Approach 16 Context-aware Failure-oblivious Computing Failure-oblivious Computing (Rinard et al. 2004)

Slide 26

Slide 26 text

Failure-oblivious Computing 17 Idea: detect buffer overflows, but continue execution

Slide 27

Slide 27 text

Failure-oblivious Computing 18 try { // write access } catch (ArrayIndexOutOfBoundsException e) { }

Slide 28

Slide 28 text

Failure-oblivious Computing 18 try { // write access } catch (ArrayIndexOutOfBoundsException e) { } We execute C, not Java code

Slide 29

Slide 29 text

Failure-oblivious Computing 19 try { // read access } catch (ArrayIndexOutOfBoundsException e) { return getPredefinedValue(); }

Slide 30

Slide 30 text

Failure-oblivious Computing 19 try { // read access } catch (ArrayIndexOutOfBoundsException e) { return getPredefinedValue(); } What if the predefined value results in erroneous execution?

Slide 31

Slide 31 text

Approach 20 Context-aware Failure-oblivious Computing Introspection (Rigger et al. 2018)

Slide 32

Slide 32 text

Approach 20 Context-aware Failure-oblivious Computing Introspection (Rigger et al. 2018) Behavior depends on the semantics of the function in which the buffer overflow occurs

Slide 33

Slide 33 text

Introspection 21 Idea: provide object meta-data to the programmer, tracked by existing bug-finding tools

Slide 34

Slide 34 text

Introspection 22 Uses introspection function Instruments program

Slide 35

Slide 35 text

Introspection 23 long size_right(void *); long size_left(void *); enum Location location(void *); void* try_cast(void *, struct Type*); int count_varargs(); void* get_vararg(int i, struct Type* type);

Slide 36

Slide 36 text

Introspection 23 long size_right(void *); long size_left(void *); enum Location location(void *); void* try_cast(void *, struct Type*); int count_varargs(); void* get_vararg(int i, struct Type* type);

Slide 37

Slide 37 text

Introspection for Bounds 24 int *arr = malloc(sizeof (int) * 10) ; int *ptr = &(arr[4]); printf ("%ld\n", size_right(ptr)); // prints 24 _size_right() sizeof(int) * 10

Slide 38

Slide 38 text

Approach 25 Context-aware Failure-oblivious Computing Failure-oblivious Computing (Rinard et al. 2004) Introspection (Rigger et al. 2018)

Slide 39

Slide 39 text

Context-aware Failure-oblivious Computing 26 Idea: Implement a Failure-oblivious Computing logic for common library functions by using introspection

Slide 40

Slide 40 text

Context-aware Failure-oblivious Computing 27 strlen() strnlen() _size_right() instruments

Slide 41

Slide 41 text

Context-aware Failure-oblivious Computing 28 strlen() strnlen() _size_right() instruments

Slide 42

Slide 42 text

1. Interceptor for strlen() 29 size_t strlen(const char *str) { return strnlen(str, size_right(str)); }

Slide 43

Slide 43 text

1. Interceptor for strlen() 29 size_t strlen(const char *str) { return strnlen(str, size_right(str)); } N S S

Slide 44

Slide 44 text

1. Interceptor for strlen() 29 size_t strlen(const char *str) { } N S S return strnlen(str, 3);

Slide 45

Slide 45 text

1. Interceptor for strlen() 29 size_t strlen(const char *str) { } N S S return strnlen(str, 3); size_t strnlen(const char *str, size_t maxlen) { const char *p = str; while (maxlen-- > 0 && *p != '\0') p++; return p - str; }

Slide 46

Slide 46 text

1. Interceptor for strlen() 29 size_t strlen(const char *str) { } N S S return strnlen(str, 3); size_t strnlen(const char *str, size_t maxlen) { const char *p = str; while (maxlen-- > 0 && *p != '\0') p++; return p - str; }

Slide 47

Slide 47 text

1. Interceptor for strlen() 29 size_t strlen(const char *str) { } N S S return strnlen(str, 3); size_t strnlen(const char *str, size_t maxlen) { const char *p = str; while (maxlen-- > 0 && *p != '\0') p++; return p - str; } 3

Slide 48

Slide 48 text

2. Interceptor for gets() 30 char *gets(char *s) { return fgets(s, _size_right(s), stdin); }

Slide 49

Slide 49 text

3. Interceptor for memcpy() 31 void *memcpy(void *dest, const void *src, size_t n) { ssize_t dstsz = _size_right(dest); size_t len = n; if (dstsz < len) { len = dstsz; } return memcpy(dest, src, len); }

Slide 50

Slide 50 text

Implementation in Tools 32

Slide 51

Slide 51 text

Context-aware Failure-oblivious Computing 33 strlen() strnlen() _size_right() instruments

Slide 52

Slide 52 text

Implementation of size_right() 34 LLVM’s AdddressSanitizer (Serebryany 2011) SoftBound (Nagarakatte 2009) Intel MPX’s based bounds instrumentation (Oleksenko 2018)

Slide 53

Slide 53 text

GCC’s Intel MPX Bounds Checks Instrumentation 35 ssize_t size_right(void* p){ ssize_t upper_bounds = (ssize_t)__builtin___bnd_get_ptr_ubound(p); size_t size = (size_t) (upper_bounds + 1) - (size_t) p; return (ssize_t) size; }

Slide 54

Slide 54 text

SoftBound+CETS 36 ssize_t _size_right(const char* p) { const char* bound = __softboundcets_load_bound_shadow_stack(1); return bound - p; }

Slide 55

Slide 55 text

LLVM’s AddressSanitizer 37 N S S

Slide 56

Slide 56 text

LLVM’s AddressSanitizer 37 N S S

Slide 57

Slide 57 text

LLVM’s AddressSanitizer 37 N S S _size_right()

Slide 58

Slide 58 text

LLVM’s AddressSanitizer 37 ASan’s metadata is not optimal for the introspection implementation N S S _size_right()

Slide 59

Slide 59 text

Evaluation 38

Slide 60

Slide 60 text

39 Effectiveness Performance

Slide 61

Slide 61 text

40 Effectiveness

Slide 62

Slide 62 text

Effectiveness 41 Can the introspection interceptors be used to defend against buffer overflows in practice?

Slide 63

Slide 63 text

Effectiveness 42 Dnsmasq CVE-2017-14493 CVE-2017-14496 CVE-2017-9047 Libxml2 CVE-2017-16352 LightFTP CVE-2017-1000218

Slide 64

Slide 64 text

Effectiveness 43 Dnsmasq CVE-2017-14493 CVE-2017-14496 CVE-2017-9047 Libxml2 CVE-2017-16352 LightFTP CVE-2017-1000218

Slide 65

Slide 65 text

CVE-2017-14493 (Dnsmasq) 44 state->mac_len = opt6_len(opt) - 2; memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);

Slide 66

Slide 66 text

CVE-2017-14493 (Dnsmasq) 44 state->mac_len = opt6_len(opt) - 2; memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len); The server successfully handled subsequent requests after mitigation

Slide 67

Slide 67 text

CVE-2017-9047 (Libxml2) 45 if (content->name != NULL) strcat(buf, (char *) content->name);

Slide 68

Slide 68 text

CVE-2017-9047 (Libxml2) 45 The parser printed a truncated error message, similar to the fixed version if (content->name != NULL) strcat(buf, (char *) content->name);

Slide 69

Slide 69 text

CVE-2017-16352 (GraphicsMagick) 46 for (p=image->directory; *p != ’\0’; p++) { q=p; while ((*q != ’\n’) && (*q != ’\0’)) q++; (void) strncpy(image_info->filename,p,q-p); image_info->filename[q-p]=’\0’; }

Slide 70

Slide 70 text

CVE-2017-16352 (GraphicsMagick) 46 The error was mitigated… for (p=image->directory; *p != ’\0’; p++) { q=p; while ((*q != ’\n’) && (*q != ’\0’)) q++; (void) strncpy(image_info->filename,p,q-p); image_info->filename[q-p]=’\0’; }

Slide 71

Slide 71 text

CVE-2017-16352 (GraphicsMagick) 47 for (p=image->directory; *p != ’\0’; p++) { q=p; while ((*q != ’\n’) && (*q != ’\0’)) q++; (void) strncpy(image_info->filename,p,q-p); image_info->filename[q-p]=’\0’; }

Slide 72

Slide 72 text

CVE-2017-16352 (GraphicsMagick) 47 … but the application code had a subsequent out-of-bounds access for (p=image->directory; *p != ’\0’; p++) { q=p; while ((*q != ’\n’) && (*q != ’\0’)) q++; (void) strncpy(image_info->filename,p,q-p); image_info->filename[q-p]=’\0’; }

Slide 73

Slide 73 text

Effectiveness: Discussion • Prevents buffer overflows only in libc functions • Terminates execution if no interceptor mitigates the error • We do not want to risk incorrect execution! 48 Execution # CVEs Could continue 4 Terminated 1

Slide 74

Slide 74 text

49 Performance

Slide 75

Slide 75 text

Performance 50 What is the overhead of the introspection interceptors?

Slide 76

Slide 76 text

Performance • Benchmarks • Network-intensive (servers) • Computation-intensive (SPEC INT) 51

Slide 77

Slide 77 text

Performance 52 Approach Network-bound CPU-bound MPX ~1% Up to 13% ASan ~1% Up to 140% SoftBound+CETS ? 3%?

Slide 78

Slide 78 text

Performance: Discussion • Low overhead • Could be more efficient by directly implementing libc functions 53 size_t strlen(const char *str) { size_t len = 0; while ( size_right(str) > 0 && *str != '\0') { len++; str++; } return len; }

Slide 79

Slide 79 text

54 Context-aware Failure-oblivious Computing @RiggerManuel https://github.com/introspection-libc

Slide 80

Slide 80 text

54 Context-aware Failure-oblivious Computing @RiggerManuel https://github.com/introspection-libc

Slide 81

Slide 81 text

54 Context-aware Failure-oblivious Computing @RiggerManuel https://github.com/introspection-libc

Slide 82

Slide 82 text

54 Context-aware Failure-oblivious Computing @RiggerManuel https://github.com/introspection-libc

Slide 83

Slide 83 text

54 Context-aware Failure-oblivious Computing @RiggerManuel https://github.com/introspection-libc