Lab: Protecting Your Applications with Oracle Solaris 11 Security

Hands-On Labs Of the System Admin and Developer Community of OTN

In this lab we we take quick tour of some of Oracle Solaris security features that can help you to protect your applications and your system. We will look at the following technologies:

  • Privileges
  • RBAC (Rights and Authorizations)
  • Integration with SMF (Service Management Facility)

Prerequisites

Software Needed

For lab exercises 3 and 4, apache 2.2 is required.

To install apache 2.2 on Solaris 11;

  • Click on the "Add More Software" icon on the desktop

Add More Software

  • When prompted, supply the root password (that one you set up while booted Oracle Solaris 11 for the first time upon importing the appliance):

Password Required

  • Search for apache-22.
  • Select "web/server/apache-22"

Package Manager

  • Click on Install/Update and install the Apache web server.

Lab Exercises

  1. Introduction to Solaris RBAC and Privileges.
  2. A closer look at Solaris Privileges.
  3. Process privileges and rights.
  4. SMF, process privileges and authorizations.

Exercise 1: Introduction to Solaris RBAC and Privileges

Expected duration: 20 minutes

The goal of this exercise is to gain a basic understanding of the RBAC/privileges framework in Solaris.

Background Information

Thanks Joerg Moellenkamp and his post on Less known Solaris features: RBAC and Privileges - Part 1: Introduction for the following introduction.

The Story of root

And then there was root. And root was almighty. And that wasn't a good thing. root was able to control the world without any control. And root needed control. It was only a short chant between the mere mortals and root. Everybody with the knowledge of the magic chant was able to speak through root.

But root wasn't alone. root had servants called daemons. Some of one them needed divine powers to do their daily job. But root was an undividable being. So the servants had to work with the powers of root. But the servants were not as perfect as root: Some of the servants started to do everything mere mortals said to them if they only said more than a certain amount of prayers at once.

Superuser

The old model of rights in a Unix systems is based on a duality. There is the superuser and the normal user. The normal users have a restricted set of rights in the system, the superuser has an unrestricted set of rights. To modify the system, a normal user has to login as root directly or assume the rights of root (by su -). But such a user has unrestricted access to the system. Often this isn't desirable. Why should you enable an operator to modify a system, when all he or she has do to on the system is create some users from time to time. You've trained them to do useradd or passwd. What do you do when they get too curious? They need root privileges to create a user or change a password. You need some mechanisms to limit this operator.

But it gets more problematic. Programs have to modify the system to work. A web server is a good example. You expect it to use port 80, ports beneath port number 1024 are privileged ports. You need special rights to modify the structures of the system to listen to port 80. A normal user doesn't have these rights. So the web server has to be started as root. The children of this process drop the rights of root by running with a normal user. But there is this single instance of the program with all the rights of the user. This process has much more rights than needed, a possible attack vector for malicious users.

Least Privilege

There is a concept in security known as least privilege. You give someone only least amount of privileges, only enough to do the tasks they are assigned. An example of the real world - you won't give the janitor the master key for all the rooms on the campus, when all he has to do is work in Building C. The other way around - there are some trusted people who have access to all rooms in case of an emergency.

You have the same concept in computer security. Everyone should have only the least amount of privileges in the system to do their job. The concept of the superuser doesn't match to this, it's an all or nothing model. You are an ordinary user with basic privileges or you are a user with unrestricted rights. There is nothing in between. This doesn't follow the least privileges model.

Role Based Access Control (RBAC)

The example with the key for the janitors is a good example. Let's imagine a large campus. You have janitors responsible for the plumbing (let's call them Lenny and Carl), for the park (let's call him Homer), for the security system (let's call her Marge and Lenny helps from time to time).

These roles have different sets of privileges: For example the plumbing janitors have access to all the rooms of the heating system. The janitor for the park has only access to the garage with the lawnmower.

When they start to work in their job, they assume a role. From the privilege perspective it's not important who is the person, but what role the person has assumed. Lenny punches the clock and assumes the role of the plumbing janitor for the next 8 hours. And while he is doing its job he uses the privileges inherent to the role. But he also has to do tasks in his office or in his workshop. It's his own room, so he doesn't need the special privileges.

