Wednesday Nov 04, 2009
Today, I am very happy to announce the availability of a new Solaris 10 Security Deep Dive training. This version has been updated for Solaris 10 10/2009 (also known as Update 8). From a security perspective, there have only been a few updates since my last posted version, but it is always good to be current. Items added in this new version include: ZFS user and group quotas, ZFS pre-defined ACL sets, NTPv4, and nss_ldap shadowAccount support. In addition, there was a bit of cleanup throughout and a new example was added for Trusted Extensions.
As usual, I have made this content available in both OpenDocument Format (ODF) and PDF. If you are using Microsoft Office, you can use the Sun MS Office ODF Plugin to read the source document.
For those of you who have downloaded one of the previous versions, thank you! There have been nearly 8,000 downloads of this presentation so far! If you have not had a chance, I would encourage you to download and check out a copy today. It is really amazing how many new and updated security features and capabilities there are in Solaris 10. If you have been away from Solaris (even Solaris 10) for a while, I am sure you will be shocked with what you can do today! As always, feedback is greatly appreciated!
Take care!
Glenn
Technorati Tag:
OpenSolaris
Solaris
security
Monday Jun 15, 2009
It has sure been a busy month and really it has just begun. Today, I am happy to announce the availability of my Solaris 10 Security Deep Dive presentation, updated for the just released Solaris 10 05/2009 (Update 7). From a security perspective, there have only been a few updates since my last posted version, for Solaris 10 10/2008 (Update 6), but it is always good to be current. Of particular interest is a new slide focused on IPsec and IKE. As usual, I have made this content available in both OpenDocument Format (ODF) and PDF. If you are using Microsoft Office, you can use the Sun MS Office ODF Plugin to read the source document.
For those of you who have downloaded one of the previous versions, thank you! There have been nearly 5,000 downloads of this presentation so far! If you have not had a chance, I would encourage you to download and check out a copy today. It is really amazing how many new and updated security features and capabilities there are in Solaris 10. If you have been away from Solaris (even Solaris 10) for a while, I am sure you will be shocked with what you can do today! As always, feedback is greatly appreciated!
Take care!
Glenn
Technorati Tag:
OpenSolaris
Solaris
security
hardening
Friday Feb 13, 2009

