kernelthread.com

A Taste of Computer Security

© Amit Singh. All Rights Reserved. Written in June 2004


Access Control

Access Control is an internal (to an operating system) protection mechanism. One form of access control is seen in CPU instructions that may only be executed in supervisor mode, which usually amounts to within the kernel. The division of virtual memory into kernel and user parts is also a form of access control.

The Matrix

Access control plays an important role at the administrative level too. The well-aged Access Matrix model is basis for several access control mechanisms. In this model, you have:

It is useful to point out the concept of a protection domain, which may be thought of as a collection of access rights that subjects inside the domain enjoy. In a typical operating system, the kernel is in its own protection domain. Each user (each user's processes, to be precise) is in a separate domain. For a given user, each of his processes are in separate domains too. Carrying this further, you will realize that within a program, different subroutines may be in different domains. An important thing to note is that domains may overlap with, or even entirely contain, other domains.

The model could be visualized as a matrix M where each row i represents an object i, each column j represents a subject j, and matrix element M[i, j] contains a set of rights. Note that M[i, j] could be empty. In a real-life operating system, such a matrix would have a large number of rows and columns, but would be sparse, thereby rendering a global table (explicitly as a two-dimensional data structure) would be inefficient.

Implementation Approaches

Two popular implementation approaches are Access Lists and Capability Lists.

An access list enumerates who all may access a particular object. Thus, you need to know the identities of all subjects. The Unix file permission scheme is an example. Note that in the context of Unix file permissions, "others" is a wildcard (catch-all) for subjects whose identity is not known (they may not even exist yet). Access lists are more effective when it's easy to put subjects in groups.

A capability list enumerates each object along with the operations allowed on it. This is a ticket-based scheme, where the possession of a capability (an unforgeable ticket) by a subject allows access to the object. In this scheme, it is extremely critical to protect the capability list, as capabilities must not propagate without proper authentication. Note that capabilities are finer grained than access list entries, and often can replace the Unix all-or-nothing super-user model. For example, rather than making the ping command setuid root, it is more secure to have a capability representing raw access to the network, and providing only that to ping.

DAC and MAC

The terms Discretionary and Mandatory are frequently used in the context of access control.

A discretionary access control (DAC) scheme is, well, at the discretion of the user. An object's owner (who is usually also the object's creator) has discretionary authority over who else may access that object. In other words, access rights are administered by the owner. Examples include Unix file permissions and a username/password system. Note that with DAC, the system cannot tell the real owner apart from anybody else. Moreover, if an access attempt fails, you may get any number of chances to retry.

Thus, access decisions in DAC are only based on apparent ownership, without taking into account the user's role or the program's functionality. Every program a user executes inherits the user's privileges. Moreover, these privileges are coarse-grained. Consequently, every setuid root application gets all possible privileges, which is usually an overkill.

Note that there are usually only two types of users: the super-user (administrators) and "normal" users.

Mandatory access control (MAC) involves aspects that the user cannot control (or is not usually allowed to control). A Utopian (or Draconian, if you so wish) MAC system would be one that uses your DNA. Another example is that of a hardware address that cannot be changed by a user. Under MAC, objects are tagged with labels representing the sensitivity of the information contained within. MAC restricts access to objects based on their sensitivity. Subjects needs formal clearance (authorization) to access objects.

As an example, on Trusted Solaris, MAC relies on sensitivity labels attached to objects. The MAC policy compares a user's current sensitivity label to that of the object being accessed. The user is denied access unless certain MAC checks are passed. It's mandatory as the labeling of information happens automatically, and ordinary users cannot change labels. In contrast, DAC uses file permissions and optional access control lists (ACLs) to restrict information based on the user's ID (uid) or his group ID (gid). It's discretionary as a file's owner can change its permissions at his discretion.

Authentication is the process of validating that a subject's credentials are correct (for example, verifying a particular user's identity). Authentication may be implemented taking into account one or more mechanisms: something the user knows (for example, a password), something the user possesses (for example, an RSA SecureID token), and something that is universally unique to the user (for example, Biometrics).

Authorization is the process of checking if a validated subject is permitted to access a particular object, and either granting or rejecting the attempted access. Authorization follows authentication.

