class: center, middle ### Secure Computer Architecture and Systems *** # Software Compartmentalisation: Introduction --- # Systems Software Security Landscape .leftcol[ - Most systems software are seen as a **single monolithic unit of trust** - One vulnerability may allow an attacker to take over an entire application/system - Not a good fit to modern apps integrate **components from various sources with different degrees of trust** - Increased risk of supply chain attacks ] .rightcol[
] --- # Systems Software Security Landscape .leftcol[ - Systems software also integrate components that are **security-critical** - Cannot continue to see modern systems software as monolithic pieces of trust - Need to bring isolation and privilege reduction **within applications** - Achieved with **software compartmentalisation** ] .rightcol[
] --- # Software Compartmentalisation - Software compartmentalisation **decompose software into lesser-privileged components that only have access to what they need to do their job** - Different from other approaches: acknowledge there will be bugs and exploits, try to limit their impact
--- # Software Compartmentalisation - Software compartmentalisation **decompose software into lesser-privileged components that only have access to what they need to do their job** - Different from other approaches: acknowledge there will be bugs and exploits, try to limit their impact
--- ## (Re)designing for Compartmentalisation - Compartmentalisation is not complete isolation: components are still part of a single application/system and **communicate** - Traditional examples: OS kernels, web browser, web servers, SSH software - Niche/specific examples, approach not widespread - Software can be **designed from scratch** with compartmentalisation in mind - That's the case for most production-ready examples - Compartmentalisation can also be **retrofitted into monolithic software** - Desirable objective given the large amount of legacy monolithic system software - Hard to achieve in practice --- # Compartmentalisation: Key Idea - **Restrict control and data flow in the application so that each compartment has the permissions it requires to do its job** - Application of the principle of least privilege to software | | Crypto library (comp. 1) | HTTP parser (comp. 2) | |--------------------|-------------------------|-------------------------| | Crypto keys | read access | no access | | HTTP request data | no access | read access | Lampson's **access control matrix** --- # Compartmentalisation: Trust Models - 3 trust models: - **Sandbox**: part of the program is untrusted, isolated the (trusted) rest of the program from it - **Safebox**: part of the program is security critical, isolated it from the (untrusted) rest of the program - **Mutual distrust**: compartments distrust each others - Stronger generalisation of the other 2 models - All generalise to more than 2 compartments
--- ## Compartmentalisation: Security Properties - **3 security properties considered**: - **Confidentiality**: an attacker cannot read/leak information from outside of a subverted compartment - **Integrity**: an attacker cannot write/tamper with data outside of a subverted compartment - **Availability**: an attacker cannot disrupt (e.g. crash) code running outside of a subverted compartment - Very hard to achieve when retrofitting without complete redesign of monolithic applications, out of scope for most existing efforts --- # Compartmentalisation in a Nutshell Basic steps for compartmentalisation: .rightsmallcol[
] --- # Compartmentalisation in a Nutshell Basic steps for compartmentalisation: .leftlargecol[ 1. Establish a **compartmentalisation policy**: decide what part of the target software goes into what compartment ] .rightsmallcol[
] --- # Compartmentalisation in a Nutshell Basic steps for compartmentalisation: .leftlargecol[ 1. Establish a **compartmentalisation policy**: decide what part of the target software goes into what compartment 2. Use **compartmentalisation abstractions** to indicate in the code compartments boundaries, private/shared data, establish communication between compartments, and secure interfaces ] .rightsmallcol[
] --- # Compartmentalisation in a Nutshell Basic steps for compartmentalisation: .leftlargecol[ 1. Establish a **compartmentalisation policy**: decide what part of the target software goes into what compartment 2. Use **compartmentalisation abstractions** to indicate in the code compartments boundaries, private/shared data, establish communication between compartments, and secure interfaces 3. At runtime have an **isolation mechanism** enforce the partitioning between compartments ] .rightsmallcol[
] --- # Enforcing Isolation
--- # Enforcing Isolation
-- - Also need a **privileged monitor** to perform security domain transitions - The OS kernel can play that role --- # Compartmentalisation: It's in the Air .leftcol[
] .rightcol[
] --- # Example .leftcol[ ```c int global; int library_function(int *parameter) { char *cryptokey = “private“; int ret = *parameter + global + 42; return ret; } int main() { int arg = 100; global = 50; char *password = “secret“; /* ... */ int res = library_function(&arg); /* ... */ return 0; } ``` ] -- .rightcol[ - Policy: `library_function` in one compartment, `main` in the other. ] --- # Manual Compartmentalisation .leftcol[ ```c int global; int library_function(int *parameter, int *result_fd, int global_copy) { char *cryptokey = "private"; int ret = *parameter + global_copy + 42; write(*result_fd, &ret, sizeof(ret)); return 0; } int main() { int arg = 100; global = 50; char *password = "secret"; int pipefd[2]; pipe(pipefd); pid_t pid = fork(); ``` ] .rightcol[ ```c if (pid == 0) { close(pipefd[0]); library_function(&arg, &pipefd[1], global); close(pipefd[1]); exit(0); } else { close(pipefd[1]); int res; read(pipefd[0], &res, sizeof(res)); wait(NULL); printf("res: %d\n", res); close(pipefd[0]); } return 0; } ``` ] --- # Manual Compartmentalisation (2) .leftcol[ ```c int global; int library_function(int *parameter, int *shared_result, int global_copy) { char *cryptokey = "private"; int ret = *parameter + global_copy + 42; *shared_result = ret; return 0; } int main() { int arg = 100; global = 50; char *password = "secret"; int shmid; int *shared_mem; shmid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0666); shared_mem = shmat(shmid, NULL, 0); ``` ] .rightcol[ ```c pid_t pid = fork(); if (pid == 0) { library_function(&arg, shared_mem, global); shmdt(shared_mem); exit(0); } else { wait(NULL); int res = *shared_mem; printf("res: %d\n", res); shmdt(shared_mem); shmctl(shmid, IPC_RMID, NULL); } return 0; } ``` ] --- ## Framework-Assisted Compartmentalisation .leftcol[ ```c *int shared global; int library_function(int *parameter) { char *cryptokey = “private“; int ret = *parameter + global + 42; return ret; } int main() { * int shared arg = 100; global = 50; char *password = “secret“; /* ... */ * int res = GATE(library_function, &arg); /* ... */ return 0; } ``` ] .rightcol[ - Policy: `library_function` in one compartment, `main` in the other. - Compartmentalisation: - Add a gate performing security domain switch (mechanism) - Identify shared data and allocate it somewhere accessible from both compartments - Can be achieved with several (mostly research) frameworks ] --- # Summary - Can't continue seeing systems software applications as single unit of trust - Need privilege-reduction efforts within applications - Software compartmentalisation decomposes programs into less-privileged compartments - Can be designed for, or retrofitted - Frameworks can help but it is generally a lot of work