Softpanorama

May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix

Solaris Privilege Sets

News

See also

Recommended Links

Process Privilege Sets

Reference

Man pages
Privileges and RBAC Solaris RBAC implementation Solaris Zones History Humor Etc

Quotes for  The Least Privilege Model in the Solaris ...

... 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.

Each process has four privilege sets in its kernel credentials:

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.

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:

traceroute www
traceroute: icmp socket: Permission denied

To determine which privilege is missing from various commands, use the debugging functionality of ppriv(1) in the shell:

ppriv -D $$
traceroute www
traceroute[2885]: missing privilege "net_icmpaccess" (euid = 1001,
syscall = 230) for "devpolicy" needed at so_socket+0xa4
traceroute: icmp socket: Permission denied

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
 

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:

roleadd -u 201 -d /export/home/debug -P "Process Management" debug
rolemod -K defaultpriv=basic,dtrace_kernel,dtrace_proc,dtrace_user debug

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:

usermod -K defaultpriv=basic,dtrace_kernel,dtrace_proc,dtrace_user username

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.
PRIV_NET_ICMPACCESS
Allow a process to send and receive ICMP packets.
PRIV_NET_PRIVADDR
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.
Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

[Oct 30, 2006] Try it for yourself Solaris 10 Privilege Debugging by Glenn Brunette

