Sunday Feb 12, 2006

Sun Ray @ Home Updates

Well, another year has passed for my little Sun Ray user. In Septmeber, I talked about a few updates that we had done to our Sun Ray environment, and I wanted to mention the latest. In late January, we upgraded the operating system on our x86-based Sun Ray server to Nevada (build 32). No issues to report - gotta love the stability of these builds! We are still running SRSS 3.1 as a preview of the next version is not yet available. Certainly, once it is available, we will give is a try.

My son has been using Firefox (from Blastwave) with plugins for Java and Macromedia Flash and has been happily able to access his favorite sites, listen to sounds, play games and puzzles, etc. He is getting more web-savvy by the day and has even been learning to type using gedit for about six months. In fact, he is coming along quite well. I will have him coding in no time now. ;-)

Technorati Tag:

Saturday Feb 11, 2006

Try it for yourself: Solaris 10 Privilege Debugging

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:

Updated Solaris 10 Security TOI

While I am at it, how about an update to the Solaris 10 Technical TOI that I had posted a while back. This new version of the TOI includes support for Solaris 10 Update 1 as well as a bunch of other new additions and examples.

I would love to hear what you think about this new version. Remeber, if you would be interested in having someone from Sun come out and talk to you and your organization on this topic, please let us know. We have been giving this (or similar) Solaris 10 Security deep dive talks to customers for some time now, and there has always been a lot of great interaction, discussion and Q&A. Honestly, they are always a lot of fun.

Take care!

Glenn

Technorati Tag:

Sunday Aug 28, 2005

Sun Rays and Nevada

By way of an update, over the July break (yes, I know it is nearly September!), I completed the upgrade of my laptop to Nevada (build 18). Add to the mix, Casper's frkit, Darren's netprof, and packages from the good folks supporting Blastwave and my laptop is a force to be reckoned! Since then, Nevada has been my only desktop. It has flawless performed on both wired and wireless networks, at home, at the office and at conferences (being projected), ... you name it.

So, since everything has been going so very well, I decided to expose my family to Nevada ;-)

A few weeks ago, we completed the upgrade of our home Sun Ray environment. My family has moved off of the Ultra 10 (running a pre-release of Solaris 10) to a eMachines PC (Pentium 4) system running Nevada (build 18) and SRSS 3.1. I have to say that the transition was completely painless - the SRSS software installed on the Nevada-based x86 platform with no problem and has since been running flawlessly. Gotta love things that "just work".

Isn't technology grand!

Friday Jul 29, 2005

JASS supports Solaris 10!

Today is the big day! The Solaris Security Toolkit version 4.2 has been released. The biggest change in this new release is with its support of the Solaris 10 OS (global and local zones). You can read all about the changes in this new update in the Release Notes. With this release, you have a fully documented and supported tool for hardening the Solaris 10 OS (as well as previous releases) on both SPARC, Intel and AMD platforms!

Download and try it out today!

Technorati Tag:

Wednesday Jun 15, 2005

Solaris 10 Query Appreciation Day

Occasionally, I look through the referer logs to see how people happen to come across my little patch of cyberspace. It is often very interesting to see what people are actually searching for when they are directed to this blog. Today, I would like to give back to those who have taken the time to visit and look around this site after being directed to it by a search engine. To that end, I will list some of the search queries that were in the referer listing today along with answers to questions or pointers that people can use for more information.

So without further ado...

The first search query reference comes from our friends at Yahoo from someone looking for more information on locked accounts in Solaris.

This topic has been covered previously. There is a little more information that can be found in the Solaris 10 What's New document as well as the passwd(1) manual page as well.

The next query comes from our friends at Google from someone looking for steps on how to disable the telnet service in Solaris 10.

The answer to this is very straightforward:

# svcadm disable telnet

That is all there is to it. Keep in mind that if you do not want the telnet service at all on your system you can also simply remove the SUNWtnetd and SUNWtnetr packages using the command:

# pkgrm SUNWtnetd SUNWtnetr

Further, if you want to simply use TCP Wrappers to control access to telnet in Solaris 10, check out this entry.

