Most UNIX operating systems run a large number of their system processes
with root privileges, giving the program the capability to read and modify
other processes, memory, I/O devices, and so on. While this gives the
system processes the power needed to perform their tasks, it also provides
them with unnecessary access to other protected parts of the system. Many
software exploits count on this escalated privilege to gain superuser access
to a machine via bugs like buffer overflows and data corruption. To combat
this problem, the Solaris 10 Operating System includes a new least privilege model, which gives a specified process only a subset of the superuser powers and not full access to all privileges.
The least privilege model evolved from Sun's experiences with Trusted
Solaris and the tighter security model used there. The Solaris 10 OS least
privileged model conveniently enables normal users to do things like mount
file systems, start daemon processes that bind to lower numbered ports, and
change the ownership of files. On the other hand, it also protects the system
against programs that previously ran with full root privileges because they
needed limited access to things like binding to ports lower than 1024, reading
from and writing to user home directories, or accessing the Ethernet device.
Since setuid root binaries and daemons that run with full root privileges are
rarely necessary under the least privilege model, an exploit in a program no
longer means a full root compromise. Damage due to programming errors like
buffer overflows can be contained to a non-root user, which has no access to
critical abilities like reading or writing protected system files or halting the machine.
The Solaris 10 OS least privilege model includes nearly 50 fine-grained
privileges as well as the basic privilege set. The defined privileges are
broken into the groups contract, cpc,
dtrace, file, ipc, net,
proc, and sys. The basic privilege set includes all
privileges granted to unprivileged processes under the traditional security
model: proc_fork, proc_exec,
proc_session, proc_info, and
file_link_any.
Process Privilege Sets
Each process has four privilege sets in its kernel credentials:
The Inheritable set (I): The privileges inherited on
exec.
The Permitted set (P): The maximum set of privileges for the
process.
The Effective set (E): The privileges currently in effect, a
subset of P.
The Limit set (L): The upper bound of the privileges a
process and its children may obtain. Any changes to the set L
take effect on the next exec.
Each process also has a privilege awareness state (PAS) which
can be set to Privilege Aware (PA) or Not-Privilege Aware
(NPA). Privilege awareness is a mechanism which allows legacy
applications to retain full compatibility with the traditional full privilege
model. Legacy applications that are NPA will appear to be
granted all privileges in the set L if any of the EUID, RUID, or
SUID are 0 (root).
When a process calls exec(2), the kernel tries to relinquish
privilege awareness. For unprivileged processes, I,
P, and E are generally the same as the basic set of
privileges, and L is typically the full set of defined
privileges. For a more detailed explanation of the theory behind the
implementation, take a look at Casper
Dik's weblog on blogs.sun.com and the
Process Rights Management Tutorial.
Once launched, a process uses the privilege manipulation
functions to add or remove privileges from the privilege sets. Privileges
can always be removed, but only privileges found in the permitted set can be
added to the effective and inheritable set. As a result, the inheritable set
can be larger than the permitted set. The limit set can never grow.
The ppriv(1) Command
Process privilege sets and their attributes are viewed and modified by the
program ppriv(1). The ppriv(1) program arguments
follow the syntax:
-D: Turns on privilege debugging for the processes or command
supplied.
-e: Interprets the remainder of the arguments as a command
line and runs the command line with specified privilege attributes and
sets.
-l: Lists all currently defined privileges on stdout.
-N: Turns off privilege debugging for the processes or
command supplied.
-s spec: Modifies a process's privilege sets according to
spec. Modifying the same set with multiple -s
options is possible as long as you make either precisely one assignment to an
individual set or any number of additions and removals. That is, assignment
and addition or removal for one set are mutually exclusive. spec
is a specification with the format
[AEILP][+-=]privsetspec, containing no
spaces, where:
AEILP: Includes one or more letters indicating which
privilege sets to change. These are case insensitive, for example, either
a or A indicates all privilege sets.
+-=: Indicates a modifier to respectively add
(+), remove (-), or assign (=) the
listed privileges to the specified set(s) in privsetspec.
privsetspec: Indicates a comma-separated privilege set
specification (priv1, priv2, and so on), as described
in priv_str_to_set(3C).
-S: Short. Reports the shortest possible output strings for
sets. The default is portable output. See
priv_str_to_set(3C).
-v: Verbose. Reports privilege sets using privilege
names.
Viewing Process Privileges
Let's take a look at a few processes with the ppriv(1) command
to see how they differ, depending on whether or not they are PA and have had
their privileges modified. In this first example, we examine the third-party
user process screen which is not privilege-aware. The
flags are not set to PRIV_AWARE, and P,
I, and E are all identically defined as the basic
privilege set. The set L is the entire defined privilege
set:
In this second example we examine the inetd process. It is not privilege aware, but its P and E sets have been modified to match L because it's running with EUID/RUID/SUID
0:
Often system administrators wish to grant certain users select privileges
so that they may perform system tasks. If the user does not have the correct
privileges, then the system outputs an error and the task is not performed.
Say that the SUID bit has been removed from the file
/usr/sbin/traceroute so that normal users cannot use it. Any system administrator should be able to use traceroute from his or her personal
account without needing to be root, though. Without the correct privileges, a
user will see the following error when trying to traceroute to the host
www:
Now that it's clear that the person with the UID 1001 is missing the
PRIV_NET_ICMPACCESS privilege, it can be
granted so that UID 1001 may successfully run traceroute. Be sure to turn off
debugging in that shell after diagnosing the problem:
ppriv -N $$
Instead of debugging every command in the shell, the user can also debug
just one process at a time:
ppriv -D -e dtrace -D test.d
Privileges and Role Based Access Control (RBAC)
The RBAC facility, present in the Solaris OS since version 8, is used to
assign specific privileges to roles or users. Solaris RBAC configuration is
controlled through four main files, /etc/security/exec_attr,
/etc/security/prof_attr, /etc/security/auth_attr,
and /etc/user_attr. exec_attr(4) specifies the
execution attributes associated with profiles. This generally includes the
user and group IDs, commands, and default/limit privileges.
prof_attr(4) contains a collection of execution profile names,
descriptions, and other attributes. auth_attr(4) contains
authorization definitions and descriptions. user_attr(4)
contains user and role definitions along with their assigned authorizations,
profiles, and projects. For a better understanding of how RBAC operates, read
the above-mentioned man pages along with rbac(5),
policy.conf(4), chkauthattr(3SECDB) man pages, and
the Roles,
Rights Profiles, and Privileges section of the Solaris 10 System
Administrator Collection.
To allow a group of users to use DTrace, the system
administrator would either create a role that had access to the
DTrace privileges or assign the privilege directly to a user. The following would
create a "debug" role and grant it the appropriate
privileges:
Now add the necessary users to the debug role with
usermod:
usermod -R debug username
The users with the role debug
can now use su to access debug, providing the appropriate password, and run the necessary
DTrace commands.
Instead of adding roles and making the users access the role via su, the system administrator can also directly assign privileges to a user. The user must be
logged out in order for the following command to succeed:
If additional privileges are required, pinpoint them by running
dtrace command ppriv again.
RBAC can also be used in conjunction with the least privilege model to more
securely run daemons, like httpd, that need to bind to privileged ports. Many
such programs do not actually need root access for anything other than
listening on a port below 1024, so granting the role/user that runs the
process net_privaddr would remove the need for ever running the process with
EUID 0.
The Defined Privilege Set
The defined privileges under the new least privilege model are listed as in
the privileges(5) man page, but here are some that system administrators are more likely to use:
PRIV_CPC_CPU
Allow a process to access per-CPU hardware performance counters.
PRIV_DTRACE_PROC
Allow DTrace process-level tracing. Allow process-level
tracing probes to be placed and enabled in processes to which the user has
permissions.
PRIV_DTRACE_USER
Allow DTrace user-level tracing. Allow use of the syscall and
profile DTrace providers to examine processes to which the user
has permissions.
PRIV_DTRACE_KERNEL
Allow DTrace kernel-level tracing.
PRIV_FILE_CHOWN
Allow a process to change a file's owner user ID. Allow a process to
change a file's group ID to one other than the process's effective group ID or
one of the process's supplemental group IDs.
PRIV_FILE_CHOWN_SELF
Allow a process to give away its files. A process with this privilege will
run as if {_POSIX_CHOWN_RESTRICTED} is not in effect.
PRIV_FILE_DAC_READ
Allow a process to read a file or directory whose permission bits or ACL
would otherwise disallow the process read permission.
PRIV_FILE_DAC_SEARCH
Allow a process to search a directory whose permission bits or ACL would
not otherwise allow the process search permission.
PRIV_FILE_DAC_WRITE
Allow a process to write a file or directory whose permission bits or ACL
do not allow the process write permission. All privileges are required to
write files owned by UID 0 in the absence of an effective UID of 0.
PRIV_FILE_OWNER
Allow a process that is not the owner of a file to modify that file's
access and modification times. Allow a process that is not the owner of a
directory to modify that directory's access and modification times. Allow a
process that is not the owner of a file or directory to remove or rename a
file or directory whose parent directory has the "save text image after
execution" (sticky) bit set. Allow a process that is not the owner of a file
to mount a namefs upon that file. Allow a process that is not the owner of a
file or directory to modify that file's or directory's permission bits or
ACL.
Allow a process to bind to a privileged port number. The privilege port
numbers are 1-1023 (the traditional UNIX privileged ports) as well as those
ports marked as "udp/tcp_extra_priv_ports" with the exception of
the ports reserved for use by NFS.
PRIV_PROC_SETID
Allow a process to set its UIDs at will, assuming UID 0 requires all
privileges to be asserted.
PRIV_PROC_ZONE
Allow a process to trace or send signals to processes in other zones. See
zones(5).
PRIV_SYS_ADMIN
Allow a process to perform system administration tasks such as setting
node and domain name and specifying coreadm(1M) and
nscd(1M) settings.
PRIV_SYS_CONFIG
Allow a process to perform various system configuration tasks. Allow
file system-specific administrative procedures, such as file system
configuration ioctls, quota calls, creation and deletion of snapshots, and
manipulating the PCFS boot sector.
PRIV_SYS_DEVICES
Allow a process to create device special files. Allow a process to
successfully call a kernel module that calls the kernel
drv_priv(9F) function to check for allowed access. Allow a
process to open the real console device directly. Allow a process to open
devices that have been exclusively opened.
PRIV_SYS_MOUNT
Allow a process to mount and unmount file systems that would otherwise be
restricted (that is, most file systems except namefs). Allow a
process to add and remove swap devices.
Privilege Set C Functions
Various C function calls are used to view and modify privileges. See the
following man pages for more information about adding privilege awareness to
your own code:
getpflags(2), setpflags(2): get or set process
flags
getppriv(2), setppriv(2): get or set a privilege
set