Feb 12, 2006 (Glenn Brunette's Security Weblog) Just this month, Darren Moffat and I have published a Sun BluePrint article and opened a OpenSolaris Security Project on privilege debugging which includes a cool, new tool, called privdebug.

Together these resources can help you quickly and easily determine which privileges are used by any process, service or application. With this information, you can configure SMF to limit the privileges granted to it using the approach described here.

Everything is freely available. So why not give it a try! We would love to hear what you think!

Take care,

Glenn

[Oct 30, 2006] BigAdmin - Submitted Tech Tip Using Process Rights Management in the Solaris 10 OS to Run setuid Binaries

Introduction

This Tech Tip explores using Process Rights Management (PRM) in the Solaris 10 OS, and how PRM enables us to execute setuid and setgid commands without the setuid or setgid flags.

Objective

PRM in the Solaris 10 OS allows us to remove setuid/setgid flags from executables that would normally have them set, while also allowing a selected set of non-privileged users to execute them.

In the Solaris 10 OS, although most of the "normal" setuid/setgid executables have been re-written to be privilege aware (PA), they still have their setuid/setgid flags set. This is necessary for the program to first gain the appropriate root privilege and then drop the unnecessary ones. However, this would require the program to be fully privilege aware and some setuid/setgid programs out there might not have been ported as yet.

This Tech Tip suggests a method to remove the setuid/setgid flag, while allowing a selected non-root user to execute the program appropriately.

Example Using ping

A good example of a setuid binary would be the ping program.

$ ls -al /usr/sbin/ping
-r-sr-xr-x   1 root     bin        45016 Apr 26  2005 /usr/sbin/ping

Now rewritten to be PA, the ping program drops unnecessary root privileges immediately upon startup:

root@solaris # ppriv -v 1325
1325:   ping -s 192.168.0.1
flags = PRIV_AWARE
        E: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        I: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        P: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        L: none

Let's say we now remove the setuid flag from /usr/sbin/ping:

root@solaris # ls -al /usr/sbin/ping
-r-xr-xr-x   1 root     bin        45016 Apr 26  2005 /usr/sbin/ping

Subsequently, a normal non-root user would no longer be able to properly execute ping:

$ ping -s 192.168.0.1  
ping: socket Permission denied

Why ping Failed

ping failed because it is now missing the net_icmpaccess privilege. To illustrate this, we run ping with the Solaris 10 OS privilege inspection and debugging feature (using ppriv):

$ ppriv -e -D ping -s 192.168.0.1  
ping[1391]: missing privilege "net_icmpaccess" (euid = 100, syscall = 230) for 
"devpolicy" needed at so_socket+0x9d
ping: socket Permission denied

The above occurs because the setuid flag has been removed from ping.

Let's look at the privilege of the parent user shell executing the ping command:

root@solaris # ppriv -v 955
955:    -ksh
flags = <none>
        E: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        I: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        P: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        L: contract_event,contract_observer,cpc_cpu,dtrace_kernel,dtrace_proc,
dtrace_user,file_chown,file_chown_self,file_dac_execute,file_dac_read,
file_dac_search,file_dac_write,file_link_any,file_owner,file_setid,ipc_dac_read,
ipc_dac_write,ipc_owner,net_icmpaccess,net_privaddr,
net_rawaccess,proc_audit,proc_chroot,proc_clock_highres,proc_exec,proc_fork,
proc_info,proc_lock_memory,proc_owner,proc_priocntl,proc_session,proc_setid,
proc_taskid,proc_zone,sys_acct,sys_admin,sys_audit,sys_config,sys_devices,
sys_ipc_config,sys_linkdir,sys_mount,sys_net_config,sys_nfs,sys_res_config,
sys_resource,sys_suser_compat,sys_time

This clearly is missing the net_icmpaccess privilege from its E, I, and P privilege set.

The Parent Shell Privileges

Let's assign the net_icmpaccess privilege to the parent shell process (pid 955):

#ppriv -s PEI-net_icmpaccess 955

Once again, let's look at the shell privileges:

root@solaris # ppriv -v 955                   
955:    -ksh
flags = <none>
        E: file_link_any,net_icmpaccess,proc_exec,proc_fork,proc_info,proc_session
        I: file_link_any,net_icmpaccess,proc_exec,proc_fork,proc_info,proc_session
        P: file_link_any,net_icmpaccess,proc_exec,proc_fork,proc_info,proc_session
        L: contract_event,contract_observer,cpc_cpu,dtrace_kernel,dtrace_proc,
dtrace_user,file_chown,file_chown_self,file_dac_execute,file_dac_read,
file_dac_search,file_dac_write,file_link_any,file_owner,file_setid,ipc_dac_read,
ipc_dac_write,ipc_owner,net_icmpaccess,net_privaddr,
net_rawaccess,proc_audit,proc_chroot,proc_clock_highres,proc_exec,proc_fork,
proc_info,proc_lock_memory,proc_owner,proc_priocntl,proc_session,proc_setid,
proc_taskid,proc_zone,sys_acct,sys_admin,sys_audit,sys_config,sys_devices,
sys_ipc_config,sys_linkdir,sys_mount,sys_net_config,sys_nfs,sys_res_config,
sys_resource,sys_suser_compat,sys_time

We now try a ping as a non-root user from shell process 955:

$ ping -s 192.168.0.1
PING 192.168.0.1: 56 data bytes
64 bytes from silence.mshome.net (192.168.0.1): icmp_seq=0. time=0.313 ms
64 bytes from silence.mshome.net (192.168.0.1): icmp_seq=1. time=0.607 ms
64 bytes from silence.mshome.net (192.168.0.1): icmp_seq=2. time=0.566 ms

Success!

Automatic Assignment

But how do we assign individual shells the necessary privileges? Do we have to assign them every time the user logs in or requires them?

Well, one way is to add the following user entry to /etc/user_attr, like so:

johndoe::::defaultpriv=basic,net_icmpaccess

The above would automatically provide user johndoe (a non-root privilege user) the appropriate privileges to run ping without requiring that ping have the setuid/setgid flag set on its executable binary.

The above example illustrates a method to allow us to clear setuid/setgid flags from non-PA executables, which would normally require them.

Flaw

There is a flaw in using /etc/user_attr to set the default privilege, of course: All the processes of user admin would now also have net_icmpaccess, even though they might not require this particular privilege.

[Apr 12, 2006] Privilege Debugging in the Solaris 10 Operating System (pdf)

a Sun BluePrints article, describes how to profile applications and services to determine which Solaris 10 privileges they attempt to use. Organizations can then restrict those applications and services so that they are granted only the absolutely necessary privileges that they need to fulfill their intended purpose.

[May 27, 2005] Enforcing a "Two Man Rule" Using RBAC in the Solaris 10 OS

Learn how to use Role-Based Access Control to enforce the "Two Man Rule", which restricts access so that two people must work in concert to execute highly privileged operations.

Process Rights Management - Tutorial

search.cpan.org: Sun::Solaris::Privilege - Perl interface to privilege sets.

This module provides wrappers for the Privilege-related system and library calls. Also provided are constants from the various Privilege-related headers and dynamically generated constants for all the privileges and privilege sets.

[Feb 11, 2005] Casper Dik's Weblog Solaris Privileges

So what makes Solaris Privileges different? Why didn't we copy something else like Trusted Solaris Privileges or "POSIX" capabilities?

Let's start from what we formulated as our requirements near the beginning of our project.

One of the important features of Solaris is complete binary backward compatibility; in order to offer that we needed to design the privilege subsystem in such a manner that current practices, binaries and products would continue to work. Of course, some have solved this issue by providing a system wide knob to turn: root / root + privileges / just privileges. We don't like knobs in our OS; specifically not ones which drastically alter the behaviour of a system. It makes it harder to develop software; it needs to work for all settings. Certain products may require conflicting settings, and so on. So we decided on a "per-process" knob which is largely automatic

With backward compatibility comes the onus on the software developer to develop future proof interfaces; that ruled out all other interfaces as they all have fixed bitmaps and fixed privilege/capability numbers, fixed structure sizes in the programmer visible parts of the system. Solaris Privileges have none of that. And while we could savely reuse the names of the Trusted Solaris interfaces we can not redefine interfaces even from a defunct standard. So we have interfaces which smell like Trusted Solaris but with a completely new userland representation of privileges and privilege sets. We can never have more signals; but we can have more privileges and more privilege sets!

The privileges and privilege sets in Solaris 10 are represented to userland processes and non-core kernel modules as strings; privilege sets are bitmasks of undetermined size; they can only be allocated through the C library routines. Privilege set names are also strings and not plain integer indices; this gives us even more flexibility. A Solaris binary compiled for 4 privilege sets of each 32 privileges will continue to work on a Solaris system with 5 privilege sets each of which can contain 64 privileges and with all the privileges having their internal representation renumbered.

[Feb 11, 2005] BigAdmin Feature Article- The Least Privilege Model in the Solaris ... by Amy Rich

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.

cool feature i am using (Score:5, Interesting)
by Anonymous Coward on Friday February 20, @08:08AM (#8338473)
i try with solaris express and I find a cool feature called "ppriv" like this:

gta3# ppriv $$
1124: bash
flags = 0x0
E: all
I: basic
P: all
L: all

Ok, so I am root I have all privileges I think

but now look at rpcbind, it is running as daemon but has less priviliges even than normal processes

gta3# ppriv 100182
100182: /usr/sbin/rpcbind
flags = 0x2
E: net_privaddr,proc_fork,sys_nfs
I: none
P: net_privaddr,proc_fork,sys_nfs
L: all

see, it does not have privilege to do 'exec'... there are 30 or more privileges and it has only 3. So i guess this means some stack attack will not work against it like exec shell

also i can run and see privileges like thids

gta3$ ppriv -D -e cat /etc/shadow
cat[100619]: missing privilege "file_dac_read" (euid = 77293, syscall = 225) needed at ufs_iaccess+0xd2
cat: cannot open /etc/shadow

not sure what this means?

Recommended Links

Google matched content

Softpanorama Recommended

Top articles

Sites

General info:

Reference

Process privilege sets and their attributes are viewed and modified by the program ppriv(1). The ppriv(1) program arguments follow the syntax:

  /usr/bin/ppriv -l [-v] [privilege-specification...]

  /usr/bin/ppriv [-v] [-S] [-D | -N] [-s spec] [pid | core]

  /usr/bin/ppriv -e [-D | -N] [-s spec] command [arg...]

The preceding options are defined as:

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:

ppriv -v 1746

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:

pcred 193
193: e/r/suid=0 e/r/sgid=0

ppriv -v 193

193: /usr/lib/inet/inetd start
flags = <none>
        E: contract_event,contract_observer,cpc_cpu,dtrace_kernel,
	dtrace_proc,dtrace_user,file_chown,file_chown_self,
	file_dac_execute,file_dac_read,file_dac_search,
	file_dac_write,file_link_any,file_owner,file_setid,
	ipc_dac_read,ipc_dac_write,ipc_owner,net_icmpaccess,
	net_privaddr,net_rawaccess,proc_audit,proc_chroot,
	proc_clock_highres,proc_exec,proc_fork,proc_info,
	proc_lock_memory,proc_owner,proc_priocntl,proc_session,
	proc_setid,proc_taskid,proc_zone,sys_acct,sys_admin,
	sys_audit,sys_config,sys_devices,sys_ipc_config,
	sys_linkdirsys_mount,sys_net_config,sys_nfs,
	sys_res_config,sys_resource,sys_suser_compat,
	sys_time
        I: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        P: contract_event,contract_observer,cpc_cpu,dtrace_kernel,
	dtrace_proc,dtrace_user,file_chown,file_chown_self,
	file_dac_execute,file_dac_read,file_dac_search,
	file_dac_write,file_link_any,file_owner,file_setid,
	ipc_dac_read,ipc_dac_write,ipc_owner,net_icmpaccess,
	net_privaddr,net_rawaccess,proc_audit,proc_chroot,
	proc_clock_highres,proc_exec,proc_fork,proc_info,
	proc_lock_memory,proc_owner,proc_priocntl,proc_session,
	proc_setid,proc_taskid,proc_zone,sys_acct,sys_admin,
	sys_audit,sys_config,sys_devices,sys_ipc_config,
	sys_linkdir,sys_mount,sys_net_config,sys_nfs,
	sys_res_config,sys_resource,sys_suser_compat,sys_time
        L: contract_event,contract_observer,cpc_cpu,dtrace_kernel,
	dtrace_proc,dtrace_user,file_chown,file_chown_self,
	file_dac_execute,file_dac_read,file_dac_search,
	file_dac_write,file_link_any,file_owner,file_setid,
	ipc_dac_read,ipc_dac_write,ipc_owner,net_icmpaccess,
	net_privaddr,net_rawaccess,proc_audit,proc_chroot,
	proc_clock_highres,proc_exec,proc_fork,proc_info,
	proc_lock_memory,proc_owner,proc_priocntl,proc_session,
	proc_setid,proc_taskid,proc_zone,sys_acct,sys_admin,
	sys_audit,sys_config,sys_devices,sys_ipc_config,sys_linkdir,
	sys_mount,sys_net_config,sys_nfs,sys_res_config,
	sys_resource,sys_suser_compat,sys_time

In this third example, we take a look at fmd(1M), a process that is privilege aware. Note the flags setting and the limitations on E, I, P, and L:

ppriv -v 306
306: /usr/lib/fm/fmd/fmd
flags = PRIV_AWARE
        E: file_dac_execute,file_dac_read,file_dac_search,
	file_dac_write,file_link_any,file_owner,proc_exec,
	proc_fork,proc_info,proc_owner,proc_priocntl,proc_session,
	sys_admin,sys_config,sys_devices,sys_res_config
        I: file_dac_execute,file_dac_read,file_dac_search,
	file_dac_write,file_link_any,file_owner,proc_exec,
	proc_fork,proc_info,proc_owner,proc_priocntl,proc_session,
	sys_admin,sys_config,sys_devices,sys_res_config
        P: file_dac_execute,file_dac_read,file_dac_search,
	file_dac_write,file_link_any,file_owner,proc_exec,
	proc_fork,proc_info,proc_owner,proc_priocntl,proc_session,
	sys_admin,sys_config,sys_devices,sys_res_config
        L: file_dac_execute,file_dac_read,file_dac_search,
	file_dac_write,file_link_any,file_owner,proc_exec,
	proc_fork,proc_info,proc_owner,proc_priocntl,proc_session,
	sys_admin,sys_config,sys_devices,sys_res_config

In this final example, we take a look at the lockd(1M) process which is PRIV_AWARE and extremely limited in its access:

ppriv -v 161
161: /usr/lib/nfs/lockd
flags = PRIV_AWARE
        E: sys_nfs
        I: none
        P: sys_nfs
        L: none

Random Findings

[May 20, 2004] Secure programmer Minimizing privileges David A. Wheeler ([email protected])
Research Staff Member, Institute for Defense Analyses.

Secure programs must minimize privileges so that any bugs are less likely to be become security vulnerabilities. This article discusses how to minimize privileges by minimizing the privileged modules, the privileges granted, and the time the privileges are active. The article discusses not only some of the traditional UNIX-like mechanisms for privileges, but some of the newer mechanisms like the FreeBSD jail(), the Linux Security Modules (LSM) framework, and Security-Enhanced Linux (SELinux).

On March 3rd, 2003, Internet Security Systems warned of a serious vulnerability in Sendmail. All electronic mail is transferred using a mail transfer agent (MTA), and Sendmail is the most popular MTA, so this warning affected many organizations worldwide. The problem was that an e-mail message with a carefully-crafted "from," "to," or "cc" field could give the sender complete (root) control over any machine running Sendmail as it's commonly configured. Even worse, typical firewalls would not protect interior machines from this attack.

The immediate cause of the vulnerability was that one of Sendmail's security checks was flawed, permitting a buffer overflow. But a significant contributing factor is that Sendmail is often installed as a monolithic "setuid root" program, with complete control over the system it runs on. Thus, any flaw in Sendmail can give an attacker immediate control over the entire system.

Is this design necessary? No; a popular competing MTA is Wietse Venema's Postfix. Postfix, like Sendmail, does a number of security checks, but Postfix is also designed as a set of modules that minimize privilege. As a result, Postfix is generally accepted as a more secure program than Sendmail. This article discusses how to minimize privileges, so you can apply the same ideas to your programs.

Basics of minimizing privileges
Real-world programs have bugs in them. It's not what we want, but it's certainly what we get. Complicated requirements, schedule pressure, and changing environments all conspire to make useful bugless programs unlikely. Even programs formally proved correct using sophisticated mathematical techniques can have bugs. Why? One reason is that proofs must make many assumptions, and usually some of those assumptions aren't completely true. Most programs aren't examined that rigorously anyway, for a variety of reasons. And even if there are no bugs today (unlikely), a maintenance change or a change in the environment may introduce a bug later on. So, to handle the real world, we have to somehow develop secure programs in spite of the bugs in our programs.

One of the most important ways to secure programs, in spite of these bugs, is to minimize privileges. A privilege is simply permission to do something that not everyone is allowed to do. On a UNIX-like system, having the privileges of the "root" user, of another user, or being a member of a group are some of the most common kinds of privileges. Some systems let you give privileges to read or write a specific file. But no matter what, to minimize privileges:

These are really goals, not hard absolutes. Your infrastructure (such as your operating system or virtual machine) may not make this easy to do precisely, or the effort to do it precisely may be so complicated that you'll introduce more bugs trying to do it precisely. But the closer you get to these goals, the less likely it will be that bugs will cause a security problem. Even if a bug causes a security problem, the problems it causes are likely to be less severe. And if you can ensure that only a tiny part of the program has special privileges, you can spend a lot of extra time making sure that one part resists attacks. This idea isn't new; the excellent 1975 paper by Saltzer and Schroeder discussing security principles specifically identifies minimizing privileges as a principle (see Resources). Some ideas, such as minimizing privileges, are timeless.

The next three sections discuss these goals in turn, including how to implement them on UNIX-like systems. After that we'll discuss some of the special mechanisms available in FreeBSD and Linux, including a discussion about NSA's Security-Enhanced Linux (SELinux).

Minimize privileged modules

As noted earlier, only the parts of the program that need a privilege should have the privilege. This means that when you're designing your program, try to break the program into separate parts so that only small and independent parts require special privileges.

If different parts must run concurrently, use processes (not threads) on UNIX-like systems. Threads share their security privileges, and a malfunctioning thread can interfere with all the other threads in a process. Write the privileged parts as though the rest of the program was attacking it: it might, someday! Make sure that the privileged part only does as little as possible; limited functionality means there's less to exploit.

One common approach is to create a command-line tool with special privileges (such as being setuid or setgid) that has an extremely limited function. The UNIX passwd command is an example; it's a command-line tool with special privileges to change the password (setuid root), but the only thing it can do is change passwords. Various GUI tools can then ask passwd to do the actual changing. Where possible, try to avoid creating setuid or setgid programs at all, because it's very difficult to make sure that you're really protecting all inputs. Nevertheless, sometimes you need to create setuid/setgid programs, so when it's necessary, make the program as small and as limited as possible.

There are many other approaches. For example, you could have a small "server" process that has special privileges; that server allows only certain requests, and only after verifying that the requester is allowed to make the request. Another common approach is to start a program with privileges, which then forks a second process that gives up all privileges and then does most of the work.

Be careful how these modules communicate with each other. On many UNIX-like systems, the command-line values and environment variable values can be viewed by other users, so they aren't a good way to privately send data between processes. Pipes work well, but be careful to avoid deadlock (a simple request/response protocol, with flushing on both sides, works well).

Minimize privileges granted

Ensure that you only grant the privileges a program actually needs -- and no more. The primary way that UNIX processes get privileges are the user and groups they can run as. Normally, processes run as the user and groups of their user, but a "setuid" or "setgid" program picks up the privileges of the user or group that owns the program.

Sadly, there are still developers on UNIX-like systems that reflexively give programs "setuid root" privileges. These developers think that they've made things "easy" for themselves, because now they don't have to think hard about exactly what privileges their programs need. The problem is that, since these programs can do literally anything on most UNIX-like systems, any bugs can quickly become a security disaster.

Don't give all possible privileges just because you need one simple task done. Instead, give programs only the privileges they need. If you can, run them as setgid not setuid -- setgid gives fewer privileges. Create special users and groups (don't use root), and use those for what you need. Make sure your executables are owned by root and only writeable by root, so others can't change them. Set very restrictive file permissions -- don't let anyone read or write files unless absolutely necessary, and use those special users and groups. An example of all this might be the standard conventions for game "top ten" scores. Many programs are "setgid games" so that only the game programs can modify the "top ten" scores, and the files storing the scores are owned by the group games (and only writeable by that group). Even if an attacker broke into a game program, all he could do would be to change the score files. Game developers still need to write their programs to protect against malicious score files, however.

One useful tool -- that unfortunately is a little hard to use -- is the chroot() system call. This system call changes what the process views when it views the "root" of the filesystem. If you plan to use this -- and it can be useful -- be prepared to take time to use it well. The "new root" has to be carefully prepared, which is complicated because correct application depends on the specifics of the platform and of the application. You must be root to make the chroot() call, and you should quickly change to non-root (a root user can escape a chroot environment, so if it's to be effective, you need to drop that privilege). And chroot doesn't change the network access. This can be a useful system call, so it's sometimes necessary to consider it, but be prepared for effort.

One often-forgotten tool is to limit resources, both for storage and for processes. This can be especially useful for limiting denial-of-service attacks:

Minimize privileges' time

Give privileges only when they're needed -- and not a moment longer.

Where possible, use whatever privileges you need immediately and then permanently give them up. Once they're permanently given up, an attack later on can't try to exploit those privileges in novel ways. For example, a program that needs a single root privilege may get started as root (say, by being setuid root) and then switch to running as a less-privileged user. This is the approach taken by many Internet servers (including the Apache Web server). UNIX-like systems don't let just any program open up the TCP/IP ports 0 through 1023; you have to have root privileges. But most servers only need to open the port when they first start up, and after that they don't need the privilege any more. One approach is to run as root, open the privileged port as soon as possible, and then permanently drop root privileges (including any privileged groups the process belongs to). Try to drop all other derived privileges too; for example, close files requiring special privileges to open as soon as you can.

If you can't permanently give up the privilege, then you can at least temporarily drop the privilege as often as possible. This isn't as good as permanently dropping the privilege, since if an attacker can take control of your program, the attacker can re-enable the privilege and exploit it. Still, it's worth doing. Many attacks only work if they trick the privileged program into doing something unintended while its privileges are enabled (for example, by creating weird symbolic links and hard links). If the program doesn't normally have its privileges enabled, it's harder for an attacker to exploit the program.

Newer mechanisms

The principles we've discussed up to this point are actually true for just about any operating system, and the general mechanisms have been very similar between just about all UNIX-like systems since the 1970s. That doesn't mean they're useless; simplicity and the test of time have their own advantages. But some newer UNIX-like systems have added mechanisms to support least privilege that are worth knowing about. While it's easy to find out about the time-tested mechanisms, information about the newer mechanisms isn't as widely known. So, here I'll discuss a few selected worthies: the FreeBSD jail(), the Linux Security Modules (LSM) framework, and Security-Enhanced Linux (SELinux).

FreeBSD jail()

The system call chroot() has a number of problems, as noted above. For example, it's hard to use correctly, root users can still escape from it, and it doesn't control network access at all. The FreeBSD developers decided to add a new system call to counteract these problems, named jail(). This call is similar to chroot(), but strives to be both easier to use and more effective. Inside a jail, all requests (even root's) are limited to the jail, processes can only communicate with other processes in that jail, and the system blocks the typical ways root users try to escape from the jail. A jail is assigned a specific IP address, and can't use any others as its own address.

The jail() call is unique to FreeBSD, which currently limits its utility. But, there's a lot of cross-pollination between the various OSS/FS kernels. For example, a version of this jail has been developed for Linux using the Linux Security Framework. And FreeBSD 5 has added a flexible MAC framework (from the TrustedBSD project), including a module with functionality essentially like SELinux's. So don't be surprised to see more of this in the future.

Linux Security Modules (LSM)

At the 2001 Linux Kernel Summit, Linus Torvalds had a problem. Several different security projects, including the Security-Enhanced Linux (SELinux) project, had asked him to add their security approach to the Linux kernel. Problem was, these different approaches were often incompatible. Torvalds didn't have an easy way to determine which was best, so instead he asked the projects to work together to create some sort of general security framework for Linux. That way, administrators could install whichever security approach they wanted on their particular system. After some discussion with Torvalds, Crispin Cowan formed a group to create a general security framework. This framework was named the Linux Security Modules (LSM) framework, and is now part of the standard Linux kernel (as of kernel version 2.6).

Conceptually, the LSM framework is very simple. The Linux kernel still does its normal security checks; for example, if you want to write to a file, you still need write permission to it. However, any time that the Linux kernel needs to decide if access should be granted, it also checks -- asks a security module via a "hook" -- to determine whether or not the action is okay. This way, an administrator can simply pick the security module he wants to use and insert it like any other Linux kernel module. From then on, that security module decides what's allowed.

The LSM framework was designed to be so flexible that it can implement many different kinds of security policies. In fact, several different projects worked together to make sure that the LSM framework is sufficient for real work. For example, the LSM framework includes several calls when internal objects are created and deleted -- not because those operations might get stopped, but so that the security module can keep track of critical data. Several different analysis tools have been used to make sure that the LSM framework didn't miss any important hooks for its purposes. This project turned out to be harder than many imagined, and its success was hard-won.

The LSM made a fundamental design decision that's worth understanding. Fundamentally, the LSM framework was intentionally designed so that almost all of its hooks would be restrictive, not authoritative. An authoritative hook makes the absolute final decision: if the hook says a request should be granted, then it's granted no matter what. In contrast, a restrictive hook can only add additional restrictions; it can't grant new permissions. In theory, if all LSM hooks were authoritative, the LSM framework would be more flexible. One hook, named capable(), is authoritative -- but only because it it has to be to support normal POSIX capabilities. But making all the hooks authoritative would have involved many radical changes to the Linux kernel, and there was doubt that such changes would be accepted.

There were also many concerns that even the smallest bugs would be disastrous if most hooks were authoritative; while making the hooks restrictive meant that users would be unsurprised (no matter what, the original UNIX permissions would still normally work). So the LSM framework developers intentionally chose the restrictive approach, and most of its developers decided that they could work within the framework.

It's important to understand some of the LSM framework's other limitations, too. The LSM framework is designed to support only access control, not other security issues such as auditing. By themselves LSM modules can't log all requests or their results, because they won't see them all. Why? One reason is because the kernel might reject a request without even calling an LSM module; a problem if you wanted to audit the rejection. Also, due to concerns about performance, some proposed LSM hooks and data fields for networks were rejected for the mainline kernel. It's possible to control some network accesses, but it's not enough to support "labelled" network flows (where different packets have different security labels handled by the operating system). These are unfortunate limitations, and not fundamental to the general idea; hopefully the LSM framework will be extended someday to eliminate these limitations.

Still, even with these limitations, the LSM framework can be very useful for adding limits to privileges. Torvalds' goals were essentially met by the LSM framework: "I'm not interested in the fight between different security people. I want the indirection that gets me out of that picture, and then the market can fight out which policy and implementation actually ends up getting used."

So, if you want to limit the privileges you give your programs on Linux, you could create your very own Linux security module. If you want to impose truly exotic limitations, that may be necessary -- and the nice thing is that it's possible. However, this isn't trivial; no matter what, you're still writing kernel code. If possible, you're better off using one of the existing Linux security modules than trying to write your own. There are several LSM modules available, but one of the most mature of the Linux security modules is the Security-Enhanced Linux (SELinux) module, so let's look at that.



Etc

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D


Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to to buy a cup of coffee for authors of this site

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Last modified: March 12, 2019