Role Based Access Control is quite similar. You login to the system, and then you start to work. You read your emails (no special privileges needed), you find an email "Create user xy45345. Your Boss". Okay, now you need special privileges. You assume the role of a User Administrator and create the user. Job done, you don´t need the privileges anymore. You leave the role and write the "Job done" mail to your boss with your normal user's privileges.

Role Based Access Control is all about this: Defining roles, giving them privileges and assigning users to this roles.

Privileges

I've used the word quite often in this introduction so far. What is a privilege? A privilege is the right to do something. For example, having the keys for the control panel of the heating system.

Unix users are nothing different. Every user has privileges in a Unix system. A normal user has the privilege to open, close, read, write and delete files when he is allowed to do this (Because he created it, because he belongs to the same group as the creater of the file or the creator gave everybody the right to do it). This looks normal to you, but it's privilege based on the login credentials you gave to system. You don't have the privilege to read all files on the system or to use a port number 1024.

Every thing done in the system is based on these privileges. Solaris has separated the tasks into many privilege sets. At the moment, there are 70 different privileges in the system. The difference between the normal user is that the users have only a basic set, while root has all.

In Solaris the model has changed, privileges and users aren't connected with each other. You can give any user the power of the traditional “root user”, and restrict the privileges of the root user. Solaris is configured to look as a traditional super user model due to our binary compatibility guarantee that mandates that the standard configuration of the system resembles the superuser model. There are application out there, which assume that only the root user or the UID 0 as unrestricted rights and exit when they are started with a different user.

The only thing that is special with UID 0 in Solaris is that it's the owner of the system configuration files, and thus has the capability to change system configurations.

RBAC and Privileges in Solaris

Both features have their root in the Trusted Solaris product. Trusted Solaris was a version of Solaris to ensure the highest security standards. Today, these mechanisms are part of the normal Solaris in conjunction with the Trusted Extensions. So RBAC is a really old feature - it has been in Solaris since Solaris 8 (published in 2000). Privileges found their way into the generic Solaris with the first availability of Solaris 10 in February 2005.

Lets start with some basic concepts for RBAC:

  • Rights: A right is the permission, to execute an executable as an privileged user. For example the permission to execute the command reboot as root.
  • Authorization: A permission that enables a user or role to perform a class of actions that could affect security. For example, security policy at installation gives ordinary users the solaris.device.cdrw authorization. This authorization enables users to read and write to a CD-ROM device.
  • Right Profiles: A collection of administrative capabilities that can be assigned to a role or to a user. A rights profile can consist of authorizations, of commands with security attributes, and of other rights profiles. Rights profiles offer a convenient way to group security attributes.
  • Role: A special identity for running privileged applications. The special identity can be assumed by assigned users only. In a system that is run by roles, superuser is unnecessary. Superuser capabilities are distributed to different roles.

Lets take a closer look at RBAC and roles:

Open a terminal window by right clicking any point in the background of the desktop, and select Open +T+erminal in the pop-up menu.

Solaris 11 Menu

Lets look at what roles are assigned to our Oracle user. In a terminal, do as follows:



oracle@solaris:~$ roles
root

As you can see here you should be assigned the role root, it allows us to assume the root role. In Solaris 11 root is not a user but rather a role. So you have to login to the system as a normal user and then assume the root role with the su command.

In a terminal window type as follows:



oracle@solaris:~$ userattr type root
role

oracle@solaris:~$ auths root
solaris.*

As you can see here root is defined as a role with all solaris authorizations, the effect of this is similar to the old almighty root user. This is put in place for backwards compatibility.

And as your user is assigned the root role, you can try this by assuming the root role:



oracle@solaris:~$ whoami
oracle
oracle@solaris:~$ su
Password: <root password>
oracle@solaris:~# whoami
root
oracle@solaris:~# who am I
oracle   pts/1        Apr 21 07:32  (:0.0)
oracle@solaris:~# exit
exit
oracle@solaris:~$

Lets add a new user, Joe Doe to our system:



oracle@solaris:~$ useradd -d /export/home/jdoe -m -s /bin/ksh -c "Joe Doe" jdoe
UX: useradd: ERROR: Permission denied.

As you can see here we are not allowed to use the useradd command. We will have to use su to execute useradd with "root" privileges, and assign missing rights to our account. The su command will prompt you for the root password.



oracle@solaris:~$ su root -c "usermod -K profiles='User Management' oracle"
Password: <your root password>

oracle@solaris:~$ userattr profiles oracle
User Management

