class: center, middle ### Secure Computer Architecture and Systems *** # Software Compartmentalisation and Interfaces --- # Retrofitting Compartmentalisation - Compartmentalisation present in production only in a **handful of specific use cases** - Micro-kernels, web browsers/servers, etc. - Software **designed from scratch with compartmentalisation in mind** - Huge amount of legacy code that would benefit from compartmentalisation - Manual approaches requires expert knowledge, an ideal goal would be able to compartmentalise monolithic software **automatically**
--- # Automated Compartmentalisation - **Automation**: let the user compartmentalise *seamlessly* (e.g. in 1 click) and *without expert knowledge* - Can we automate all the steps of compartmentalisation? - **Policy definition**: *some* approaches relying on standard programming language/runtime constructs can be automated - E.g. every library/object file/function within its own compartment - **Cross-compartment shared data/communication management**: need to identify all shared data and allocate it in shared memory/exchange it through message passing - Identification is the hardest bit, has been shown to be automatable in recent research efforts --- # Automated Compartmentalisation - Can we automate all the steps of compartmentalisation? (continued) - **Applying an isolation mechanism**: good primitives (e.g. `fork()` for processes) to automate isolation, similar support for other mechanisms in several frameworks .center[That's it?] --- # Interface Safety .leftcol[ Monolithic app to compartmentalise: ```c double data[DATA_SIZE]; /* ... */ int lib_function(int index, double object) { data[index] = object; /* ... */ } int main() { int index = get_index(); double object = get_index(); if (index < DATA_SIZE) lib_function(index, object); /* ... */ } ``` ] .rightcol[ - **Policy**: `lib_function` in a compartment, `main` in another - Safebox `lib_function` which does not trust `main` - **Compartmentalisation**: put a gate at the level of the call to `lib_function`. No shared data. - Several frameworks provide a good level of automation for all that ] --- # Interface Safety .leftcol[ Monolithic app to compartmentalise: ```c double data[DATA_SIZE]; /* ... */ int lib_function(int index, double object) { * data[index] = object; /* ... */ } int main() { int index = get_index(); double object = get_index(); if (index < DATA_SIZE) * lib_function(index, object); /* ... */ } ``` ] .rightcol[ - Compartmentalisation creates a **new internal trust boundary**: the interface between the two compartments - The call to `lib_function` - Assume `main` is malicious and send corrupted values through this interface - Lack of check in `lib_function` gives an attacker taking over `main` an **arbitrary memory write primitive** ] --- # Interface Safety .leftcol[ Monolithic app to compartmentalise: ```c double data[DATA_SIZE]; /* ... */ int lib_function(int index, double object) { * if (index >= DATA_SIZE || index < 0) * return -1; data[index] = object; /* ... */ } int main() { int index = get_index(); double object = get_index(); if (index < DATA_SIZE) lib_function(index, object); } ``` ] .rightcol[ - Fix: have a check within the trusted compartment ] --- # Interface Safety .leftlargecol[ - Retrofitting compartmentalisation in existing software creates **internal trust boundaries** - Such **monolithic software was never designed with these internal trust assumptions** - The majority of existing approaches at compartmentalisation (including automated ones) do not provide any help for securing interfaces .center[How bad is the problem, do we still get safety benefits from compartmentalisation without securing interfaces?] ] .righsmalltcol[
] --- ## Compartment Interface Vulnerabilities (CIVs) - **CIVs**: vulnerabilities arising due to lack of or improper Control and Data flow validation at compartment boundaries. Classes of CIV include: - **Data leakage**: - Exposure of addresses - Exposure of confidential data - **Data corruption**: - Dereference of corrupted pointer - Usage of corrupted indexing information - Usage of corrupted object - **Temporal violations**: - Breaking API usage ordering - Usage of corrupted synchronisation primitives - Shared memory TOCTTOU --- # How Bad is the Issue of CIVs? .leftcol[ - Recent research study proposes a fuzzer injecting malformed data in monolithic software at potential compartment boundaries - To emulate the result of compartmentalising without securing interfaces ] .rigthcol[
] --- # How Bad is the Issue of CIVs? .leftcol[ - Recent research study proposes a fuzzer injecting malformed data in monolithic software at potential compartment boundaries - To emulate the result of compartmentalising without securing interfaces - Goal is to study the bugs found ] .rightcol[
] --- # How Bad is the Issue of CIVs? - Fuzz 36 APIs total divided into 2 trust models - **Sandbox**: - Apache + libmarkdown - cURL + libnghttp2 - git + libcurl - etc. - **Safebox**: - Curl + libssl - GPG + libgcrypt - sudo + libapparmor - Look at libraries but also module and internal APIs - Many of these have been compartmentalised in past research studies --- # Unprotected APIs Fuzzing Results - Found 629 unique bugs - Read / Write / Exec, both limited and arbitrary - Alloc / `NULL` bugs Example in safeboxing sudo's authentication API: ```c int sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *cb) { /* ... abbreviated ... */ sav = pass[8]; // read CIV pass[8] = '\0'; // write CIV } /* ... abbreviated ... */ ``` --- # Unprotected APIs Fuzzing Results Examples in safeboxing libssl: ```c // CIV 1: option setting API leads to arbitrary R/W ulong SSL_CTX_set_options(SSL_CTX *ctx, ulong op) { return ctx->options |= op; } ``` ```c // CIV 2: cross-API object SSL_CTX with function // pointers leads to arbitrary execution SSL *SSL_new(SSL_CTX *ctx) { /* ... */ s->method = ctx->method; /* ... */ if (!s->method->ssl_new(s)) // arbitrary execution goto err; } /* ... */ ``` --- # Takeaways from the Study - **CIVs are widespread and compartmentalisation without securing interfaces is mostly meaningless** - **Clear disparities among APIs** - There are large and almost totally CIV-free APIs, and small but fully vulnerable APIs - No correlation between API size and CIV count - Some API design patterns (e.g. modules) are highly vulnerable because of a large amount of state exposure - **CIVs are high-impact** - 75% of scenarios have at least 1 write vulnerability - 70% of R/W and 50% of execute vulnerabilities are arbitrary - **Fixing CIVs goes beyond writing simple checks** - Requires API redesign in many cases, hard to automate --- # Summary - **Automated compartmentalisation** is a desirable objective - Several steps of the process have been shown to be automatable in research efforts - But production-ready tools are not there yet - A step that is unlikely to be automatable is **securing cross-compartment interface** - Unfortunate because without it compartmentalising is mostly meaningless