Another Google query was looking for information on minimal Solaris 10 configurations. This is a great topic. In Solaris 10, a new software installation cluster called the Reduced Networking Meta Cluster is available and should be leveraged when building minimal configurations. You can read about it here. Further, for a great read check out Eric Boutilier's seven part series on building a UNIX OE platform from scratch.

Well, that's enough for today. I would like to occassionally do more entries like this where we can provide more directed feedback based on what people are actually searching for. While it may be too late in some cases for them, it may help people down the road who have similar questions or concerns.

I am off to finalize a presentation on Solaris recommended practices for the NY State Cyber Security Conference. If you will be at the conference tomorrow, please drop by and say hello!

Take care!

Technorati Tag:

Tuesday Jun 14, 2005

Privilege Enabling Set-ID Programs: Part 2

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:

Privilege Enabling Set-ID Programs

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:

  1. drops any privileges that it will never need;
  2. enables the remaining privileges exactly when it needs them;
  3. 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:

  1. the ping(1M) source code is simple and straightforward to read and understand, and
  2. 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:

Tuesday May 31, 2005

Automating security enforcement and audit with N1 SPS

I noticed over the weekend that Sun's N1 Service Provisioning System (SPS) was featured on www.sun.com. The title of the feature was Accelerate Deployment from Days to Minutes. This feature reminded me that I had been wanting to talk about a proof of concept that Dave Walker, Peter Charpentier, and I did with SPS and the Solaris Security Toolkit (aka JASS). So, I guess now is as good a time as any!

For those who may not know, the Solaris Security Toolkit is an officially supported Sun product that can be used to improve the security of Solaris systems running Solaris 2.5.1 through 9 (with support for Solaris 10 on the way). The Toolkit supports SPARC, Intel and AMD platforms as well as Trusted Solaris 8. The Toolkit also supports three modes of operation: hardening (apply), undo, and audit. Lastly, the Toolkit can be used to create a security profile (based on your own security policies and standards) that can then be (re-)applied to systems. You can even use the Toolkit to assess a system against a known profile to determine its degree of compliance.

So what does this have to do with SPS? Well, for sites with tens, hundreds or even thousands of systems, keeping them secure and validating that they are all in compliance with their expected security profiles can be a daunting process. Rather than individually securing (or validating) each system, you can use SPS to do it all for you at the click of a button!

Whether you have a single security profile or many, you can still use SPS to automatically harden your systems (at installation/provisioning time) as well as later in their lifecycle (perhaps after patch or application installation) - all from a centralized management platform. Auditing is made easy as well since you can evaluate all of your systems against the same (or different) profile almost simultaneously. You can even use the SPS command line interface for this functionality so that you can include pre- or post-process the output so that you can automatically create reports from the results. Given that the Solaris Security Toolkit supports 5 levels of verbosity, you can select the one that most fits your needs.

For example, often for large sites, you may want to select a low level of verbosity such as "level 0" which will simply report whether an entire audit run passed or failed (along with a number indicating the failure count).  For example, something like:

# ./jass-execute -a hardening.driver -V 0
hardening.driver               [FAIL] Grand Total: 6 Errors

For assessment runs that result in at least one failure, you could have SPS automatically re-run the report on that system using a higher level of verbosity to see exactly what the failures were.  For example, you could get information like this:

# env JASS_LOG_SUCCESS=0 JASS_LOG_NOTICE=0 ./jass-execute -a hardening.driver -V 2
disable-dmi                    [FAIL] Service lrc:/etc/rc3_d/S77dmi was installed.
disable-dmi                    [FAIL] Process /usr/lib/dmi/dmispd:430:root was found.
disable-dmi                    [FAIL] Process /usr/lib/dmi/dmispd:1240:root was found.
disable-dmi                    [FAIL] Process /usr/lib/dmi/dmispd:1135:root was found.
disable-dmi                    [FAIL] Process /usr/lib/dmi/snmpXdmid:433:root was found.
disable-dmi                    [FAIL] Process /usr/lib/dmi/snmpXdmid:1141:root was found.
disable-dmi                    [FAIL] Script Total: 6 Errors
hardening.driver               [FAIL] Driver Total: 6 Errors
hardening.driver               [FAIL] Grand Total: 6 Errors

