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:

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:

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!

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
&lt #include <priv_utils.h>
---
&gt #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.

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:

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:

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.

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.

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!

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:

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):

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:

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:

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.

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):

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:

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.

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:

About

This area of cyberspace is dedicated the goal of raising cybersecurity awareness. This blog will discuss cybersecurity risks, trends, news and best practices with a focus on improving mission assurance.