Virtual Glenn is a pretty strange concept, but for those who can move past it, check this out! This is a picture of my SecondLife avatar in front of the Solaris Campus stage. On February 24th, 2009 at 9 AM PT / 12 PM ET, I will be participating in an expert chat that will be loosely based around my blog article titled Top 5 Solaris 10 Security Features You Should Be Using. I will be talking a bit about each of the five items as well as answering questions. In total, the event will last about an hour and should be a lot of fun (assuming I can overcome being a SecondLife n00b!)
This will be my first presentation inside of a virtual world, and I would encourage anyone who is interested to get a login, a copy of the client, and join me on the 24th to have a little fun a world away. For more information, check out the Sun Virtual Worlds posting for the event! Hope to see you there!
Wednesday Dec 10, 2008
Special thanks to Matt Ingenthron for pointing out that mod_privileges has been integrated back in the Apache trunk (manual) recently. For more information check out NIQ's Soapbox posting on the subject.
Looks like I will have to find a new target (I am looking at you MySQL!) for my BluePrints. I have used the Apache with SMF privileges example in a few publications including Limiting Service Privileges in the Solaris 10 Operating System (2005) and Privilege Debugging in the Solaris 10 Operating System (2006). The content of these papers is still relevant in the general sense, but with the introduction of mod_security, some of this content will no longer be as useful for Apache. That said, lots of other services can and do benefit from the techniques described.
If you find yourself ever wanting to do something similar - converting your services to be privilege aware on Solaris 10, check out the Sun BluePrints article Privilege Bracketing in the Solaris 10 Operating System (2006). Also, check out the OpenSolaris Security Community project on Privilege Debugging as it can help you in finding out what privileges your programs and services need.
Until next time!
Glenn
Technorati Tag:
Apache
OpenSolaris
Solaris
security
Friday Nov 14, 2008
It must be that time of year again. At Sun's Customer Engineering Conference this year, I unveiled the latest update to my Solaris 10 Security Deep Dive Presentation. This version has been updated based upon Solaris 10 10/08 (Update 6) which means it is in sync with the most recently shipping version of Solaris 10. This version is in OpenDocument Format. Should you want a PDF version, you can use this copy.
The last update that I had posted was downloaded more than 2,000 times. That is a great number for such a specialized and technical topic. With all of these downloads, however, I have yet to hear from you! Please be sure to send along your feedback! I am particularly interested in things like:
- Does the content meet your needs? How can it be improved?
- What are your security requirements not met today by Solaris 10? What is your wish list?
- Is their content where you would like more detailed information (e.g., a BluePrint)?
As I said in my last Solaris 10 Security Update... If you have not taken a look into what Solaris 10 can offer recently, you really must give it a look! Also, be on the look out for a posting very soon on a project called Immutable Service Containers. With that as a teaser, I will sign off for today...
Take care!
Glenn
Technorati Tag:
OpenSolaris
Solaris
security
Tuesday Apr 25, 2006
Dear diary... It has been quite a while since my last posting...
While I have not posted very much to my blog lately, I have been quite busy writing. In fact, since February, the following Sun BluePrints articles have been published:
Today's article talks about how to enable
snoop(1M) in a non-global (or local) zone. In Solaris 10 today, the
ability to use the snoop(1M) command or any other packet sniffer for that matter is restricted to the global zone.
There is no way to snoop traffic from within a zone. Enter the
Configurable
Privileges for Zones project which integrated into
Nevada build 37 and of course is available in
OpenSolaris today.
Using this project and a little device manipulation, you can today get snoop working in a non-global zone, and here is how to do it... But first, a few warnings:
WARNING #1: This approach will allow the local zone to see all of the network traffic associated with the device that
is added. Unless you use separate network interfaces for the global zone and other non-global zones, this means that
following these instructions will allow a zone to see traffic intended for or exchanged with another zone.
WARNING #2: This approach is likely not generally recommended. This is meant only as an illustration of what can
be done and may serve as a useful workaround in some environments until a more recommended, secure and supportable
solution is available.
With that out of the way, let's give it a try!
First, you must configure your zone to include the net_rawaccess privilege. This is done using a new zonecfg(1M) parameter, limitpriv. In the following example, we will assume that we have
previously created and installed a non-global zone, called test. To add the new net_rawaccess privilege, simply use the following command:
# zonecfg -z test
zonecfg:test> set limitpriv=default,net_rawaccess
zonecfg:test> exit
Next, let's boot up the zone and check that the privilege has been successfully added:
# zoneadm -z test boot
# zlogin test
[Connected to zone 'test' pts/5]
Last login: Mon Apr 24 23:49:15 on pts/5
Sun Microsystems Inc. SunOS 5.11 snv_38 October 2007
# ppriv $$
4547: -sh
flags =
E: basic,contract_event,contract_observer,file_chown,file_chown_self,file_dac_execute,
file_dac_read,file_dac_search,file_dac_write,file_owner,file_setid,ipc_dac_read,
ipc_dac_write,ipc_owner,net_bindmlp,net_icmpaccess,net_mac_aware,net_privaddr,
net_rawaccess,proc_audit,proc_chroot,proc_owner,proc_setid,proc_taskid,sys_acct,
sys_admin,sys_audit,sys_mount,sys_nfs,sys_resource
I: basic
P: basic,contract_event,contract_observer,file_chown,file_chown_self,file_dac_execute,
file_dac_read,file_dac_search,file_dac_write,file_owner,file_setid,ipc_dac_read,
ipc_dac_write,ipc_owner,net_bindmlp,net_icmpaccess,net_mac_aware,net_privaddr,
net_rawaccess,proc_audit,proc_chroot,proc_owner,proc_setid,proc_taskid,sys_acct,
sys_admin,sys_audit,sys_mount,sys_nfs,sys_resource
L: basic,contract_event,contract_observer,file_chown,file_chown_self,file_dac_execute,
file_dac_read,file_dac_search,file_dac_write,file_owner,file_setid,ipc_dac_read,
ipc_dac_write,ipc_owner,net_bindmlp,net_icmpaccess,net_mac_aware,net_privaddr,
net_rawaccess,proc_audit,proc_chroot,proc_owner,proc_setid,proc_taskid,sys_acct,
sys_admin,sys_audit,sys_mount,sys_nfs,sys_resource
Technically speaking what comes next is likely not recommended, but it does work and can help
you out in a pinch if you need to get this functionality working in a non-global zone until
a more recommended method becomes available.
In order to get snoop working in a non-global zone, you must also introduce the network
devices into the zone. The following commands must be executed from the global zone and are
representative only (based on my system's configuration). The actual command you should use
will vary (based on the actual interface name and the major/minor numbers of the device.
On my system, the network interface name is nge0. My first goal is to determine the
major and minor device number associated with the network interface:
# ls -l /dev/nge0
lrwxrwxrwx 1 root root 38 Apr 21 10:02 /dev/nge0 -> ../devices/pci@0,0/pci108e,5347@a:nge0
# ls -l /devices/pci@0,0/pci108e,5347@a:nge0
crw-rw-rw- 1 root root 96, 1 Apr 22 10:46 /devices/pci@0,0/pci108e,5347@a:nge0
With this information, we can now create the network device in the non-global zone:
# zonecfg -z test info zonepath
zonepath: /my/zones/test
# cd /my/zones/test/dev
# mknod nge0 c 96 1
# ls -l nge0
crw-r--r-- 1 root root 96, 1 Apr 25 13:00 nge0
All the hard work is now done. With the privilege and device added to the zone, you can now use snoop!
# snoop -d nge0
Using device /dev/nge0 (promiscuous mode)
192.168.1.11 -> test TCP D=22 S=62991 Syn Seq=2109859625 Len=0 Win=49640 Options=
test -> 192.168.1.11 TCP D=62991 S=22 Syn Ack=2109859626 Seq=377273646 Len=0 Win=49640 Options=
192.168.1.11 -> test TCP D=22 S=62991 Ack=377273647 Seq=2109859626 Len=0 Win=49640
test -> 192.168.1.11 TCP D=62991 S=22 Push Ack=2109859626 Seq=377273647 Len=20 Win=49640
Voila! Piece of cake! Just use this tip with caution as you do not inadvertantly want to expose yourself.
Peek-a-boo! I'll see you (later!)
Take care,
g
Technorati Tag:
OpenSolaris
Solaris
security
Sunday Feb 12, 2006
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
Technorati Tag:
OpenSolaris
Solaris
security
Tuesday Jun 14, 2005
Previously, we talked about how the ping program was modified in Solaris 10 to be privilege aware. During that discussion, it was noted that the functions used in the ping program were private to the OpenSolaris ON (OS and Networking) consolidation. While this is fine for programs like ping that reside in that consolidation, it does not offer a solution to programs in other consolidations or for those developed external to OpenSolaris. As a companion to that article, let's now discuss how we can adapt ping.c to use the public privilege manipulation functions yet still accomplish the same result - making the program privilege-aware and implementing bracketing around privileged operations.
Without further ado, let's just dive into the code. By way of convention, I will be showing only the changes that need be implemented to covert the original ping.c program to use the new public functions.
The first thing that you will notice is that a different header file is used. If you want to use the public interfaces, then you should be sure to include priv.h and not priv_utils.h:
72c72
< #include <priv_utils.h>
---
> #include <priv.h>
Next, we move to the section of the code that configured the privilege sets at the start of the program. This was done in order to drop any privileges that were not needed and disable those that were left (and not needed right now). This was originally accomplished using the __init_suid_priv function which provided a convenient wrapper for the functionality described below. Rather than a single line, we need to do a little more work. To make the code easier to follow, a new function, setup_privs, was created to do the initial privilege operations. This handles the majority of the work originally done by __init_suid_priv. This code is fairly well documented, so I will not go into too much detail as to what it does.
225a226
> static priv_set_t *setup_privs(void);
227a229,298
> * setup_privs()
> */
> priv_set_t *
> setup_privs(void)
> {
> priv_set_t *pPrivSet = NULL;
> priv_set_t *lPrivSet = NULL;
>
> /*
> * Start with the 'basic' privilege set and then remove any
> * of the 'basic' privileges that will not be needed by this
> * process. The 'net_icmpaccess' privilege will be added
> * since we know that we will need it for the permitted set.
> */
>
> if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) {
> perror("priv_str_to_set");
> return (NULL);
> }
>
> /*
> * Let's clear all of the privileges we know we will not
> * need from the 'basic' set.
> */
>
> (void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY);
> (void) priv_delset(pPrivSet, PRIV_PROC_EXEC);
> (void) priv_delset(pPrivSet, PRIV_PROC_FORK);
> (void) priv_delset(pPrivSet, PRIV_PROC_INFO);
> (void) priv_delset(pPrivSet, PRIV_PROC_SESSION);
>
> /* Next add the known required privilege, 'net_icmpaccess' */
>
> (void) priv_addset(pPrivSet, PRIV_NET_ICMPACCESS);
>
> /* Set the permitted privilege set. */
>
> if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
> perror("setppriv(PRIV_SET, PRIV_PERMITTED)");
> return (NULL);
> }
>
> /* Ensure that the 'net_icmpaccess' privilege is off by default. */
>
> if (priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_NET_ICMPACCESS,
> NULL) != 0) {
> perror("priv_set(PRIV_OFF, PRIV_EFFECTIVE)");
> return (NULL);
> }
>
> /* Clear the limit set. */
>
> if ((lPrivSet = priv_allocset()) == NULL) {
> perror("priv_allocset");
> return (NULL);
> }
>
> priv_emptyset(lPrivSet);
>
> if (setppriv(PRIV_SET, PRIV_LIMIT, lPrivSet) != 0) {
> perror("setppriv(PRIV_SET, PRIV_LIMIT)");
> return (NULL);
> }
>
> priv_freeset(lPrivSet);
>
> return (pPrivSet);
> }
>
> /*
So, why do we go through the process of starting with the basic set of
privileges and removing them all? Why not just start out with no
privileges and simply the code? The answer lies in the fact that
the basic privilege set is not intended to be static. Over time
additional non-administrative privileges may be added. If you
started with simply no privileges, then you may find that your code
will fail as it will need a privilege for an operation that previously
did not require one. In essence, this is a way of future-proofing
your code so that it can better adapt to changes in Solaris down the
road.
So at this point, we have defined a function that will help minic most of the behavior that had been done by __init_suid_priv. Let's take a look at how this function is used:
243a315
> priv_set_t *privSet = NULL;
252,253d323
< (void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_NET_ICMPACCESS,
< (char *)NULL);
254a325,337
> if ((privSet = setup_privs()) == NULL) {
> exit(EXIT_FAILURE);
> }
>
> /*
> * Reset the real and effective UIDs for this process.
> */
>
> if (setreuid(getuid(), getuid()) != 0) {
> perror("setreuid");
> exit(EXIT_FAILURE);
> }
>
As you can see, the __init_suid_priv call has been replaced by calls to both setup_privs and setreuid(2) functions. This is a fairly simple replacement since all of the "hard work" was done in the setup_privs function. We capture the privilege set parameter, privSet, as we will need it later in the code when it comes time to relinquish our privileges. Let's continue sequentially down the code to see where other replacements are needed. Frankly, the hard part is over. The rest of the changes needed to complete the conversion from private to public privilege manipulation functions are trivial. Let's take a look at the next replacement:
602c685,687
< __priv_relinquish();
---
> /*
> * Clear the permitted set of the 'net_icmpaccess' privilege.
> */
603a689,696
> (void) priv_delset(privSet, PRIV_NET_ICMPACCESS);
>
> if (setppriv(PRIV_SET, PRIV_PERMITTED, privSet) != 0) {
> perror("setppriv(PRIV_PERMITTED)");
> exit(EXIT_FAILURE);
> }
> priv_freeset(privSet);
>
In this case, we are replacing the __priv_relinquish function with a call to setppriv(2). Before we can do this however, we need to remove the net_icmpaccess privilege from privSet using the priv_delset function. Remember that privSet (returned to us from setup_privs earlier in the code) contains the privileges from the basic set that we had not already dropped as well as the net_icmpaccess privilege. By removing the net_icmpaccess privilege, setppriv will set to the process' permitted privilege set to the non-dropped basic privileges (which in this particular case is none although as Solaris continues to evolve and new non-administrative privileges are added, this may change).
Moving along to the next section of replacement code, we come to where the bracketing of the net_icmpaccess privilege is enforced. In thiscase, the call to __priv_bracket is replaced with a call to priv_set(3C) function. priv_set is called with the PRIV_ON parameter which enables the net_icmpaccess privilege for the process' effective privilege set.
1197c1290,1293
< (void) __priv_bracket(PRIV_ON);
---
> if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_NET_ICMPACCESS, NULL) != 0) {
> perror("priv_set(PRIV_ON, PRIV_EFFECTIVE)");
> exit(EXIT_FAILURE);
> }
Similarly, the companion instance of __priv_bracket is replaced with another call to priv_set once the privileged operations are complete to remove the net_icmpaccess privilege (from the process' effective privilege set) - therefore completing the bracketing of privilege.
1208c1304,1308
< (void) __priv_bracket(PRIV_OFF);
---
> if (priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_NET_ICMPACCESS,
> NULL) != 0) {
> perror("priv_set(PRIV_OFF, PRIV_EFFECTIVE)");
> exit(EXIT_FAILURE);
> }
That is all there is to it. As you can tell, there is a bit more work in the initial setup of a process' privilege sets, but once that is complete, the use of the public privilege manipulation functions is straightforward. I know that this helps to illustrate how you can privilege enable your code whether you choose to use ON specific functions or the public ones defined in the Solaris product documentation. For those who just can't get enough, check out Joep Vesseur's discussion of several developer-focused security enhancements in Solaris 10 (and OpenSolaris).
Last, but certainly not least, I would like to offer my sincere thanks to Casper, Joep and Darren for their help with this article. You guys are the best!
Take care and have fun!
Technorati Tag:
OpenSolaris
Solaris
security
Tuesday Jun 14, 2005
There have been quite a few posts, articles,and resources made available discussing the new process privilege model introduced the Solaris 10
operating system. The majority of them have focused on describing what
this new privilege model is, why it is useful and how it can be used
through mechanisms such as Solaris RBAC, SMF, and ppriv(1). Today, with the launch of OpenSolaris,
I feel the urge to discuss privileges from the view of a software
developer (not that I am one anymore, but please indulge me a
bit). If you are interested in this kind of thing, you can find
more information about this in the Solaris 10 product documentation.
Today, let's look at a how a developer could develop a program to be privilege aware.
In particular, for our example, let's take a set-id program and
configure it such that it:
- drops any privileges that it will never
need;
- enables the remaining privileges exactly when it needs
them;
- relinquishes the use of privileges when they are no longer needed
Sounds pretty straight forward, right? Essentially, we
just want to ensure that a program is only running with those
privileges that it needs, and it activates those privileges only when
it needs them. To illustrate this concept, let's take a look at ping.c. This program was converted to use Solaris privileges by Casper Dik way back in 2003. I chose to use it for this example because:
- the
ping(1M)
source code is simple and straightforward to read and understand, and
- all of the changes needed to make it privilege aware were contained
in one file
There is nothing special about ping with respect to
privileges and the same techniques described below could be applied to
other programs whether they are set-id or not.
So, let's begin this tale back in February of 2003 before the ping command was made privilege aware. In those days, ping was a set-uid root program that controlled its use of privilege using seteuid(2). When the program started as root,
it quickly set its effective UID to the UID of the calling user to run with less privilege. When it came time to execute a
privileged operation, the code issued another seteuid call that reset
its EUID to root so that the privileged operation could succeed.
With
the introduction of process privileges in Solaris 10, this model
was no longer needed. Rather than executing code as EUID 0, specific
privileges are used to define the types of privileged
operations that are be permitted. This is a huge step forward as
privilege aware programs will now run only with the privileges that
they need (exactly when they need them). So, enough of the fluff, let's
get to the code! Note
that all of the following code examples were taken from ping.c.
The first thing that you will notice that if you want to configure a
program to be privilege aware, you will need to include a new header
that will declare functions and define constants used by the privilege
functions described below:
72 #include <priv_utils.h>
With the header out of the way, we move into
main where the first thing that we do is drop all of the privileges
that we do not need:
247 /*
248 * This program needs the net_icmpaccess privileges. We'll fail
249 * on the socket call and report the error there when we have
250 * insufficient privileges.
251 */
252 (void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_NET_ICMPACCESS,
253 (char *)NULL);
Remember that ping is still set-uid root. This means that when it is started, it will have the privileges that have been assigned to root which by default is all.
The purpose of the __init_suid_priv function is to do the following (described in priv_utils.h):
48 /*
49 * Should be run at the start of a set-uid root program;
50 * if the effective uid == 0 and the real uid != 0,
51 * the specified privileges X are assigned as follows:
52 *
53 * P = I + X + B (B added insofar allowable from L)
54 * E = I
55 * (i.e., the requested privileges are dormant, not active)
56 * Then resets all uids to the invoking uid; no-op if euid == uid == 0.
57 *
58 * flags: PU_LIMITPRIVS, PU_CLEARLIMITSET, PU_CLEARINHERITABLE
59 *
60 * Caches the required privileges for use by __priv_bracket().
61 *
62 */
So this function (as used in the ping.c code) will reset the real and effective UID of the process to that of the calling user so that it is no longer running as root.
Further, it will clear the limit set of the process which means that
any children spawned by this process will themselves have no
privileges. Lastly, this function will also add the net_icmpaccess
privilege to the process' permitted set so that it can be enabled and
used when necessary. The process' four privilege sets (effective,
inheritable, permitted and limit) will
look like this:
# ppriv -S `pgrep ping`
14527: ping localhost
flags = PRIV_AWARE
E: basic
I: basic
P: basic,net_icmpaccess
L: none
According to ppriv, the net_icmpaccess privilege is used to allow a process to send and receive ICMP packets:
$ ppriv -lv net_icmpaccess
net_icmpaccess
Allows a process to send and receive ICMP packets.
So rather than having the potential to access all of root's
power, a ping process will now run as the calling user's UID with a single (non-basic) privilege that allows the sending or receiving ICMP packets. Sounds great,
but we are not done yet! In priv_utils.h, you will find more instruction as to how to proceed:
65 /*
66 * After calling __init_suid_priv we can __priv_bracket(PRIV_ON) and
67 * __priv_bracket(PRIV_OFF) and __priv_relinquish to get rid of the
68 * privileges forever.
69 */
Recall that before ping was made privilege aware,
it used seteuid to control when its privileges were in effect. This was necessary for the program to only run in a privileged
capacity when it needs to execute privileged operations. In the new
model, the process leverages a capability called privilege bracketing
which controls when a privilege (defined in the process' permitted set)
is made effective. To see this capability in action, take a look at the
following code which appears in the setup_socket function:
1196 /* now we need the net_icmpaccess privilege */
1197 (void) __priv_bracket(PRIV_ON);
1198
1199 recv_sock = socket(family, SOCK_RAW,
1200 (family == AF_INET) ? IPPROTO_ICMP : IPPROTO_ICMPV6);
1201
1202 if (recv_sock < 0) {
1203 Fprintf(stderr, "%s: socket %s\n", progname, strerror(errno));
1204 exit(EXIT_FAILURE);
1205 }
1206
1207 /* revert to non-privileged user after opening sockets */
1208 (void) __priv_bracket(PRIV_OFF);
As you can see, the __priv_bracket function is used around the privileged operation (in this case the socket(2)
call) to
control whether or not the instructions are executed with privilege.
This is one form of privilege bracketing that enables and
disables all of the privileges cached by the __init_suid_priv function called earlier in the program (and described above). There are other privilege manipulation functions available to allow more fine grained control if needed.
Our
final step is to relinquish the privileges when we are sure that we will no longer need them:
602 __priv_relinquish();
The __priv_relinquish function is called after the setup_socket function has completed in main. Since the program will no longer
need the net_raw_icmpaccess privilege (the only non-basic privilege available to the process), it can now be safely dropped. The
__priv_relinquish function is used for just this purpose. Note that once a privilege is relinquished, it is gone. If you
think that you may need the privilege later in the program, you should simply disable its use (removing it from the process'
effective set) until you need it again.
That's all there is to it. Pretty cool, eh?
One thing that I should mention, however. In the development of this article, I was reminded by Darren Moffat that the privilege functions and header file described above are
private to Solaris (and more specifically the ON [OS and Networking]
consolidation). So, the approach described above will work just
fine if you are modifying set-id programs in ON such as atq, atrm, traceroute, lpstat,
and the like. If you want to make other programs privilege aware,
you can do this using a set of privilege manipulation functions described in the
Solaris 10 product documentation. Regardless of the
method you use, however, there should be nothing to stop you from improving your
code by making your programs privilege aware and bracketing privileged
operations.
Take care and have fun!
Technorati Tag:
OpenSolaris
Solaris
security
Friday Sep 24, 2004
This entry is a continuation of my list of lesser known and/or publicized security enhancements to the Solaris 10 OS. In this update,
I will be talking about how to restrict the output of the ps(1)
command such that users can only see processes that they own. This is a very useful capability especially for ISPs and other
organizations that do not want to allow users to see what other users are doing.
This new feature would not have been possible without the introduction of process privileges into the Solaris 10 OS. For a great overview
of process privileges, see Casper Dik's blog entry
on this topic. Be sure to read his article to get a more in depth understanding of process privileges.
So, before we begin, let's see what the output of ps -aef might look like for an average user (in this case, gmb):
$ ps -aef
UID PID PPID C STIME TTY TIME CMD
root 0 0 0 Sep 23 ? 0:07 sched
root 1 0 0 Sep 23 ? 0:01 /sbin/init
root 2 0 0 Sep 23 ? 0:00 pageout
root 3 0 0 Sep 23 ? 2:31 fsflush
root 393 1 0 Sep 23 ? 0:00 /usr/sbin/auditd
root 7 1 0 Sep 23 ? 0:11 /lib/svc/bin/svc.startd
root 9 1 0 Sep 23 ? 0:19 svc.configd
root 176 1 0 Sep 23 ? 0:00 /usr/sbin/syslogd
root 64 1 0 Sep 23 ? 0:00 /usr/sbin/nscd
daemon 91 1 0 Sep 23 ? 0:02 kcfd
root 170 1 0 Sep 23 ? 0:01 /usr/lib/utmpd
gmb 1795 1792 0 22:17:26 pts/1 0:00 -sh
root 1527 7 0 00:53:24 console 0:00 /usr/bin/login
root 82 1 0 Sep 23 ? 0:00 /usr/lib/sysevent/syseventd
smmsp 334 1 0 Sep 23 ? 0:00 /usr/lib/sendmail -Ac -q15m
daemon 137 1 0 Sep 23 ? 0:06 /usr/sbin/rpcbind
root 84 1 0 Sep 23 ? 0:00 /usr/lib/picl/picld
root 1601 1527 0 07:36:19 console 0:00 -sh
root 181 1 0 Sep 23 ? 0:04 /usr/lib/inet/inetd start
root 281 1 0 Sep 23 ? 0:00 /usr/lib/nfs/mountd
root 187 1 0 Sep 23 ? 0:00 /usr/sbin/cron
root 1402 1 0 00:26:14 ? 0:00 /usr/lib/ssh/sshd
daemon 289 1 0 Sep 23 ? 0:00 /usr/lib/nfs/nfsd
daemon 264 1 0 Sep 23 ? 0:00 /usr/lib/nfs/statd
root 303 1 0 Sep 23 ? 0:00 /usr/lib/fm/fmd/fmd
daemon 268 1 0 Sep 23 ? 0:00 /usr/lib/nfs/lockd
root 291 1 0 Sep 23 ? 0:00 /usr/lib/autofs/automountd
gmb 1799 1795 0 22:17:28 pts/1 0:00 ps -aef
root 1789 181 1 22:17:19 ? 0:00 /usr/sbin/in.telnetd
root 1792 1789 1 22:17:19 pts/1 0:00 login -p -h 10.1.1.100 -d /dev/pts/1
root 335 1 0 Sep 23 ? 0:06 /usr/lib/sendmail -bd -q15m
daemon 296 1 0 Sep 23 ? 0:00 /usr/lib/nfs/nfsmapid
As you can see, the gmb user can see not only his processes but also those of the
root, daemon, and smmsp accounts. We can change this behavior either
globally or on a per-user basis. Just as we discussed in the Solaris
10 Account Lockout entry, we can use user-specific changes to force a subset of users
to comply with some policy or use the user-specific changes to make exceptions for those
users. The flexibility of this format allows it to be adapted quite easily to the needs
of many organizations.
For our first example, we will illustrate how the global change can be made. So do this,
we must edit the
/etc/security/policy.conf file, uncomment the PRIV_DEFAULT entry and set its value
as follows:
PRIV_DEFAULT=basic,!proc_info
For those not familiar with the proc_info privilege, you can find more information
about it using the ppriv(1)
command:
# ppriv -l -v proc_info
proc_info
Allows a process to examine the status of processes other
than those it can send signals to. Processes which cannot
be examined cannot be seen in /proc and appear not to exist.
This is all that you need to do to globally configure your Solaris 10 system so that users
will only be able to see processes that they own. Note that this will obviously not
apply to root who by default has all privileges or to other users or processes that
have been explicitly given the proc_info privilege. Regardless, it is still a very
quick and effective way to limit what processes users may see.
Returning to the gmb account example, I re-login to the system and again
run the ps -aef command, but this time I receive different results:
$ ssh -l gmb sampleHost
gmb@sampleHost's password:
Last login: Fri Sep 24 22:25:18 2004 from 10.1.1.100
Sun Microsystems Inc. SunOS 5.10 s10_67 May 2004
$ ps -aef
UID PID PPID C STIME TTY TIME CMD
gmb 1823 1819 0 22:30:17 pts/1 0:00 ps -aef
gmb 1819 1815 0 22:30:14 pts/1 0:00 -sh
$
As you can see, the gmb user may now only see his own processes. Way cool.
Next, to illustrate the per-user configuration ability, I will leave this global
configuration in place and use the per-user configuration ability to allow the
gmb user to view processes owned by other users. This is just an example
of how exceptions can be implemented. The same process could be used to enable
this feature for just a user or subset of users on the system.
To accomplish this task, we go back to the
user_attr(4) file. In this file, we will modify the existing entry for the
gmb user (or create one if one had not already been there). The following
example illustrates the change that needs to be made. Specifically you need to
add the defaultpriv entry to specify the default list of privileges that
will be available to this user. By modifying this parameter, you
will change the default set of privileges available to a user (by either adding
or removing privileges as needed.) In this case, we are returning the user's
default set of privileges to basic from basic,!proc_info.
gmb::::lock_after_retries=no;defaultpriv=basic
So, let's see if this really works. In the following example, we will confirm
the configuration of the system, login to the system as the
gmb user, and run the ps -aef command to verify that the gmb user can
see processes owned by other users.
# grep "^PRIV_DEFAULT=" /etc/security/policy.conf
PRIV_DEFAULT=basic,!proc_info
# grep "^gmb:" /etc/user_attr
gmb::::lock_after_retries=no;defaultpriv=basic
# ssh -l gmb localhost
Password:
Last login: Fri Sep 24 22:37:55 2004 from 10.1.1.100
Sun Microsystems Inc. SunOS 5.10 s10_67 May 2004
$ id -a
uid=100(gmb) gid=1(other) groups=1(other)
$ ps -aef
UID PID PPID C STIME TTY TIME CMD
root 0 0 0 Sep 23 ? 0:07 sched
root 1 0 0 Sep 23 ? 0:01 /sbin/init
root 2 0 0 Sep 23 ? 0:00 pageout
root 3 0 0 Sep 23 ? 2:33 fsflush
root 393 1 0 Sep 23 ? 0:00 /usr/sbin/auditd
root 7 1 0 Sep 23 ? 0:11 /lib/svc/bin/svc.startd
root 9 1 0 Sep 23 ? 0:19 svc.configd
root 176 1 0 Sep 23 ? 0:00 /usr/sbin/syslogd
root 64 1 0 Sep 23 ? 0:00 /usr/sbin/nscd
daemon 91 1 0 Sep 23 ? 0:02 kcfd
root 170 1 0 Sep 23 ? 0:01 /usr/lib/utmpd
root 1900 1402 7 22:42:05 ? 0:02 /usr/lib/ssh/sshd
root 1527 7 0 00:53:24 console 0:00 /usr/bin/login
root 82 1 0 Sep 23 ? 0:00 /usr/lib/sysevent/syseventd
smmsp 334 1 0 Sep 23 ? 0:00 /usr/lib/sendmail -Ac -q15m
daemon 137 1 0 Sep 23 ? 0:06 /usr/sbin/rpcbind
root 84 1 0 Sep 23 ? 0:00 /usr/lib/picl/picld
root 1601 1527 0 07:36:19 console 0:00 -sh
root 181 1 0 Sep 23 ? 0:04 /usr/lib/inet/inetd start
root 281 1 0 Sep 23 ? 0:00 /usr/lib/nfs/mountd
root 187 1 0 Sep 23 ? 0:00 /usr/sbin/cron
root 1402 1 0 00:26:14 ? 0:00 /usr/lib/ssh/sshd
daemon 289 1 0 Sep 23 ? 0:00 /usr/lib/nfs/nfsd
daemon 264 1 0 Sep 23 ? 0:00 /usr/lib/nfs/statd
root 303 1 0 Sep 23 ? 0:00 /usr/lib/fm/fmd/fmd
daemon 268 1 0 Sep 23 ? 0:00 /usr/lib/nfs/lockd
root 291 1 0 Sep 23 ? 0:00 /usr/lib/autofs/automountd
gmb 1912 1908 0 22:42:12 pts/1 0:00 ps -aef
root 335 1 0 Sep 23 ? 0:06 /usr/lib/sendmail -bd -q15m
daemon 296 1 0 Sep 23 ? 0:00 /usr/lib/nfs/nfsmapid
gmb 1908 1900 0 22:42:10 pts/1 0:00 -sh
root 1899 1601 6 22:42:05 console 0:02 ssh -l gmb localhost
It worked! That was pretty easy, right? This is just one very small example of how you can
use process privileges in your daily lives. I will try to add more interesting examples of
practical uses for process privileges in the future.
Before ending, I do want to highlight
that while these examples focused on the ps(1) command - other process related commands
will also be impacted such as ptree(1), pcred(1), pmap(1), psig(1),
etc. Further, as a user running without the proc_info privilege, you will not even be
able to see other processes in the /proc directory:
$ id -a
uid=101(foo) gid=1(other) groups=1(other)
$ ppriv $$
1915: -sh
flags =
E: basic,!proc_info
I: basic,!proc_info
P: basic,!proc_info
L: all
$ ls -l /proc
total 4
dr-x--x--x 5 foo other 832 Sep 24 22:52 1915
dr-x--x--x 5 foo other 832 Sep 24 22:56 1932
I hope you enjoyed this
article and please watch this space for new discussion of Solaris 10 security features.
Take care and have a great weekend.
Technorati Tag:
OpenSolaris
Solaris
security