This helps reduce the amount of information that an analyst would need to sift through in order to diagnose and fix problems.  In this case, the fix could be to simply ensure that the disable-dmi.fin Finish script was in the security profile of the system before running the Toolkit in hardening (apply) mode.  Further, once the fix was completed, you could use SPS to reassess the system to verify that the fix was correctly implemented (by just using the Toolkit again in audit mode).

You can even use SPS to upgrade the Toolkit software or add, remove or modify security profiles used by the Toolkit. The number of ways you can use SPS is really bounded by your imagination. In addition to the Solaris Security Toolkit, you could use SPS to automate the installation, configuration and use of other security controls like the Basic Auditing and Reporting Toolkit (BART) found in Solaris 10.

If this is a topic of interest to you, please let me know. If we get enough replies then perhaps we will do a more detailed "how-to" article describing how all of this works and could be deployed in an actual data center environment.

Technorati Tag:

Wednesday Apr 20, 2005

Enforcing a Two Man Rule Using Solaris 10 RBAC

The "two man rule" (also sometimes called the "four eyes rule") has its origins in military protocol although for quite some time it has been welcomed into the stockpile of IT security controls used by organizations around the world. The "two man rule" specifies that there must be two individuals that must act in concert in order to perform some action. Further, each individual should have comparable knowledge and skill in order to detect attempts of subversion initiated by the other. One can certainly see why this is essential for tasks such as safeguarding a country's nuclear arsenal. One would not want all of that authority to rest in the hands of one individual.

The "two man rule" is also useful for IT security. Whether you are talking about physical or logical access controls, the "two man rule" has been applied to help secure IT assets for quite some time. Whether you want to protect access to key data sets or restrict who may perform sensitive or high impact operations on a system, using the "two man rule" may be an option. That said, in many circumstances, more traditional IT security controls are likely appropriate. Using the "two man rule" is most often reserved for restricting the most sensitive IT security operations performed within an organization. Whether and where you could apply the "two man rule" to your organization will depend on your policy, architecture, processes and requirements.

Let's assume that you are interested in applying the "two man rule" on a given system. For our example, we will focus on implementing the "two man rule" on the Solaris 10 operating system. It should be noted that the same techniques apply to both Solaris 8 and 9 since all three versions of the operating system included the Solaris Role-based Access Control ("RBAC") facility. We will make use of this facility to implement the "two man rule" as described above.

The content and examples below will include references to both normal users and roles. In the Solaris OS, roles are similar to normal user accounts with two important differences. First, a role cannot be accessed directly over the network or from the console. You can only use the su(1M) command (or smc(1M)) to assume a role. In either case, a user must first authenticate to the system as himself before attempting to access a role. Secondly, a role can only be assumed by authorized users. That is, before a given user can assume a role, an administrator must assign that role to the user otherwise attempts to access the role will fail. Both of these restrictions are important for preserving accountability and will factor quite heavily in our implementation of the two man rule in Solaris 10.

So let's begin. For our example, we will implement the "two man rule" for our hypothetical IT security administrators, joe and john. From here, there are several ways that we can go:

  • Configure both joe and john with normal accounts on the system, each able to assume an individual Solaris role. Neither joe nor john will know the password for the role that they are permitted to assume. For example, joe is permitted to assume the role roleA but is unable to do so since only john knows the password for that role. This option creates two roles (one for each user) each able to perform a restricted operation. This approach has the benefit of either user being able to assume the role (i.e., it does not require that one user be the initiator of the action). Further by permitting both users to be on the system they have more opportunity to monitor the actions of the other (e.g., Solaris auditing, syslog, etc.).

  • Configure only one user on the system with permission to assume one role. In this example, one user would know the initial password while the other user would know the second (i.e., role) password. This case is similar to the first although it only requires one user and one role account on the system. It suffers from the disadvantage of not permitting the second user to log directly into the system thereby potentially missing critical monitoring opportunities. Further, it requires that joe must be first logged into the system before john can assume roleA.

  • Configure both joe and john as in example one but only give them access to the same shared role. In this case, neither user would have the password to authenticate to that role. In order to obtain the authenticator for that role, both users would be required to work together to obtain the password from an external source such as a physical safe. This option has the benefit of greater protection since access to the safe could be placed in an area that requires additional physical controls and provides greater opportunities for monitoring. Further, the authenticator could be monitored and changed by a third party who has no relationship to either joe or john. This approach also preserves the benefits of the first approach where both joe and john can easily monitor the activities of the other.