As you can see, we now have the right to manage users. To take advantage of this right, we will invoke a profile shell, e.g. pfbash, and create the new user, jdoe.



oracle@solaris:~$ pfbash
oracle@solaris:~$ useradd -d /export/home/jdoe -g oinstall -m -s /bin/ksh -c "Joe Doe" jdoe

To change the user's password we have to have User Security profile assigned, but it is not advised to assign it to a regular user because it allows the user to change passwords of other users, including more powerful ones. User Management profile is safe, because you can only delegate what you already have. Therefore, let's change the password of the new user using root role:



oracle@solaris:~$ su root -c passwd jdoe
Password: <root password>
New Password: abc123
Re-enter new Password: abc123
passwd: password successfully changed for jdoe
oracle@solaris:~$ su - jdoe
Password: abc123
Oracle Corporation    SunOS 5.11    11.0    November 2011
jdoe@solaris:/export/home/jdoe$ roles
No roles
jdoe@solaris:/export/home/jdoe$ su root
Password: <root password>
Roles can only be assumed by authorized users
su: Sorry
jdoe@solaris:/export/home/jdoe$ exit
oracle@solaris:~$

Note: -g oinstall option is submitted to the useradd command. It is necessary to add it because oracle user is in oinstall group by default in this lab setup. Default group in Oracle Solaris 11 is staff. Therefore, if you do not explicitly require to add the user to oinstall group with -g oinstall, useradd will try to add the new user to staff group. You are not allowed to do it as user oracle, because a user with "User Management" profile is allowed to add a new user just to a group which he/she already belongs to.

NEW in Role Authentication in Solaris 11

Role Authentication procedure has changed in Solaris 11. Running earlier Solaris version, including Oracle Solaris 11 Express, user had to know role password in order to assume the role. Oracle Solaris 11 includes the ability to specify whether to use the role password or user password when a user wants to assume a given role.   Administrators can specify either 'user' or 'role' for the 'roleauth' keyword. If roleauth is not specified, 'role' is implied. Any newly created roles will be 'user' by default.

Summary

As you can see here jdoe doesn't have any roles assigned to him and he can't use su to assume the root role. We'll get back to him later. Now let's move on to a closer look at privileges in Exercise 2.

Exercise 2: A Closer Look at Solaris Privileges

Expected duration: 20 minutes

Introduction

The goal of this exercise is to understand Solaris privileges and how to use them

Background Information

Privileges

What are Privileges? Privileges are rights to do an operation in the kernel. These rights are enforced by the kernel. Whenever you do something within the kernel the access is controlled by privileges.

List of privileges

contract_event, contract_identity, contract_observer, cpc_cpu, dtrace_kernel, dtrace_proc, dtrace_user, file_chown, file_chown_self, file_dac_execute, file_dac_read, file_dac_search, file_dac_write, file_downgrade_sl, file_flag_set, file_link_any, file_owner, file_setid, file_upgrade_sl, graphics_access, graphics_map, ipc_dac_read, ipc_dac_write, ipc_owner, net_access, net_bindmlp, net_icmpaccess, net_mac_aware, net_mac_implicit, net_observability, net_privaddr, net_rawaccess, proc_audit, proc_chroot, proc_clock_highres, proc_exec, proc_fork, proc_info, proc_lock_memory, proc_owner, proc_priocntl, proc_session, proc_setid, proc_taskid, proc_zone, sys_acct, sys_admin, sys_audit, sys_config, sys_devices, sys_ipc_config, sys_linkdir, sys_mount, sys_iptun_config, sys_dl_config, sys_ip_config, sys_net_config, sys_nfs, sys_ppp_config, sys_res_config, sys_resource, sys_smb, sys_suser_compat, sys_time, sys_trans_label, virt_manage, win_colormap, win_config, win_dac_read, win_dac_write, win_devices, win_dga, win_downgrade_sl, win_fontpath, win_mac_read, win_mac_write, win_selection, win_upgrade_sl, xvm_control

Legend: blue - basic privilege

Conventional Unix

On conventional Unix systems you have a root user and they have all privileges. And you have a normal user, who has only a limited set of privileges. Sometimes you need the rights of an admin to do some tasks. You don´t even need to administer the system.



