class: center, middle ### COMP26020 Programming Languages and Paradigms Part 1: C Programming *** # Memory Safety --- background-image: url(include/segfault.jpg) --- # Memory Unsafety in C Programs - C, and other languages e.g. C++ **are inherently memory unsafe** - There is absolutely no check at runtime if memory accessed is initialised, allocated, or mapped - In most cases the compiler won't warn you either -- - **A few examples of memory errors:** - Out of bounds accesses on buffers (e.g. overflow) -- - Out of bounds arrays indexing -- - Dereferencing `NULL` or freed (*dangling*) pointers -- - Failure to initialise stack/heap-allocated variables before read access -- - Memory leaks -- - Double free -- - Use-after-free -- - etc. --- # Memory Unsafety in C Programs - Memory errors are **hard to detect, hard to debug** - No warning/error at compile-time - Undefined behaviour: at runtime sometimes it crashes, sometimes not... -- .large[.center[**⚠️ These bugs have huge security implications! ⚠️**]] Exploiting these bugs an attacker can: - Leak sensitive data (e.g. passwords, crypto keys) - Tamper with sensitive data - Escalate privileges - Take over the entire program ---
.small[Sources: https://zd.net/3q8axgo, https://zd.net/3wfFHU7] --- class: inverse, middle, center # Example 1: Infoleak --- # Example 1: Infoleak Assume the following scenario: - A security-sensitive program is distributed in binary-only form - It contains sensitive data: a password - An attacker has access to the binary only and aims to figure out the password --- name: infoleak # Example 1: Infoleak Original code: ```c char *welcome_message = "Hi there! How is it going?\n"; // 27 char char *password = "secret"; char entered_password[128]; int main(int argc, char **argv) { for(int i=0; i<27; i++) // Print welcome message character by character printf("%c", welcome_message[i]); printf("Please input the password:\n"); scanf("%s", entered_password); if(!strcmp(entered_password, password)) { printf("Passowrd ok!\n"); /* ... */ } else { printf("Wrong password! aborting\n"); } return 0; } ``` .codelink[
`23-memory-safety/infoleak-orig.c`
] --- # Example 1: Infoleak Updated code (`welcome_message` shortened): ```c *char *welcome_message = "Hi there!\n"; // shortened welcome message, only 11 chars now char *password = "secret"; char entered_password[128]; int main(int argc, char **argv) { for(int i=0; i<27; i++) printf("%c", welcome_message[i]); printf("Please input the password:\n"); scanf("%s", entered_password); if(!strcmp(entered_password, password)) { printf("Passowrd ok!\n"); /* ... */ } else { printf("Wrong password! aborting\n"); } return 0; } ``` .codelink[
`23-memory-safety/infoleak-updated.c`
] --- name: infoleak # Example 1: Infoleak Updated code (`welcome_message` shortened): ```c *char *welcome_message = "Hi there!\n"; // shortened welcome message, only 11 chars now char *password = "secret"; char entered_password[128]; int main(int argc, char **argv) { * for(int i=0; i<27; i++) // Oopsie! forgot to update that bit of the code printf("%c", welcome_message[i]); printf("Please input the password:\n"); scanf("%s", entered_password); if(!strcmp(entered_password, password)) { printf("Passowrd ok!\n"); /* ... */ } else { printf("Wrong password! aborting\n"); } return 0; } ``` .codelink[
`23-memory-safety/infoleak-updated.c`
] --- template: infoleak
--- template: infoleak
--- template: infoleak
--- class: inverse, middle, center # Example 2: Sensitive Data Tampering --- # Example 2: Sensitive Data Tampering Assume the following scenario: - Same type of program performing a password check - This time we assume that the attacker has access to the source code (e.g. open source program) - For that reason the password is stored encrypted - Attacker aims to bypass the password check --- name: tampering # Example 2: Sensitive Data Tampering ```c char user_input[32] = "0000000000"; char password_hash[32] = "tfdsfu"; // "secret" encrypted with caesar cypher with shift 1 int main(int argc, char **argv) { if(argc != 2) { printf("Usage: %s
\n", argv[0]); return 0; } strcpy(user_input, argv[1]); caesar_encrypt(user_input); if(!strncmp(password_hash, user_input, strlen(password_hash))) { printf("login success!\n"); /* do important stuff ... */ } else { printf("wrong password!\n"); } return 0; } ``` .codelink[
`23-memory-safety/tampering.c`
] --- template: tampering
--- template: tampering
--- template: tampering
--- template: tampering
--- class: inverse, center, middle # Example 3: Stack Smashing --- # Example 3: Stack Smashing - Classic control flow hijacking attack: - Attacker has external (e.g. command line) access to the program - Attacker exploits a bug to make the program execute code it's not supposed to - Originally proposed in 1996 here: http://www.phrack.org/archives/issues/49/14.txt - First let's see how the CPU manage function calls/returns --- # Example 3: Stack Smashing
--- # Example 3: Stack Smashing
--- # Example 3: Stack Smashing
--- # Example 3: Stack Smashing
--- # Example 3: Stack Smashing
--- # Example 3: Stack Smashing ```c char *password = "upqtfdsfu"; // properly encrypted password void security_critical_function() { printf("launching nukes!!\n"); } void preprocess_input(char *string) { char local_buffer[16]; strcpy(local_buffer, string); /* work on local buffer ... */ return; } int main(int argc, char **argv) { if (argc != 2) { printf("usage: %s
\n", argv[0]); return -1; } preprocess_input(argv[1]); caesar_encrypt(argv[1]); if(!strncmp(password, argv[1], strlen(password))) security_critical_function(); else printf("Unauthorised user!\n"); return 0; } ``` .codelink[
`23-memory-safety/stack-smashing.c`
] --- name: smashing # Example 3: Stack Smashing .leftcol[ ```c char *password = "upqtfdsfu"; void security_critical_function() { printf("launching nukes!!\n"); } void preprocess_input(char *string) { char local_buffer[16]; strcpy(local_buffer, string); /* work on local buffer ... */ } int main(int argc, char **argv) { if (argc != 2) { /* ... */ } * preprocess_input(argv[1]); caesar_encrypt(argv[1]); if(!strncmp(password, argv[1], strlen(password))) security_critical_function(); else printf("Unauthorised user!\n"); return 0; } ``` .codelink[
`23-memory-safety/stack-smashing.c`
] ] --- template: smashing .rightcol[
] --- template: smashing .rightcol[
] --- template: smashing .rightcol[
] --- template: smashing .rightcol[
] --- template: smashing .rightcol[
] --- class: inverse, center, middle # Example 4: Use-After-Free --- name: uaf # Example 4: Use-After-Free .leftcol[ ```c typedef struct { double member1; double member2; void (*member3)(int); } my_struct; void print_hello(int x) { printf("Hello, parameter: %d\n", x); } void security_critical_function() { printf("Launching nukes!\n"); /* ... */ } // ``` ] .rightcol[ ```c int main(int argc, char **argv) { /* allocate and init ms */ my_struct *ms = malloc(sizeof(my_struct)); ms->member1 = 42.0; ms->member2 = 42.0; ms->member3 = &print_hello; /* call the function pointer */ ms->member3(12); free(ms); char *buffer = malloc(12); strcpy(buffer, argv[1]); ms->member3(12); /* check a password, runs sec_crit_fn */ } ``` .codelink[
`23-memory-safety/stack-smashing.c`
] ] --- # Example 4: Use-After-Free .leftcol[ ```c typedef struct { double member1; double member2; * void (*member3)(int); } my_struct; void print_hello(int x) { printf("Hello, parameter: %d\n", x); } void security_critical_function() { printf("Launching nukes!\n"); /* ... */ } // ``` ] .rightcol[ ```c int main(int argc, char **argv) { /* allocate and init ms */ my_struct *ms = malloc(sizeof(my_struct)); ms->member1 = 42.0; ms->member2 = 42.0; * ms->member3 = &print_hello; /* call the function pointer */ * ms->member3(12); free(ms); char *buffer = malloc(12); strcpy(buffer, argv[1]); ms->member3(12); exit(0); } ``` .codelink[
`23-memory-safety/stack-smashing.c`
] ] - `member2` is a **function pointer** - Can be dynamically set and called at runtime --- template: uaf
--- template: uaf
--- template: uaf
--- template: uaf
--- # Summary - C is **not memory safe** - Memory issues benign at a first glance can have **huge security consequences** - How to avoid these? ---- .center[Feedback form: https://bit.ly/3iybv0Y]