For our example, I will choose the first option. This option will allow me to showcase the capabilities of Solaris RBAC to implement the "two man rule" without depending on external factors such as those described in the third option above. The actual choice that you make will depend on your policy and requirements. Additional security controls (physical and logical) beyond those described in this article may also be required depending on the level of assurance that you need for your situation.

First, let's verify our users - joe and john:

# getent passwd joe john
joe:x:105:1::/export/home/joe:/bin/pfsh
john:x:106:1::/export/home/john:/bin/pfsh

You will note that these users have been configured with profile shells. This is only done to simplify some of the commands that follow. If you did want want to use a profile shell, you could prefix your commands with pfexec(1) when you wanted them to be evaluated by Solaris RBAC to run with privilege.

We can verify that these account do not have any special privileges (beyond those available to any regular Solaris user) by running the following commands:

# roles joe john
joe : No roles
john : No roles

# profiles -l joe john

      All:
          \*

      All:
          \*

# auths joe john
joe : solaris.device.cdrw,solaris.profmgr.read,solaris.jobs.users,solaris.mail.mailq,solaris.admin.usermgr.read,
solaris.admin.logsvc.read,solaris.admin.fsmgr.read,solaris.admin.serialmgr.read,solaris.admin.diskmgr.read,
solaris.admin.procmgr.user,solaris.compsys.read,solaris.admin.printer.read,solaris.admin.prodreg.read,
solaris.admin.dcmgr.read,solaris.snmp.read,solaris.project.read,solaris.admin.patchmgr.read,
solaris.network.hosts.read,solaris.admin.volmgr.read
john : solaris.device.cdrw,solaris.profmgr.read,solaris.jobs.users,solaris.mail.mailq,solaris.admin.usermgr.read,
solaris.admin.logsvc.read,solaris.admin.fsmgr.read,solaris.admin.serialmgr.read,solaris.admin.diskmgr.read,
solaris.admin.procmgr.user,solaris.compsys.read,solaris.admin.printer.read,solaris.admin.prodreg.read,
solaris.admin.dcmgr.read,solaris.snmp.read,solaris.project.read,solaris.admin.patchmgr.read,
solaris.network.hosts.read,solaris.admin.volmgr.read

As you can see, neither joe nor john have been granted access to any roles, rights profiles or authorizations (beyond those available to any normal Solaris user). You will notice several authorizations that are available to them. They have been granted by default using the AUTHS_GRANTED and PROFS_GRANTED parameters in the /etc/security/policy.conf file.

To each of these users we will grant the rights profile Audit Review. This will allow both joe and john to review Solaris audit records so that each can monitor the activities of the other. This step is not necessary for the "two man rule" if you have an external third party who is able to monitor the activities of the two users.

# usermod -P "Audit Review" joe
# usermod -P "Audit Review" john

Let's verify that this change has taken effect:

# profiles -l joe john

      Audit Review:
          /usr/sbin/praudit    euid=0
          /usr/sbin/auditreduce    euid=0
          /usr/sbin/auditstat    euid=0
      All:
          \*

      Audit Review:
          /usr/sbin/praudit    euid=0
          /usr/sbin/auditreduce    euid=0
          /usr/sbin/auditstat    euid=0
      All:
          \*

Now that we have verified the accounts have been configured as expected, we will create two roles: roleA and roleB. roleA will be assigned to joe, and roleB will be assigned to john. To these roles, our restricted operations will be assigned.

# roleadd -d /export/home/roleA -m roleA
64 blocks

# passwd roleA
New Password:
Re-enter new Password:
passwd: password successfully changed for roleA