oracle@solaris:~$ ls -l /usr/sbin/traceroute
-r-sr-xr-x 1 root bin 46868 2010-11-05 08:02 /usr/sbin/traceroute
oracle@solaris:~$ ls -l /usr/sbin/ping
-r-sr-xr-x 1 root bin 55940 2010-11-05 08:01 /usr/sbin/ping

You can use traceroute and ping because both tools are setuid tools. setuid allows a process to run with a specific userid and all the privileges that comes with that user. In the case of setuid to root the process would have root's privileges. A setuid program in Solaris can be privilege-aware and hence only retain the privileges needed for the operation.

You need a special privilege to ping - the privilege to use access ICMP. On conventional systems this right is reserved for the root user. Thus the ping program has to be executed with the rights of root. The problem: At the time of the execution of the program, the program has all the rights of the user. Not only to access ICMP, but the program is capable of doing everything on the system, such as deleting files in /etc. This may not a problem with ping or traceroute but think about larger programs. An exploit in a setuid program can lead to the escalation of the user's privileges.

Let's have a look at the privileges of an ordinary user. There is a tool to get the privileges of any given process in the system, it's called ppriv. $$ is a shortcut for the actual process id (in this case the process id of the shell):



oracle@solaris:~$ ppriv $$
1684:    -bash
flags = <none>
    E: basic
    I: basic
    P: basic
    L: all

What does "basic" mean, we can add -v to the ppriv flag to expand the aliases:



oracle@solaris:~$ ppriv -v $$
1684:    -bash
flags = <none>
    E: file_link_any,file_read,file_write,net_access,proc_exec,proc_fork,proc_info,proc_session
    I: file_link_any,file_read,file_write,net_access,proc_exec,proc_fork,proc_info,proc_session
    P: file_link_any,file_read,file_write,net_access,proc_exec,proc_fork,proc_info,proc_session
    L: contract_event,contract_identity,contract_observer,cpc_cpu,dtrace_kernel,dtrace_proc,dtrace_user,file_chown,
    file_chown_self,file_dac_execute,file_dac_read,file_dac_search,file_dac_write,file_downgrade_sl,file_flag_set,
    file_link_any,file_owner,file_read,file_setid,file_upgrade_sl,file_write,graphics_access,graphics_map,ipc_dac_read,
    ipc_dac_write,ipc_owner,net_access,net_bindmlp,net_icmpaccess,net_mac_aware,net_mac_implicit,net_observability,
    net_privaddr,net_rawaccess,proc_audit,proc_chroot,proc_clock_highres,proc_exec,proc_fork,proc_info,proc_lock_memory,
    proc_owner,proc_priocntl,proc_session,proc_setid,proc_taskid,proc_zone,sys_acct,sys_admin,sys_audit,sys_config,
    sys_devices,sys_dl_config,sys_ip_config,sys_ipc_config,sys_iptun_config,sys_linkdir,sys_mount,sys_net_config,sys_nfs,
    sys_ppp_config,sys_res_bind,sys_res_config,sys_resource,sys_smb,sys_suser_compat,sys_time,sys_trans_label,
    virt_manage,win_colormap,win_config,win_dac_read,win_dac_write,win_devices,win_dga,win_downgrade_sl,win_fontpath,
    win_mac_read,win_mac_write,win_selection,win_upgrade_sl,xvm_control

Every process in the system has four sets of privileges that determine if a process is enabled to use a privilege or not. The theory of privileges is quite complex. I would suggest to read the chapter How Privileges Are Implemented" in the Developers Guide to Oracle Solaris Security to learn how each set controls or is controlled other privilege sets.

At this time, I want only to explain the meaning of the first letter:

  • E: Effective privileges set
  • I: Inheritable privileges set
  • P: Permitted privileges set
  • L: Limit privileges set

You can think about the privilege sets as keyrings. The effective privilege set are the keys the janitor has on its keyring. The permitted privilege set are the keys the janitor is allowed to put on its keyring. The janitor can decide to remove some of the keys. Perhaps he thinks: I work only in room 232 today, I don´t need all the other keys. I'll leave them in my office. When he looses his keyring he lost only the control of this single room, not about the complete campus.

The inheritable privilege set is not a really a keyring. The janitor thinks about his new assistant: "Good worker, but I will not give him my key for the room with the expensive tools." The limited privilege set is the overarching order from the boss of janitor to his team leaders: "You are allowed to give your assistant the keys for normal rooms, but not for the rooms with all this blinking boxes from Oracle".