Auditing is the recording of key (or designated) events in the authentication and authorization processes, say, in a log.

DTE

Domain and Type Enforcement (DTE) [Badger et al, 1995] is an access control mechanism based on the principle of least privilege. Thus, only those access rights that are absolutely necessary are granted to a program. DTE is enforced in the kernel, but is configurable, and is meant to be used as a tool for implementing MACs.

In DTE, subjects are grouped into domains, while objects are grouped into types. Access rules specify which domains have access to which types. Execution of certain programs may cause transitions between domains. An important feature of DTE is a high-level language, DTEL, that allows specification of security policies. A sample policy is shown below:

/* Sample DTE Policy */ type unix_t /* normal UNIX files, programs, etc. */ type movie_t /* movie footage */ #define DEFAULT (/bin/zsh), (/bin/sh), (/bin/csh), (rxd->unix_t) domain editor_d = DEFAULT, (rwd->movie_t); domain system_d = (/etc/init), (rwxd->unix_t), (auto->login_d); domain login_d = (/bin/login), (rwxd->unix_t), (exec->movie_d); initial_domain system_d; /* system starts in this domain */ assign -r unix_t /; assign -r movie_t /projects/movies;

The above specification means that the first process (/etc/init) starts in the system_d domain. All processes inherit this domain, except /bin/login, which runs in its own domain, which has the authority to create the user domain movie_d.

Flask and SELinux

The National Security Agency (NSA) and Secure Computing Corporation (SSC) collaborated to design a generalization of type enforcement as a flexible access control mechanism. Originally implemented for microkernel-based systems (such as Mach), the architecture was enhanced as the University of Utah joined in to to integrate it into the Fluke research operating system. Later ported (in part) to Utah's OSKit, Flask was most recently implemented for Linux, resulting in Security-Enhanced Linux (SELinux).

Flexibility in such an architecture was important for it to be acceptable for mainstream operating systems. SELinux includes mandatory access controls on a variety of objects: processes (operations such as execute, fork, ptrace, change scheduling policy, send certain signals, ...), files (create, get/set attributes, inherit across execve, receive via IPC), filesystems (mount, remount, unmount, associate), TCP and Unix domain sockets, network interfaces, IPC objects, procfs, devpts, and so on.

Similar to DTE, the security policy configuration in SELinux uses a high-level language for specification. Type enforcement can be combined with Role-Based Access Control (RBAC), wherein each process has an associated role. System processes run in the system_r role, while user may have roles such as sysadm_r and user_r. A role is only allowed to enter a specified set of domains. Domain transitions may occur, for example, to a more restricted domain when the user runs an application that should be run with a subset of the user's privileges.

Linux Security Modules

Linux Security Modules (LSM) [Cowan et al, 2002] is a general purpose access control framework for the Linux kernel that allows various access control modules to be implemented as loadable kernel modules. Some existing access control implementations have been ported to this framework, such as:

The LSM interface mediates access to internal kernel objects by using hooks in the kernel code just before the access. Most LSM hooks are restrictive, but permissive hooks are supported. Examples of kernel objects include process structures, superblocks, inodes, open files, network devices, network buffers, sockets, skbuffs, ipc message queues, semaphores, and shared memory, and so on. Opaque security fields are used to associate security information with these objects.

CQUAL is a type based static analysis tool. Zhang, Edwards, and Jaeger [Using CQUAL for Static Analysis of Authorization Hook Placement, 2002] used a CQUAL lattice, along with GCC changes, to verify complete mediation of operations on key kernel data structures. The goal is to ensure that each controlled operation is completely mediated by hooks that enforce its required authorization.

CQUAL also supports user defined type qualifiers.

LIDS

Linux Intrusion Detection System (LIDS) is an enhancement for the Linux kernel that implements, among other things, mandatory access control.

Some other interesting features of LIDS include a built-in portscan detector, the ability to "seal" the kernel so that no more kernel modules may be loaded or unloaded, filesystem access control lists, capability lists to control super-user privileges, etc. Note that LIDS allows you to disable a capability so that even the super-user may not use it (for example, the ability to install a packet sniffer, or configure the firewall), and also re-enable it.

<<< Securing Memory main Detecting Intrusion >>>