# roleadd -d /export/home/roleB -m roleB
64 blocks

# passwd roleB
New Password:
Re-enter new Password:
passwd: password successfully changed for roleB

# usermod -R roleA joe
# usermod -R roleB john
Now, let's verify that the roles have been created and assigned as we expected:

# getent passwd roleA roleB
roleA:x:107:1::/export/home/roleA:/bin/pfsh
roleB:x:108:1::/export/home/roleB:/bin/pfsh

# roles joe john
joe : roleA
john : roleB

Great. Our last step is to assign the restricted operations to the roles so that joe and john can perform them after they have jointly assumed either roleA or roleB. For our example, we will assign the Crypto Management rights profile to both roleA and roleB. This will allow either of those roles to execute cryptographic administration functions such as those provided by cryptoadm(1M):

# rolemod -P "Crypto Management" roleA
# rolemod -P "Crypto Management" roleB

To see what privileged commands are now available to these roles, use the following command:

# profiles -l roleA roleB

      Crypto Management:
          /usr/sbin/cryptoadm    euid=0
          /usr/sfw/bin/CA.pl    euid=0
          /usr/sfw/bin/openssl    euid=0
      All:
          \*

      Crypto Management:
          /usr/sbin/cryptoadm    euid=0
          /usr/sfw/bin/CA.pl    euid=0
          /usr/sfw/bin/openssl    euid=0
      All:
          \*

Great! We are all set. At this point, we have two users (joe and john). joe is permitted to assume roleA, and john is permitted to assume roleB. joe does not know the password for roleA (although john does), and similarly john does not know the password for roleB (although joe does). Both of the users have been assigned the Audit Review rights profile allowing them to monitor each other's activities. Both of the roles have been assigned the Crypto Management rights profile allowing them to perform cryptographic management operations on the system.

Let's verify that this all actually works... For my example, all of the users and roles were created within a zone called "blue". The first thing that I will do to test is log into the zone as joe:

# zlogin -l joe blue
[Connected to zone 'blue' pts/2]
Last login: Tue Apr 12 07:20:19 on pts/2
joe$ id -a
uid=105(joe) gid=1(other) groups=1(other)
joe$ auths
solaris.audit.read,solaris.device.cdrw,solaris.profmgr.read,solaris.jobs.users,solaris.mail.mailq,
solaris.admin.usermgr.read,solaris.admin.logsvc.read,solaris.admin.fsmgr.read,solaris.admin.serialmgr.read,
solaris.admin.diskmgr.read,solaris.admin.procmgr.user,solaris.compsys.read,solaris.admin.printer.read,
solaris.admin.prodreg.read,solaris.admin.dcmgr.read,solaris.snmp.read,solaris.project.read,
solaris.admin.patchmgr.read,solaris.network.hosts.read,solaris.admin.volmgr.read
joe$ profiles -l

      Audit Review:
          /usr/sbin/praudit    euid=0
          /usr/sbin/auditreduce    euid=0
          /usr/sbin/auditstat    euid=0
      All:
          \*
joe$ roles
roleA

First, since joe does know the password for roleB, let's see if we can assume that role:

joe$ su roleB
Password:
Roles can only be assumed by authorized users
su: Sorry

Even with a valid password, joe is not permitted to assume roleB. Next, let's try to guess the password for roleA:

joe$ su roleA
Password:
su: Sorry
joe$ su roleA
Password:
su: Sorry
joe$ su roleA
Password:
su: Sorry

No luck. In order to prevent brute force password attempts, you could also configure account lockout so that an account will be administratively locked after n consecutive failed authentication attempts, where n is the value defined by the RETRIES parameter in /etc/default/login.

Next, let's see what user john would see in the audit trails after joe executed the above commands. Since john has been granted the Audit Review rights profile, he is able to look at the Solaris audit records. If you wanted to further limit what john could see in the audit trail, you could develop a small wrapper script to call praudit(1M) and auditreduce(1M) to filter out unwanted records. So, let's pick up our example with john logging into the "blue" zone:

