6 minute read

UCL Course COMP0133: Distributed Systems and Security LEC-19


Motivation and Goal

Situation

  • Servers often hold sensitive data and Single server shared by different users

  • One user should not see data of other users

  • Subsystems on single server must cooperate to operate

Goal

Prevent users from obtaining or modifying data other than their own

to limit the harm that attackers can do when exploiting the server


Approach: Compartmentalization

Provide minimal access to system data and resources for its job for each subsystem

Define narrow interfaces that allow only exact operatons required for applications between subsystems

Define assuming exploit may occur, especially in subsystems closest to users


Idea

Principle of Least Privilege

  • Each subsystem should only have access to read or modify data needed for its job

  • The above requirement should be enforced externally (OS -> APP) not within subsystems

  • Must decompose system into subsystems
    必须将系统分解为子系统

    Must reason carefully about truly minimal set of privileges needed by each subsystem
    必须仔细推理每个子系统所需的真正最小权限集

  • Must be able to grant privileges in fine-grained (not generous) manner
    必须能够以细粒度的方式授予权限

Privilege Separation

  • Determine which subsystems most exposed to attack

  • Reduce privileges of most exposed subsystems


Implementations

Follow Least Privilege Principle and Privilege Separation

  • split a web server into multiple processes

  • each process has different minimal privileges and runs as different user IDs

  • use UNIX isolation mechanism to prevent processes from reading or writing data of others

UNIX Isolation Mechanism

Change Root Directory

The system call chroot() which changes the root directory of the calling process to that specified in path

which means it can set process’s notion of file system root such that directories above this point will not be changed

e.g.,

chdir("/usr/local/alone"); —– change the current working directory of the calling process to the given directory

chroot("/usr/local/alone"); —– change the root directory of the calling process to the given directory

setuid(61100); —– set the effective user ID (currently unprivileged user ID that not be used) of the calling process

such that process has no access to any other filesystem
except files in tree rooted at specific path /usr/local/alone
—– Pros

then it is impossible to access UNIX setuid-root programs (e.g., change password)
or other sensitive data elsewhere on disk

but it is needed to have a priori set up all system files needed by process in directory —– Cons

Pass File Descriptor

Since the parent server process is privileged (as root) initially,

the privileged parent process can open files that needed by unprivileged child

and can pass the child open file descriptors to these files when the parent fork() child

such that child process can read these files even if it cannot open them

and can pass the child open file descriptors to these files dynamically by sendmsg() after the parent fork() child

such that child process that connect to network can just accept connection (not read)

and then pass socket for that connection to another lower privileged process that can read

It is needed since the privileged parent server process
not have connection to network to get the potential malicious user inputs

Overview

  • okld (launcher daemon) process forks okd (dispatcher) process,
    oklogd (logger daemon) process, and a series of service processes

    where okld process is privileged (as root)

    services request to oklogd process by RPC to write log entries to disk (only oklogd process has the write privilege)

    and external network requests are received by okd process

  • okd process forks pubd (publish daemon) process

    where pubd process has limited read access to static data
    (e.g., configuration files and HTML template files) stored on the local disk

  • okd process parses user input without holding any sensitive data

    and send user input to corresponding service processess by RPC

  • each service process (i.e., \( svc_i \)) parses the received user input in a jail directory chroot()ed by okld process

    such that each of them cannot read or write data in other services

  • database proxy process (i.e., \( data_i \)) only accpets authenticated requests for subset of narrow RPC interface

    which can then read sensitive data from database


Effectiveness

Althrough okld process runs as root, there is no need to worry about exploit on it

since it has no potentially malicious user input, and okd child process with lower privilege will accept them


Trade-off between Isolation and Performance

where

  • \( s_i \) —– services

  • \( u_j \) —– users

  • \( t_{i,j} \) —– state for user \( u_j \) in service \( s_i \)

  • \( p_k \) —– processes

  • \( \rightarrow \) —– dependency (e.g., process \( p_1 \) depends on service \( s_1 \) in OKWS Model)

  • Grey Shading —– entities that will be influenced by attackers when process \( p_1 \) is exploited successfully

Strict Model

Strict Model uses one process per user which will give the strictest isolation

but it will require many processes which will lead to high cost and low performance

e.g.,

huge memory cost due to seperate virtual memory space & huge CPU cost

due to context switch (change one process to another)

OKWS Model

OKWS Model uses one process per service which will achieve lower cost and better performance

but the compromised service may reveal data of one user to another


Summary

  • Least Privilege Principle and Privilege Separation hold real promise for limiting harm exploits can do

  • Programming model for services requires new style of programming

    • must set up all system files needed by process in directory since chroot()ed services

    • must define narrow and per-service interfaces to database

    • must communicate explicitly using RPC between service and database