At the moment the most interesting set is the E:. This is the effective set of privileges. This is the set of privilege effectively available to process. Compared to the full list of privileges mentioned above the set is much smaller. But this matches your experience when you use a Unix system.

Lets see how it looks when we assume the root role:



oracle@solaris:~$ su -
Password: <root password>
Oracle Corporation    SunOS 5.11    11.0    November 2011
You have new mail.
root@solaris:~# ppriv $$
1779:    -bash
flags = <none>
    E: all
    I: basic
    P: all
    L: all

This role has much more privileges. The effective set is much broader. When we assume the root role we assume all privileges in the system. NOTE: This is strictly to provide backwards compatibility and is not the recommended usage going forward.

Lets add some privileges to our jdoe user, let's assume that he is a software developer that needs access to DTrace to debug some applications.

First lets try to use DTrace as jdoe:



# su - jdoe
Password: abc123
Oracle Corporation    SunOS 5.11    11.0    November 2011
jdoe@solaris:/export/home/jdoe$ ppriv $$
1790:    -ksh
flags = <none>

    E: basic
    I: basic
    P: basic
    L: all
jdoe@solaris:/export/home/jdoe$ dtrace -l
dtrace: failed to initialize dtrace: DTrace requires additional privileges

As we can see here jdoe is missing some privileges to be allowed to use DTrace. There are have 3 privileges needed for DTrace: dtrace_kernel, dtrace_proc, dtrace_user, depending on what the user needs to use DTrace for. We can add these privileges to the user in three different ways

  1. Add the privileges needed to the user. This would allow the user to use DTrace as him or herself.
  2. Create an execution profile with the dtrace command and the needed privileges, and assign the profile to the user. This would allow him or her to use a profile shell (f.e., pfbash) to execute the dtrace command.
  3. Create a role with the needed privileges, and assign the role to user. This would requirer the user to assume the role to use DTrace.

Lets see how how to add dtrace privileges directly to the user (run first command as root, then exit root shell and continue as oracle user):



# usermod -K defaultpriv=basic,dtrace_kernel,dtrace_proc,dtrace_user jdoe
oracle@solaris:~$ userattr defaultpriv
basic,dtrace_kernel,dtrace_proc,dtrace_user

Note

You will need to add basic to the set of privileges you assign to the user, without that he would not be able to do the most basic things such as create files, spawn new processes etc.

As you can see, jdoe now has the three needed privileges to use the dtrace command, lets give it a try:



oracle@solaris:~$ su - jdoe
Password: abc123
Oracle Corporation    SunOS 5.11    11.0    November 2011
jdoe@solaris:/export/home/jdoe$ ppriv $$
1814:    -ksh
flags = <none>
    E: basic,dtrace_kernel,dtrace_proc,dtrace_user
    I: basic,dtrace_kernel,dtrace_proc,dtrace_user
    P: basic,dtrace_kernel,dtrace_proc,dtrace_user
    L: all
jdoe@solaris:/export/home/jdoe$ dtrace -l | more

   ID   PROVIDER            MODULE                          FUNCTION NAME
    1     dtrace                                                     BEGIN
    2     dtrace                                                     END
    3     dtrace                                                     ERROR
  530        fbt            smbsrv                 smb_match_private entry
...
  555        fbt            smbsrv                  smb_gmttoken_xdr return
--More--

OK, so that worked, just for the fun of it lets try to create a role that does the same.

First lets remove the dtrace privileges from jdoe:



oracle@solaris:~$ usermod -K defaultpriv=basic jdoe

oracle@solaris:~$ userattr defaultpriv jdoe
basic
 

Then lets create our role (using root shell, i.e. as a root user), lets call the role "bugger", and assign it to jdoe



# roleadd -u 201 -d /export/home/bugger -P "Process Management" bugger

oracle@solaris:~$ passwd bugger
New Password: abc123
Re-enter new Password: abc123
passwd: password successfully changed for bugger

oracle@solaris:~$ rolemod -K defaultpriv=basic,dtrace_kernel,dtrace_proc,dtrace_user bugger
oracle@solaris:~$ userattr defaultpriv bugger
basic,dtrace_kernel,dtrace_proc,dtrace_user

oracle@solaris:~$ usermod -R bugger jdoe
oracle@solaris:~$ roles jdoe
bugger

OK, lets try and see if jdoe now can use DTrace



