Seyed Masoud Hosseini · Overview · Study log · Weekly summaries · Ideas · Search · Transcript · RSS feed
Computer Security · Lecture 4 of 22 · 1:23:29
Lecture 4: Privilege Separation
Study guide
What this lecture covers
Earlier lectures showed that C programs almost inevitably contain vulnerabilities such as buffer overflows. This lecture asks a different question: instead of trying to eliminate every bug, how do you design a system so that a single bug does not compromise everything? The answer is privilege separation, splitting an application into pieces that each hold only the privileges needed for their job, so a bug in one piece limits the damage an attacker can do.
To make this concrete, the lecture walks through Unix's protection mechanisms (users, groups, file permissions, file descriptors, chroot, setuid) in detail, then applies them to OKWS, a privilege-separated web server built for OkCupid. After watching, you should be able to explain how Unix decides whether a process can act on a file, process, or network resource, and how OKWS's architecture uses those primitives to limit what an attacker can reach after compromising any one component.
Key ideas
- Privilege separation: splitting an application into components that each get only the privileges necessary for their task, so a vulnerability in one component doesn't expose everything.
- Principal: in Unix, a process's privileges are represented by a userid (uid) plus a list of group IDs (gids).
- File permissions: each inode stores an owning uid and gid plus read/write/execute bits for owner, group, and other, often written as an octal number like
644. - File descriptors: security checks happen when a file is opened; anyone holding the resulting descriptor can use it freely, which lets a privileged helper open a file and hand the descriptor to a less-privileged process.
- setuid binaries: an executable that switches the running process's uid to the file's owner on execution, the classic (and tricky) way to gain elevated privileges in Unix.
- chroot: restricts a process's view of the filesystem to a subtree; only root can call it, and its exact semantics (rewriting how
/and/../resolve) matter for avoiding escapes. - OKWS architecture: separate processes (okd, pubd, oklogd, services, a database proxy, and the root-only okld launcher) each run under distinct uids and chroots so that compromising one limits an attacker's reach.
Walkthrough
Why privilege separation, and Unix as an isolation mechanism (0:00)
The lecture opens by motivating privilege separation as a general defense: rather than relying on an application having no bugs, split it into pieces so an attacker who exploits one piece only gets that piece's privileges. Real systems use this idea widely: SSH separates components to protect its keys, and Chrome sandboxes its renderer so a bug there doesn't give full control of the machine. Unix is introduced as one mechanism for enforcing this isolation, alongside virtual machines and containers, and the class discusses what needs protecting in an OS: files, directories, sockets, processes, memory, and file descriptors.
Unix principals and file permissions (6:06)
The lecture explains that Unix's security subject is the process, identified by a uid and a set of gids. For files and directories, permissions live in the inode as an owning uid/gid plus a 3x3 matrix of read/write/execute bits for owner, group, and other, commonly encoded as octal (for example 644). Only the file's owner can change its permissions. Directory operations like unlink, link, and rename depend on write permission on the directory rather than the file itself, and execute permission on a directory means the ability to look up names in it. A worked example traces the checks the kernel performs on open("/etc/passwd"), and a puzzle about combining two Unix groups to approximate an intersection shows both the flexibility and the limits of this permission model, including the fact that Unix does not enforce transitive restrictions once a process holds a privilege.
File descriptors, processes, and networking (23:34)
Because file access checks happen only at open time, a file descriptor itself becomes a bearer credential: anyone holding it can read or write freely, and descriptors can be inherited by children or passed over sockets. This lets a privileged process open a file and hand a narrowly scoped descriptor to a less-privileged one. For processes, a process can generally only create, kill, or ptrace another process with the same uid. Networking follows different rules: anyone can connect out, but binding to a port below 1024 requires uid 0 (root), a restriction meant to stop ordinary users from hijacking well-known services like port 80.
Bootstrapping privilege: setuid, login, and chroot (31:46)
The lecture covers how uid values are assigned in the first place: setuid() (callable only by root), the login process that checks credentials against /etc/passwd and /etc/shadow and then calls setuid to drop into the user's account, and setuid binaries such as su, which run with the privileges of the file's owner rather than the invoking user. This mechanism is powerful but historically fragile, for example old bugs let attackers use environment variables to hijack a setuid binary's shared libraries. The lecture then explains chroot, including the two-step mechanism the kernel actually uses (redefining what / means and rewriting /../ within that process), why only root can call it, and a demonstrated escape technique using an open file descriptor to a pre-chroot root directory combined with fchdir and repeated chroot calls.
OKWS: architecture and request flow (50:07)
Contrasted with a typical Apache-style server, where one process handles everything and a single database account has access to all data, OKWS splits a request's handling across several processes: okd (the dispatcher), oklogd (logging), pubd (template rendering), individual services (one per feature, such as newsletters or matching), and a database proxy that only accepts a fixed set of parameterized query templates guarded by a 20-byte token. okld, the launcher, runs as root and is responsible for the operations that require root, such as setting uids, chrooting processes, and binding port 80. The lecture traces how a request flows from the browser through okd to a service and finally to the database proxy.
Evaluating OKWS's security (1:07:40)
The lecture closes by assessing each component's attack surface and blast radius. okd turns out to be the most dangerous component to compromise, since it can rewrite responses and steal other users' passwords and data as they pass through. oklogd mainly risks garbling the log rather than leaking the database. Services are considered the most likely place for bugs, since they're written quickly by individual developers, but their damage is limited to whatever queries the database proxy permits. okld runs as root but accepts very little external input, so its actual attack surface is small. The class also discusses why OKWS separates by service rather than by end user (mainly performance and the fact that services like matching need to read many users' data at once), and confirms that this architecture, while imperfect, is a substantial improvement over an unseparated design.
Before you watch
- Review buffer overflows and C memory-safety vulnerabilities from the prior lecture, since this lecture treats them as the kind of bug privilege separation is meant to contain.
- Be comfortable with basic Unix concepts: users, processes, and the file system.
- If your course lab is modeled on a privilege-separated web server, having read that assignment's description will make the OKWS comparison more concrete.
Check your understanding
- Why does giving an application fewer privileges per component limit the damage of a single vulnerability, even if that vulnerability is never fixed?
- Walk through the checks the Unix kernel performs when a process calls
open("/etc/passwd"). - Why can a process holding an open file descriptor read or write it freely, even if it could not have opened that file itself?
- Explain the trick used to escape a
chrootjail using an open file descriptor andfchdir, and why only root is allowed to callchroot. - Of okd, oklogd, a service, and okld, which component's compromise is most damaging in OKWS, and why?
Vocabulary
- privilege separation (noun)
- Splitting a system into parts that each hold only the access they need.
Privilege separation limits damage from a single bug. - principal (noun)
- The identity a system uses to decide what actions are allowed.
A Unix process's principal is its user ID and groups. - inode (noun)
- A data structure storing information about a file, such as its owner and permissions.
Each file's permissions live in its inode. - file descriptor (noun)
- A number a process uses to refer to an open file or resource.
Holding a file descriptor lets a process use it freely. - setuid (adjective)
- Describing a program that runs with the privileges of its file owner rather than the user who launched it.
A setuid binary can gain elevated privileges when run. - chroot (noun)
- A mechanism restricting a process's view of the filesystem to one subtree.
Chroot limits which files a process can even see. - bearer credential (noun)
- A credential that grants access to anyone who simply holds it.
A file descriptor acts like a bearer credential. - attack surface (noun)
- The parts of a system exposed to potential attackers.
A component's attack surface shows how it might be exploited. - blast radius (noun)
- The extent of damage possible if a component is compromised.
Splitting services limits the blast radius of any single bug. - dispatcher (noun)
- A component that routes incoming requests to the right handler.
The dispatcher sends each request to the correct service. - parameterized query (noun)
- A database query template that safely inserts values instead of raw text.
The database proxy only accepts parameterized queries. - isolation (noun)
- Keeping components separated so problems in one don't spread to others.
Unix provides isolation between different users' processes. - escape (verb)
- To break out of an intended restriction or boundary.
A clever trick can escape a chroot jail. - credential (noun)
- Information used to prove identity or gain access.
Login checks credentials against the password file. - template rendering (noun)
- The process of filling a page layout with real content before showing it.
A separate process handles template rendering. - launcher (noun)
- A program responsible for starting other processes.
The root-only launcher sets up privileges for each service. - assess (verb)
- To carefully judge how good, safe, or effective something is.
The lecture assesses each component's attack surface. - damage (noun)
- Harm caused by a successful attack.
A compromised service limits the damage an attacker can do. - flow (noun)
- The path data or control takes through a system.
The lecture traces the request flow through each process. - elevate (verb)
- To increase the level of access or privilege something has.
A setuid binary can elevate a process's privileges.
From the YouTube description
MIT 6.858 Computer Systems Security, Fall 2014
View the complete course: http://ocw.mit.edu/6-858F14
Instructor: Nickolai Zeldovich
In this lecture, Professor Zeldovich introduces the concept of privilege separation in the context of system security.
License: Creative Commons BY-NC-SA
More information at http://ocw.mit.edu/terms
More courses at http://ocw.mit.edu
← Lecture 3: Buffer Overflow Exploits and Defenses · Lecture 6: Capabilities →