# zlogin -l john blue
[Connected to zone 'blue' pts/2]
john$ id -a
uid=106(john) gid=1(other) groups=1(other)
john$ auths
solaris.audit.read,solaris.device.cdrw,solaris.profmgr.read,solaris.jobs.users,solaris.mail.mailq,
solaris.admin.usermgr.read,solaris.admin.logsvc.read,solaris.admin.fsmgr.read,solaris.admin.serialmgr.read,
solaris.admin.diskmgr.read,solaris.admin.procmgr.user,solaris.compsys.read,solaris.admin.printer.read,
solaris.admin.prodreg.read,solaris.admin.dcmgr.read,solaris.snmp.read,solaris.project.read,
solaris.admin.patchmgr.read,solaris.network.hosts.read,solaris.admin.volmgr.read
john$ profiles -l

      Audit Review:
          /usr/sbin/praudit    euid=0
          /usr/sbin/auditreduce    euid=0
          /usr/sbin/auditstat    euid=0
      All:
          \*
john$ roles
roleB

Next, john uses the praudit and auditreduce commands to look at any attmepts to su taken by joe:

john$ auditreduce -m AUE_su -r joe | praudit -s
file,2005-04-12 07:25:06.000 -04:00,
header,97,2,AUE_su,,10.8.31.9,2005-04-12 07:28:30.220 -04:00
subject,gmb,root,other,joe,other,1834,3097759606,12114 22 129.150.66.247
text,bad auth. for user roleB
return,failure,2
header,97,2,AUE_su,,10.8.31.9,2005-04-12 07:28:40.043 -04:00
subject,gmb,root,other,joe,other,1835,3097759606,12114 22 129.150.66.247
text,bad auth. for user roleA
return,failure,2
header,97,2,AUE_su,,10.8.31.9,2005-04-12 07:28:49.940 -04:00
subject,gmb,root,other,joe,other,1836,3097759606,12114 22 129.150.66.247
text,bad auth. for user roleA
return,failure,2
header,97,2,AUE_su,,10.8.31.9,2005-04-12 07:28:59.683 -04:00
subject,gmb,root,other,joe,other,1837,3097759606,12114 22 129.150.66.247
text,bad auth. for user roleA
return,failure,2
file,2005-04-12 07:28:59.000 -04:00,

From this audit trail, you can see that user joe attempted to assume both roleA and roleB. In fact, joe attempted to assume roleB three times with each attempt ending in failure. For more information on the audit logs, their format and options for configuring them, see auditd(1M). For the purposes of this example, Solaris auditing was configured with the following policies:

# auditconfig -getpolicy
audit policies = argv,cnt,perzone

Further, the users and roles defined in this example were audited as follows:

# cat /etc/security/audit_user
#
# Copyright (c) 1988 by Sun Microsystems, Inc.
#
# ident "@(#)audit_user.txt     1.6     00/07/17 SMI"
#
#
# User Level Audit User File
#
# File Format
#
#       username:always:never
#
root:lo:no
joe:lo,ad,ex:
john:lo,ad,ex:
roleA:lo,ad,ex:
roleB:lo,ad,ex:

These settings effectively audited login and logout events, administrative actions and command execution (exec(2) calls). You should configure Solaris auditing to comply with your local auditing requirements and policies. The configuration presented serves only as an example to illustrate the type of information that can be collected.

By now, you can see that joe cannot access the Cryto Management rights profile on his own. Let's see what would happen if joe attempted to simply perform a restricted cryptographic operation on his own:

joe$ cryptoadm stop
cryptoadm: failed to stop cryptographic framework daemon - Not owner.

Still no luck. In order to perform those restricted operations, he will need john to help him assume roleA. In the final example below, we illustrate that working in concert, joe and john together can successfully assume roleA.

joe$ su roleA
Password:
roleA$ id -a
uid=107(roleA) gid=1(other) groups=1(other)
roleA$ profiles -l

      Crypto Management:
          /usr/sbin/cryptoadm    euid=0
          /usr/sfw/bin/CA.pl    euid=0
          /usr/sfw/bin/openssl    euid=0
      All:
          \*

