|
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 |
News | Process Privilege Sets | 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.
- The defined privileges are broken into the groups
contract
,cpc
,dtrace
,file
,ipc
,net
,proc
, andsys
.- The basic privilege set includes all privileges granted to unprivileged processes under the traditional security model:
proc_fork
,proc_exec
,proc_session
,proc_info
, andfile_link_any
.
Each process has four privilege sets in its kernel credentials:
I
): The privileges
inherited on exec
. P
): The maximum set
of privileges for the process. E
): The privileges
currently in effect, a subset of P
. 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.
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 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
PRIV_DTRACE_PROC
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
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
DTrace
kernel-level tracing.
PRIV_FILE_CHOWN
PRIV_FILE_CHOWN_SELF
{_POSIX_CHOWN_RESTRICTED}
is not in effect.
PRIV_FILE_DAC_READ
PRIV_FILE_DAC_SEARCH
PRIV_FILE_DAC_WRITE
PRIV_FILE_OWNER
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
PRIV_NET_PRIVADDR
udp/tcp_extra_priv_ports
"
with the exception of the ports reserved for use by NFS.
PRIV_PROC_SETID
PRIV_PROC_ZONE
zones(5)
.
PRIV_SYS_ADMIN
coreadm(1M)
and nscd(1M)
settings.
PRIV_SYS_CONFIG
PRIV_SYS_DEVICES
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
namefs
). Allow a process to add and remove swap devices.
|
Switchboard | ||||
Latest | |||||
Past week | |||||
Past month |
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
Introduction
This Tech Tip explores using Process Rights Management (PRM) in the Solaris 10 OS, and how PRM enables us to execute
setuid
andsetgid
commands without thesetuid
orsetgid
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 theirsetuid
/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 somesetuid
/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 theping
program.$ ls -al /usr/sbin/ping -r-sr-xr-x 1 root bin 45016 Apr 26 2005 /usr/sbin/pingNow 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: noneLet'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/pingSubsequently, a normal non-root user would no longer be able to properly execute
ping
:$ ping -s 192.168.0.1 ping: socket Permission deniedWhy
ping
Failed
ping
failed because it is now missing thenet_icmpaccess
privilege. To illustrate this, we runping
with the Solaris 10 OS privilege inspection and debugging feature (usingppriv
):$ 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 deniedThe above occurs because the
setuid
flag has been removed fromping
.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_timeThis 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 955Once 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_timeWe 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 msSuccess!
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_icmpaccessThe above would automatically provide user
johndoe
(a non-root privilege user) the appropriate privileges to runping
without requiring thatping
have thesetuid
/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 useradmin
would now also havenet_icmpaccess
, even though they might not require this particular privilege.
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.
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.
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.
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.
ppriv(1)
Command
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
, andsys
. The basic privilege set includes all privileges granted to unprivileged processes under the traditional security model:proc_fork
,proc_exec
,proc_session
,proc_info
, andfile_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: allOk, 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: allsee, 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?
Google matched content |
General info:
jail()
. 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:
-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. 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
[May 20, 2004]
Secure programmer Minimizing privileges David A. Wheeler
([email protected])
Research Staff Member, Institute for Defense Analyses.
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:
- Give a privilege to only the parts of the program needing it
- Grant only the specific privileges that part absolutely requires
- Limit the time those privileges are active or can be activated to the absolute minimum
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 askpasswd
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 thechroot()
call, and you should quickly change to non-root (a root user can escape achroot
environment, so if it's to be effective, you need to drop that privilege). Andchroot
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:
- For storage, you can set quotas (limits) for the amount of storage or the number of files, per user and per group, for every mounted filesystem. On GNU/Linux systems see quota(1), quotactl(2), and quotaon(8) for more about this, but although they're not quite everywhere, quota systems are included in most UNIX-like systems. On GNU/Linux and many other systems, you can set "hard" limits (never to exceed) and "soft" limits (which can be temporarily exceeded).
- For processes, you can set a number of limits such as the number of open files, number of processes, and so on. Such capabilities are actually part of standards (such as the Single UNIX Specification), so they've nearly ubiquitous on UNIX-like systems; for more information, see getrlimit(2), setrlimit(2), and getrusage(2), sysconf(3), and ulimit(1). Processes can never exceed the "current limit," but they can raise the current limits all the way up to the "upper limit." Unfortunately, there's a weird terminology problem here that can trip you up. The "current limit" is also called the "soft" limit, and the upper limit is also called the "hard" limit. Thus, you have the bizarre situation that processes can never exceed the soft (current) limit of the process limits -- while for quotas you can exceed the soft limits. I suggest using the terms "current limit" and "upper limit" for process limits (never using the terms "soft" and "hard") so there's no confusion.
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.
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).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, namedjail()
. This call is similar tochroot()
, 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.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.
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 quotes : Somerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose Bierce : Bernard 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 DOS : Programming Languages History : PL/1 : Simula 67 : C : History of GCC development : Scripting 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-Month : How 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