oracle@solaris:~$ su - jdoe
Password:
Oracle Corporation    SunOS 5.11    11.0    November 2011
jdoe@solaris:/export/home/jdoe$ roles
bugger
jdoe@solaris:/export/home/jdoe$ su bugger
Password:
jdoe@solaris:~$ ppriv $$
1885:    sh
flags = PRIV_PFEXEC
    E: basic,dtrace_kernel,dtrace_proc,dtrace_user
    I: basic,dtrace_kernel,dtrace_proc,dtrace_user
    P: basic,dtrace_kernel,dtrace_proc,dtrace_user
    L: all
jdoe@solaris:~$ dtrace -l | more
   ID   PROVIDER            MODULE                          FUNCTION NAME
    1     dtrace                                                     BEGIN
    2     dtrace                                                     END
    3     dtrace                                                     ERROR
  530        fbt            smbsrv                 smb_match_private entry
...
  555        fbt            smbsrv                  smb_gmttoken_xdr return
--More--

Summary

Now you should have a basic understanding about privileges and how you can assign them to users, however wouldn't it be nice if we could do the same to processes? We will look at that in exercise 3.

Exercise 3: Process Privileges and Rights

Expected duration: 10 minutes

Background

We have looked at how you can add privileges to a user, now we'll look at how privileges interact with processes, we will look at both processes that are privilege aware and processes that are non-privilege aware.

The idea of managing the privileges is not limited to users and their shells. In any given system you find dozens of programs running as daemons.

These daemons interact in several ways with the privileges. The best way is "privilege-aware programming". Let's assume you code a daemon for your system. For example: You know that your daemon will never do an exec() call. So you can safely drop this privilege. The process modifies the permitted privilege set. The process can remove a privilege but not add it. Even when someone is able to access your process, the attacker can't make an exec() call. The process doesn't even have the privilege to do such a call. And the attacker can't add the privilege again. Several processes and programs in Solaris are already privilege aware. For example the kernel-level cryptographic framework daemon. Let's look at the privileges of the daemon.

In order to observe or manage privileges, a process must itself already have those privileges. Therefore we will assume the root role for the following exercise.



oracle@solaris:~$ su - root
Password: <root password>
oracle@solaris:~# ps -ef | grep "kcfd"
  daemon   129     1   0   Apr 04 ?           0:00 /lib/crypto/kcfd
  oracle  1902  1684   0 08:19:19 pts/1       0:00 grep kcfd
oracle@solaris:~# ppriv -v 129
129:    /lib/crypto/kcfd
flags = PRIV_AWARE
    E: file_owner,file_read,file_write,net_access,proc_priocntl,sys_devices
    I: none
    P: file_owner,file_read,file_write,net_access,proc_priocntl,sys_devices
    L: none

This daemon doesn't have even the basic privileges of a regular user. It has the only the bare minimum of privileges to do it's job.

Non-privilege aware processes

But the world isn't perfect. Not every process is privilege aware. Thus you have to limit the privileges by other mechanisms. The Service Management Facility comes to help.

Let's take the Apache Webserver as an example. The apache web server is not privilege aware. We start the daemon via the Service Management Framework (SMF).



oracle@solaris:~# svcadm -v enable -s apache22
svc:/network/http:apache22 enabled.

OK, now we look at the processes of the Apache daemons.



oracle@solaris:~# ps -ef | grep "apache" | grep -v grep
webservd  1931  1928   0 08:22:59 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1934  1928   0 08:22:59 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1932  1928   0 08:22:59 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1935  1928   0 08:22:59 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1933  1928   0 08:22:59 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
    root  1928     1   1 08:22:58 ?           0:00 /usr/apache2/2.2/bin/httpd -k start

Six daemons running as webservd, and one running as root.



oracle@solaris:~# ppriv 1928
1928: /usr/apache2/2.2/bin/httpd -k start
flags = <none>
  E: all
  I: basic
  P: all
  L: all

As expected for a root process, this process has the complete set of privileges of a root user. Now lets look at one of its children:



oracle@solaris:~# ppriv 1931
1931:    /usr/apache2/2.2/bin/httpd -k start
flags = <none>
    E: basic
    I: basic
    P: basic
    L: all

Much better ... only basic privileges.