With these privileges, joe and john can perform operations such as starting and stopping the Solaris cryptographic framework:

roleA$ echo "foo" | digest -a md5
d3b07384d113edec49eaa6238ad5ff00
roleA$ cryptoadm stop
roleA$ echo "foo" | digest -a md5
digest: failed to initialize PKCS #11 framework: CKR_GENERAL_ERROR
roleA$ cryptoadm start
roleA$ echo "foo" | digest -a md5
d3b07384d113edec49eaa6238ad5ff00

Clearly, you can see that the "two man rule" is enforced since neither joe nor john can perform any cryptographic management operations on the system without knowledge and support of the other. Further, should either user attempt to access their assigned role, the other user can be alerted through the presence of a Solaris audit record (that neither user can modify). Very cool.

Finally, I would like to thank both Collin Sampson and Scott Rotondo for their careful review and feedback provided on this article.

As always, I am interested in your feedback and thoughts. Please let me know if you have any questions. Take care!

Technorati Tag:

Friday Apr 15, 2005

CIS Solaris 10 Security Benchmark Published

It is with great pleasure that I can announce the public availability of the Solaris 10 Security Benchmark published by the Center for Internet Security.

For those who are not aware, for more than two years, Sun has been working quite closely with CIS to refine the Solaris Benchmark and to better align that document with Sun's BluePrints and tools. Frankly, both parties have benefited from this collaboration and has led to the addition or tuning of many recommendations and the filing of several RFEs that will in turn improve the overall quality and security of Solaris. It is great to see and be a part of such a collaborative effort, and this release marks the greatest level of Sun participation yet!

So - congratulations to CIS and the Unix Benchmark team on a job well done.

Technorati Tag:

Friday Apr 08, 2005

New Sun BluePrints Security Cookbook

As I alluded to in a previous article, another one of my blog articles was recently reworked and published as a Sun BluePrints Cookbook. Integrating BART and the Solaris Fingerprint Database in the Solaris 10 Operating System was published this month. This article does feature quite a bit of cleanup and some new content in addition to what you may have already seen. This will be my last BART article for a little bit as I have turned by focus on the Service Management Framework. Look for some new Sun BluePrints Security Cookbooks focusing on SMF in the next few months!

As always, I am very interested in any feedback that you may have...

Take care!

Technorati Tag:

Wednesday Apr 06, 2005

Enabling TCP Wrappers on Solaris 10

Tip of the Month: Enabling TCP Wrappers in Solaris 10

Before answering this question, let's first provide a little background. TCP Wrappers has been around for many, many years. It is used to restrict access to TCP services based on host name, IP address, network address, etc. For more detailed on what TCP Wrappers is and how you can use it, see tcpd(1M). TCP Wrappers was integrated into Solaris starting in Solaris 9 where both Solaris Secure Shell and inetd-based (streams, nowait) services were wrapped. Bonus points are awarded to anyone who knows why UDP services are not wrapped by default.

TCP Wrappers support in Secure Shell was always enabled since Secure Shell always called the TCP Wrapper function host_access(3) to determine if a connection attempt should proceed. If TCP Wrappers was not configured on that system, access, by default, would be granted. Otherwise, the rules as defined in the hosts.allow and hosts.deny files would apply. For more information on these files, see hosts_access(4). Note that this and all of the TCP Wrappers manual pages a stored under /usr/sfw/man in Solaris 10. To view this manual page, you can use the following command:

$ man -M /usr/sfw/man -s 4 hosts_access

inetd-based services use TCP Wrappers in a different way. In Solaris 9, to enable TCP Wrappers for inetd-based services, you must edit the /etc/default/inetd file and set the ENABLE_TCPWRAPPERSparameter to YES. By default, TCP Wrappers was not enabled for inetd.

In Solaris 10, two new services were wrapped: sendmail and rpcbind. sendmail works in a way similar to Secure Shell. It always calls the host_access function and therefore TCP Wrappers support is always enabled. Nothing else needs to be done to enable TCP Wrappers support for that service. On the other hand, TCP Wrappers support for rpcbind must be enabled manually using the new Service Management Framework ("SMF"). Similarly, inetd was modified to use a SMF property to control whether TCP Wrappers is enabled for inetd-based services.

Let's look at how to enable TCP Wrappers for inetd and rpcbind...

To enable TCP Wrappers support for inetd-based services, you can simply use the following commands:

# inetadm -M tcp_wrappers=true
# svcadm refresh inetd

This will enable TCP Wrappers for inetd-based (streams, nowait) services like telnet, rlogin, and ftp (for example):

# inetadm -l telnet | grep tcp_wrappers
default  tcp_wrappers=TRUE

You can see that this setting has taken effect for inetd by running the following command:

# svcprop -p defaults inetd
defaults/tcp_wrappers boolean true

Note that you can also use the svccfg(1M) command to enable TCP Wrappers for inetd-based services.

# svccfg -s inetd setprop defaults/tcp_wrappers=true
# svcadm refresh inetd

Whether you use inetadm(1M) or svccfg is really a matter of preference. Note that you can also use inetadm or svccfg to enable TCP Wrappers on a per-service basis. For example, let's say that we wanted to enable TCP Wrappers for telnet but not for ftp. By default, both the global and per-service settings for TCP Wrappers are disabled:

# inetadm -p | grep tcp_wrappers
tcp_wrappers=FALSE

# inetadm -l telnet | grep tcp_wrappers
default  tcp_wrappers=FALSE

# inetadm -l ftp | grep tcp_wrappers
default  tcp_wrappers=FALSE

To enable TCP Wrappers for telnet, use the following command:

# inetadm -m telnet tcp_wrappers=TRUE

Let's check out settings again:

# inetadm -p | grep tcp_wrappers
tcp_wrappers=FALSE

# inetadm -l telnet | grep tcp_wrappers
         tcp_wrappers=TRUE

# inetadm -l ftp | grep tcp_wrappers
default  tcp_wrappers=FALSE

As you can see, TCP Wrappers has been enabled for telnet but none of the other inetd-based services. Pretty cool, eh?

You can enable TCP Wrappers support for rpcbind by running the following command:

# svccfg -s rpc/bind setprop config/enable_tcpwrappers=true
# svcadm refresh rpc/bind

This change can be verified by running:

# svcprop -p config/enable_tcpwrappers rpc/bind
true

That is all that there is to it! Quick, easy and painless! As always, let me know what you think!

Take care!

Technorati Tag:

Solaris 10 Security Technical TOI

In a recent posting, I talked about a presentation that I gave on Solaris 10 at a set of "boot camps" in Somerset, NJ and New York City. The presentation was a deep dive into Solaris 10 security that talked about a variety of capabilities in depth and covered many other features and enhancements that you may not have heard about. The version of this talk that I gave at the boot camp has been posted if you are interested. I would love to hear what you think.

If you would be interested in having Sun come out and deliver this presentations to your and your organizations, please let us know. We have been giving this (or similar) Solaris 10 Security deep dive talks to customers for some time now, and there has always been a lot of great interaction, discussion and Q&A focused on how this great technology can be applied to solve problems facing their organizations.

Take care!

Technorati Tag:

Friday Jan 21, 2005

World's Youngest Sun Ray on Solaris 10 User

As I talked about previously, my son received a Sun Ray 150 for his birthday this year. He took to it like a fish to water and was easily navigating several of his favorite sites. He had a lot of fun playing games and even brought some of his friends over to his "office" and showed them how to use it.

For those who may be interested, the Sun Ray 150 is connected to an Ultra 10 workstation (440Mhz, 1-Gbyte RAM, 9-Gbyte disk) running Solaris 10 (build 74) and the Sun Ray Server Software 3.0.

I had the Sun Ray configured in its normal and controlled access (kiosk) modes to see which would be more managable. In its normal mode, we used the Java Desktop System interface. Each mode has its benefits for a home system, and I have not quite decided which way it will end up. It does not appear to matter, however, for my son who simply enjoys surfing the web with Mozilla and playing Java and Macromedia Flash games.

Now if I could just get him to file bugs and RFEs! Maybe next year...

About

gbrunett

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today