OK, There is a reason for this configuration. On Unix systems, you have two groups of ports. Privileged ones from 1-1023 and unprivileged ones from 1024 up. You can only bind to a privileged port with the privilege to do it. A normal user doesn´t have this privilege, but root has it. And thus there has to be one process running as root. Do you remember the list of privileges for the apache process running at root. The process has all privileges but needs only one of them, that isn't part of the basic privilege set.

Exercise 4: SMF, Process Privileges and Authorizations

Expected duration: 10 minutes

Introduction

We have now looked at both privilege aware and non-privilege aware processes, now lets look at how we can use SMF to let a user with a limited set of privileges manage a non-privilege aware process and give it the required privileges without using setuid to root.

In order to observe or manage privileges, a process must itself already have those privileges. Therefore we will assume the root role for the following exercise.

Background

How to get rid of the root apache process

It doesn't to be this way. With Solaris you can give any user or process the privilege to use a privileged port. You don't need the root process anymore.

Let's configure it this way. At first we have to deactivate the running apache from exercise 3:



oracle@solaris:~$ su - root
Password: <root password>
oracle@solaris:~# svcadm -v disable -s apache22
svc:/network/http:apache22 disabled.

We will not be explaining the Service Management Facility here, but you can set certain properties in SMF to control the startup of a service:



1  oracle@solaris:~# svccfg -s apache22
2  svc:/network/http:apache22> setprop start/user = astring: webservd
3  svc:/network/http:apache22> setprop start/group = astring: webservd
4  svc:/network/http:apache22> setprop start/privileges = astring:
5  basic,!proc_session,!proc_info,!file_link_any,net_privaddr
6  svc:/network/http:apache22> setprop start/limit_privileges = astring: :default
7  svc:/network/http:apache22> setprop start/use_profile = boolean: false
8  svc:/network/http:apache22> setprop start/supp_groups = astring: :default
9  svc:/network/http:apache22> setprop start/working_directory = astring: :default
10 svc:/network/http:apache22> setprop start/project = astring: :default
11 svc:/network/http:apache22> setprop start/resource_pool = astring: :default
12 svc:/network/http:apache22> end

Line 2 to 4 are the most interesting ones. Without any changes, the Apache daemon starts as root and forks away processes with the webservd user. But we want to get rid of the root user for this configuration. Thus we start the daemon directly with the webservd user, the same goes for the group id.

Now it gets interesting. Without this line (line 4), the kernel would deny Apache to bind to port 80. webservd is a regular user without the privilege to use a privileged port. The property start/privileges sets the privileges to start the service. At first, we give the service basic privileges. Then we add the privilege to use a privileged port. The service would start up now.

But wait, we can do more. A webserver shouldn't do any hardlinks. And it doesn't send signals outside it's session. And it doesn't look at processes other than those to which it can send signals. We don´t need these privileges. proc_session, proc_info and file_link_any are part of the basic privilege set. We remove them, by adding a ! in front of the privilege:



oracle@solaris:~# svcadm -v refresh apache22
Password:
Action refresh set for svc:/network/http:apache22.

OK, we have notified SMF of the configuration changes.

Until now, the apache daemon used the root privileges. Thus the ownership of files and directories were unproblematic. The daemon was able to read and write in any directory or file in the system. As we drop its privilege set by using a regular user, we have to modify the ownership of some files and move some files:



oracle@solaris:~# mkdir -p -m 755 /var/apache2/2.2/run
oracle@solaris:~# chown webservd:webservd /var/apache2/2.2/run
oracle@solaris:~# chown webservd:webservd /var/apache2/2.2/logs/access_log
oracle@solaris:~# chown webservd:webservd /var/apache2/2.2/logs/error_log

Note
While the service no longer runs as root, there is a trade-off. In the "root" configuration, logs were owned by root and could not be modified by "webservd". In the new model, the web server has fewer privileges but the logs are now owned and writable by "webservd". This is not good or bad, just a tradeoff.

We need some configuration changes, too. We have to move the LockFile and the PidFile. There wasn't one of the two configuration directives specified earlier, thus we're simply appending them to the end of the configuration file:



oracle@solaris:~# bash -c 'echo LockFile /var/apache2/2.2/logs/accept.lock >> /etc/apache2/2.2/httpd.conf'
oracle@solaris:~# bash -c 'echo PidFile /var/apache2/2.2/run/httpd.pid >> /etc/apache2/2.2/httpd.conf'

OK, everything is in place. Let´s give it a try.



oracle@solaris:~# svcadm -v enable -s apache22
svc:/network/http:apache22 enabled.

Now we check for the running httpd processes:



oracle@solaris:~# ps -ef | grep "httpd" | grep -v "grep"
webservd  2064  2057   0 08:43:24 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2061  2057   0 08:43:24 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2062  2057   0 08:43:24 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2060  2057   0 08:43:24 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2063  2057   0 08:43:24 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2057     1   1 08:43:23 ?           0:00 /usr/apache2/2.2/bin/httpd -k start

You notice the difference ? There is no httpd running as root. All processes run with the userid webservd. Mission accomplished.

Let´s check the privileges of the processes. At first the one, who ran as root before:



oracle@solaris:~# ppriv 2057
2057:    /usr/apache2/2.2/bin/httpd -k start
flags = <none>
    E: basic,!file_link_any,net_privaddr,!proc_info,!proc_session
    I: basic,!file_link_any,net_privaddr,!proc_info,!proc_session
    P: basic,!file_link_any,net_privaddr,!proc_info,!proc_session
    L: all

Only the least privileges to do the job, no root privileges. And even the other processes are more secure now. Before we changed the configuration of the webserver, it had the basic privileges of a regular user. Now we limited even this set.

But we still need to be a privileged user to start apache. Wouldn't it be nice if I could delegate management of “services” to unprivileged users. I can use authorizations to do that, and authorizations is integrated with SMF. There are two authorizations we will need to add to our user to give hi the right to manage the apach22 service. We need a authorization to manage our service as well as a authorization to change the state of our service:

  • solaris.smf.value.http/apache22 - Gives a user the right to modify the value of a property in the Apache service.
  • solaris.smf.manage.http/apache22 - Gives a user the right to change the state of a the Apache service with svcadm.

Both are needed to change the state of a service, as the state of the service is kept as a property for the service.



oracle@solaris:~# svcprop http:apache22 | grep auth
httpd/value_authorization astring solaris.smf.value.http/apache22
general/action_authorization astring solaris.smf.manage.http/apache22
general/value_authorization astring solaris.smf.value.http/apache22

First we need to add our authorizations to /etc/security/auth_attr



oracle@solaris:~# echo solaris.smf.manage.http:::Mange Apache 2.2:: >> /etc/security/auth_attr
Password: oracle
oracle@solaris:~# echo solaris.smf.value.http:::Mange Apache 2.2:: >> /etc/security/auth_attr

Note

In most SMF manifests one authorization is used for both action_authorization and value_authorization, as they are commonly used together.

Now we can exit the root role since we are finished manipulating privileges. Lets add those authorizations to our old friend jdoe.



oracle@solaris:~# exit
oracle@solaris:~$ usermod -A solaris.smf.manage.http/apache22,solaris.smf.value.http/apache22 jdoe

oracle@solaris:~$ userattr auths jdoe
solaris.smf.manage.http/apache22,solaris.smf.value.http/apache22

Lets see if jdoe can start and stop apache now



oracle@solaris:~$ su - jdoe
Password: abc123
Oracle Corporation    SunOS 5.11    11.0    November 2011
jdoe@solaris:/export/home/jdoe$ /usr/sbin/svcadm enable apache22
jdoe@solaris:/export/home/jdoe$ svcs apache22
STATE          STIME    FMRI
online          8:43:23 svc:/network/http:apache22
jdoe@solaris:/export/home/jdoe$ /usr/sbin/svcadm disable apache22
jdoe@solaris:/export/home/jdoe$ svcs apache22
STATE          STIME    FMRI
disabled        8:53:37 svc:/network/http:apache22

See that worked fine, so by using SMF we've been able to take a service such as apache, removed it's need to start as root by giving it the privileges it needed and nothing more. We also removed some privileges that apache doesn't need, but a hacker would need to take control of your system.

Add to that we added the right to manage the apache service via SMF to an unprivileged user by giving him the correct authorizations that allows a user to manage that particular service and nothing else, as you can see here.



jdoe@solaris:/export/home/jdoe$ svcs sendmail
STATE          STIME    FMRI
online          6:48:12 svc:/network/smtp:sendmail
jdoe@solaris:/export/home/jdoe$ svcadm disable sendmail
svcadm: svc:/network/smtp:sendmail: Permission denied.