Role Based Access Control and Least Privileges

Role Based Access Control and Least Privileges

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 indivisible being. So the servants had to work with the powers of root. But the servants wasn’t 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.

One day, the world of root experienced a large disaster, the negation of being. Top became bottom, left became right, the monster of erem-ef annihilated much of the world. But it got even stranger. root destroyed its own world, and by the power of root the destruction was complete.

Then there was a FLASH. The world restarted, root got a second attempt to reign his world. But this time, it would be different world.

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 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 creating some users from time to time. You’ve trained him to do useradd or passwd, but it’s a Windows admin who doesn’t know anything about being an Unix admin. What do you do when he gets to curious. He needs root privileges to create a user or change a password. You need some mechanisms to limit this operator.

But it’s get more problematic. Programs have to modify the system to work. A webserver is a nice example. It uses port 80. Ports beneath port number 1024 have a special meaning. They are privileged ports. You need special rights to modify the structures of the system to listen to the port 80. A normal user doesn’t have this rights. So the webserver 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 rights than needed, a possible attack vector for malicious users.

This led to the development to different models of handling the rights of users in the system: Privileges and Role Based Access Control.

Least privileges

There is a concept in security. It’s called least privileges. You give someone only least amount of privileges, only enough to do its tasks. 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 working in Building C. The other way round: There are some trusted people who have access to all rooms in case of emergency.

You have the same concept in computer security. Everyone should have only the least amount of privileges in the system to do its job. The concept of the superuser doesn’t match to this. It’s an all or nothing. You are an ordinary user with basic privileges or you are an user with unrestricted rights. There is nothing in between. There is no least privileges in this concept.

Role Based Access Control

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 Marge, Lenny helps from time to time).

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

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 has to do tasks in his office or in his workshop. It’s his own room, so he doesn’t need the privileges. He doesn’t need the special privileges.

Role Based Access Control is quite similar. You login to the system, and then you start 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 an User Administrator 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 users.

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 the article 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 his allowed to do this (Because he created it, because he belongs to the same group as the create 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 this privileges. Solaris 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 has only a basic set, the root has all.

But it hasn’t to be this way. Privileges and users aren’t connected with each other. You can give any user the power of the root user, and restrict the privileges of the root user. It’s just 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.

RBAC and Privileges in Solaris

Both features have their root in the Trusted Solaris development. Trusted Solaris was a version of Solaris to ensure 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’s in Solaris since version 8 (published in 2000). Privileges found their way into the generic Solaris with the first availability of Solaris 10 in February 2005.

Some basic terms

As usual the world of RBAC has some special terms. Before using it, i«m want to explain the jargon. I copy the exact definition from the RBAC manual:

  • Rights: A right is the description, 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.

Practical side of RBAC</b>

After so much theory, let’s work with roles. After installation of a Solaris system there are no rules assigned to a normal user:

$ roles
No roles

Let’s use the standard example for RBAC: reboot the system. To do this task, you need to be root.

$ /usr/sbin/reboot  
reboot: permission denied

You are not allowed to do this. Okay, until now you would give the root account to all people, who have to reboot the system. But why should someone be able to modify users, when all he or she should to is using the reboot command ?

Okay, at first you create a role. As mentioned before, it’s a special user account.

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

After creating the role, you have to assign a role password.

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

Okay, when you look into the /etc/passwd, you see a quite normal user account.

# grep reboot /etc/passwd
reboot:x:101:1::/export/home/reboot:/bin/pfsh

There is one important difference. You use a special kind of shell. This shell are called profile shells and have special mechanisms to check executions against the RBAC databases.

Okay, we’ve created the role, now we have to assign them to a user:

# usermod -R reboot jmoekamp
UX: usermod: jmoekamp is currently logged in, some changes may not take effect until next login.

The RBAC system stores the role assignments in the /etc/user_attr file

# grep "jmoekamp" /etc/user_attr
jmoekamp::::type=normal;roles=reboot

But at the moment, this role isn’t functional, as this role has no assigned role profile. It’s a role without rights an privileges.

At first, lets create a REBOOT role profile. It’s quite easy. Just a line at the end of prof_attr. This file stores all the attributes of

# echo "REBOOT:::profile to reboot:help=reboot.html" >> /etc/security/prof_attr

Okay, now assign the role profile REBOOT to the role reboot

# rolemod -P REBOOT reboot

The information of this assignment is stored in the /etc/usr. Let’s have a look into it:

# grep reboot /etc/user_attr
reboot::::type=role;profiles=REBOOT
jmoekamp::::type=normal;roles=reboot

But this isn’t enough: The profile is empty. You have to assign some administrative command to it.

# echo "REBOOT:suser:cmd:::/usr/sbin/reboot:euid=0" >> /etc/security/exec_attr

Using the new role

Okay, let’s check the role assignments.

$ roles
reboot

We have still no rights to execute the reboot command.

$ /usr/sbin/reboot
reboot: permission denied

But now we assume the reboot role.

$ su reboot
Password:

And as you see ...

$ /usr/sbin/reboot
Connection to 10.211.55.3 closed by remote host.
Connection to 10.211.55.3 closed.

Connection terminates, systems reboots.

Authorizations

But RBAC can do more for you. There is an additional concept in it: Authorizations.

Authorizations is a mechanism that needs support of the applications. This application checks if the user has the necessary authorization to use a program.

Let’s use the example of the janitor: Rights give him the access to the drilling machine. But this is a rather strange drilling machine. It checks, if the janitor has the permission to drill holes, when he trigger the button.

The concept of authorization is a fine grained system. An application can check for a vast amount of privileges. For example the application can check for the authorization to modify the configuration, to read the configuration or printing the status. A user can have all this authorizations, none or something in between.

It’s like the janitors new power screwdriver. It checks if the janitor has the permission to use it at anticlockwise rotation, the permission to use it at clockwise rotation and the permission to set different speeds of rotation.

Using authorizations for Services

Although applications need support to this models, you can even use it as an admin. SMF has build in support for authorizations. You can assign authorizations to a service. Every role or user with this authorization is allowed to work with the service (restarting,stop,start,status, ...). Let’s use Apache for this example.

A normal user has no permission to restart the service:

moekamp$ /usr/sbin/svcadm -v disable -s apache2
svcadm: svc:/network/http:apache2: Couldn't modify "general" property group (permission denied).

Wouldn’t it be nice, to have an authorisation that enables an regular user to restart it? Okay, no problem. Let’s create one:

$ su root
# echo "solaris.smf.manage.apache/server:::Apache Server management::" >> /etc/security/auth_attr

That’s all. Where is the definition of the permission that the authorization means? There is no definition. It’s the job of the application to work with.

Now assign this authorization to the user:

# usermod -A solaris.smf.manage.apache/server jmoekamp
UX: usermod: jmoekamp is currently logged in, some changes may not take effect until next login.

Okay, but at the moment no one checks for this authorization, as no application is aware of it. We have to tell SMF to use this authorization.

The authorizations for an SMF servers is part of the general properties of the service. Let’s have a look at the properties of this services.

# svcprop -p general apache2
general/enabled boolean false
general/entity_stability astring Evolving

No authorization configured. Okay ... let’s add the authorization we’ve defined before:

svccfg -s apache2 setprop general/action_authorization=astring: 'solaris.smf.manage.apache/server'

Check the properties again:

# svcadm refresh apache2   
# svcprop -p general apache2
general/enabled boolean false
general/action_authorization astring solaris.smf.manage.apache/server
general/entity_stability astring Evolving

Okay, a short test. Exit your root shell and login as the regular user you have assigned the authorization.

bash-3.2$ svcs apache2
STATE          STIME    FMRI
disabled       22:49:51 svc:/network/http:apache2

Okay, I can view the status of the service. Now I try to start it.

bash-3.2$ /usr/sbin/svcadm enable apache2
svcadm: svc:/network/http:apache2: Permission denied.

What the hell ...? No permission to start the service? Yes, enabling the service is not only a method (the start up script), it’s a value of a certain parameter. When you only have the action_authorization you can only do task, that doesn’t change the state of the service. You can restart it (no change of the service properties), but not enable or disable it (a change of the service properties). But this is not a problem. You have to login as root again and assign the solaris.smf.manage.apache/server authorization to the value authorization.

# svccfg -s apache2 setprop general/value_authorization=astring: 'solaris.smf.manage.apache/server'

With the value authorization SMF allows you to change the state of the service. Try it again.

bash-3.2$ /usr/sbin/svcadm enable apache2
bash-3.2$

Cool, isn’t it ... try this with init.d ... ;)

Predefined roles

This was a really simple example. Roles can get really complex. But you don’t have to define all role profiles at your own. For some standard tasks, there are some predefined roles. Just look at the /etc/security/prof_attr. There are 70 role profiles defined in this file. For example the right profile "Software Installation"

Software Installation:::Add application software to the system:help=RtSoftwareInstall.html; auths=solaris.admin.prodreg.read, solaris.admin.prodreg.modify, solaris.admin.prodreg.delete,solaris.admin.dcmgr.admin, solaris.admin.dcmgr.read,solaris.admin.patchmgr.*

This role profile has already some predefined command, that need special security attributes to succeed:

Software Installation:solaris:act:::Open;*;JAVA_BYTE_CODE;*;*:uid=0;gid=2
Software Installation:suser:cmd:::/usr/bin/ln:euid=0
Software Installation:suser:cmd:::/usr/bin/pkginfo:uid=0
Software Installation:suser:cmd:::/usr/bin/pkgmk:uid=0
Software Installation:suser:cmd:::/usr/bin/pkgparam:uid=0
Software Installation:suser:cmd:::/usr/bin/pkgproto:uid=0
Software Installation:suser:cmd:::/usr/bin/pkgtrans:uid=0
Software Installation:suser:cmd:::/usr/bin/prodreg:uid=0
Software Installation:suser:cmd:::/usr/ccs/bin/make:euid=0
Software Installation:suser:cmd:::/usr/sbin/install:euid=0
Software Installation:suser:cmd:::/usr/sbin/patchadd:uid=0
Software Installation:suser:cmd:::/usr/sbin/patchrm:uid=0
Software Installation:suser:cmd:::/usr/sbin/pkgadd:uid=0;gid=bin
Software Installation:suser:cmd:::/usr/sbin/pkgask:uid=0
Software Installation:suser:cmd:::/usr/sbin/pkgchk:uid=0
Software Installation:suser:cmd:::/usr/sbin/pkgrm:uid=0;gid=bin

This is all you need to install software on your system. You can use this predefined role profiles at your will. You don’t have to do define all this stuff on your own.

Privileges

We’ve talked a lot about RBAC, roles, role profiles. But what are Privileges? Privileges are rights to do an operation in the kernel. This rights are enforced by the kernel. Whenever you do something within the kernel the access is controlled by the privileges.

At the moment, the rights to do something with the kernel are separated into 70 classes:

contract_event contract_observer cpc_cpu dtrace_kernel dtrace_proc dtrace_user file_chown file_chown_self file_dac_execute file_dac_read file_dac_search file_dac_write file_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_bindmlp net_icmpaccess net_mac_aware 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_ip_config sys_ipc_config sys_linkdir sys_mount sys_net_config sys_nfs sys_res_config sys_resource sys_smb sys_suser_compat sys_time sys_trans_label 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

Every UNIX-System does this task hidden behind this privileges. There are many different privileges in the kernel. This privileges are not Solaris specific. It’s the way to control the access to this privileges.

Conventional Unix

On conventional unix systems you have a root user, he has 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 admin the system. You can only traceroute or ping a system, because both tools are setuid tools

$ ls -l /usr/sbin/traceroute
-r-sr-xr-x   1 root     bin        42324 Nov 21 00:09 /usr/sbin/traceroute
$ ls -l /usr/sbin/ping
-r-sr-xr-x   1 root     bin        51396 Nov 18 19:31 /usr/sbin/ping

setuid is nothing else than a violation of the security policy. You need a special privilege to ping: The privilege to use access ICMP. On conventional system this right is reserved to 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 rights of the user. Not only to access ICMP, the program is capable to do everything on the system, 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 users privileges. Setuid root and you are toast.

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 <code>ppriv</code>.$$ is a shortcut for the actual process id (in this case the process id of the shell):

bash-3.2$ ppriv -v $$
646:    bash
flags = <none>
        E: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        I: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        P: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        L: contract_event, (..) ,win_upgrade_sl

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 <a href="http://docs.sun.com/app/docs/doc/816-4557/prbactm-1?a=view">Security Services</a> manual 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

  • P: permitted privileges set

  • L: limit privileges set

  • I: inheritable 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 leave them in my office. When he looses his keyring he lost only the control about this single room, not about the complete campus.

The inheritable privilege is not a really a keyring. The janitor thinks about his new assistant: "Good worker, but I won’t 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 Sun".

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.

Some practical insights to the system

You logged in as a normal user, and you have only a few privileges. It’s called the basic set.

bash-3.2$ ppriv $$
815:    bash
flags = <none>
        E: basic
        I: basic
        P: basic
        L: all

Okay, this example looks different than the one shown before. Nevertheless is has the same meaning. With the switch <code>-v</code> you can expand the aliases.

bash-3.2$ ppriv -v $$
815:    bash
flags = <none>
        E: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        I: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        P: file_link_any,proc_exec,proc_fork,proc_info,proc_session
        L: contract_event, (..) ,win_upgrade_sl

Looks a little bit more familiar? Okay, now let’s login as root.

$su root
Password:
# ppriv $$
819:    sh
flags = <none>
        E: all
        I: basic
        P: all
        L: all

This user has much more privileges. The effective set is much broader. The user has all privileges in the system.

How to give an user additional privileges

Now let’s assume, you have an user, that wants to use dtrace. You need three privileges to use Dtrace: dtrace_kernel,dtrace_proc,dtrace_user. root has this privileges. A normal user not. Giving root to a developer? God beware! This is a prelude to disaster. But no problem. Assign the matching privileges to the user, and the user is enabled to use dtrace.

$ su root
Password:
# usermod -K defaultpriv=basic,dtrace\_kernel,dtrace\_proc,dtrace\_user jmoekamp
UX: usermod: jmoekamp is currently logged in, some changes may not take effect until next login.

Exit to the login prompt and login as the user you’ve assigned the privilieges.

$ ppriv $$
829:    -sh
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

Simple ...

RBAC and privileges combined

Well, but we can do better than that. We’ve learned there is a thing like RBAC. There is no reason that inhibits the assignment of privileges to a role. At first we create a role bughunt, for simplicity we use the Process Management role profile. After this we set the role password.

# roleadd -m -d /export/home/bughunting -P "Process Management" bughunt
# passwd bughunt
New Password: 
Re-enter new Password:

Now we assign the privileges ...

# rolemod -K defaultpriv=basic,dtrace_kernel,dtrace_proc,dtrace_user bughunt

... and the user to the role.

# usermod -R bughunt jmoekamp
UX: usermod: jmoekamp is currently logged in, some changes may not take effect until next login.

As you might have espected, the user itself doesn’t have the privileges to use dtrace.

$ ppriv $$
883:    -sh
flags = <none>
        E: basic
        I: basic
        P: basic
        L: all

But now assume the role <code>bughunt</code>

$ su bughunt
Password:
$ ppriv $$
893:    pfsh
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

And DTrace is at your service.

Privilege-aware programming

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

These daemons interact in several ways with the privileges. The best way is "Privilege-aware programming". Okay. Let’s assume, you code a daemon for your system. For example: You know, that you never will 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 your code, 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.

# ps -ef | grep "kcfd" 
  daemon   125     1   0 14:24:19 ?           0:00 /usr/lib/crypto/kcfd
    root   734   728   0 15:54:08 pts/1       0:00 grep kcfd
# ppriv -v 125
125:    /usr/lib/crypto/kcfd
flags = PRIV_AWARE
        E: file_owner,proc_priocntl,sys_devices
        I: none
        P: file_owner,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 its 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 framework comes to help. The following example is copied from Glen Brunettes Blueprint <a href="http://www.sun.com/blueprints/0505/819-2680.pdf">Limiting Service Privileges in the Solaris 10 Operating System </a>

Let’s take the Apache Webserver as an example. The apache isn’t privilege aware. We start the daemon via the Service Management Framework.

# svcadm -v enable -s apache2
svc:/network/http:apache2 enabled.

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

# ps -ef | grep "apache"
webservd  1123  1122   0 19:11:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1125  1122   0 19:11:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
    root  1122     1   1 19:11:50 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1128  1122   0 19:11:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1127  1122   0 19:11:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1126  1122   0 19:11:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  1124  1122   0 19:11:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start

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

# ppriv  1122
1122:   /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. Okay, now one of its children.

# ppriv 1124
1124:   /usr/apache2/2.2/bin/httpd -k start
flags = <none>
        E: basic
        I: basic
        P: basic
        L: all

Much better ... only basic privileges.

Okay, 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.

How to get rid of the root apache

Well, but it hasn’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.

Now, let’s configure it this way. At first we have to deactivate the running apache.

svcadm -v disable -s apache2
svc:/network/http:apache2 disabled.

I won’t explain the Service Management Framework here, but you can set certain properties in SMF to control the startup of a service.

# svccfg -s apache2
svc:/network/http:apache2> setprop start/user = astring: webservd
svc:/network/http:apache2> setprop start/group = astring: webservd
svc:/network/http:apache2> setprop start/privileges = astring: basic,!proc_session,!proc_info,!file_link_any,net_privaddr
svc:/network/http:apache2> setprop start/limit_privileges = astring: :default
svc:/network/http:apache2> setprop start/use_profile = boolean: false
svc:/network/http:apache2> setprop start/supp_groups = astring: :default
svc:/network/http:apache2> setprop start/working_directory = astring: :default
svc:/network/http:apache2> setprop start/project = astring: :default
svc:/network/http:apache2> setprop start/resource_pool = astring: :default
svc:/network/http:apache2> 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. Same for the group id.

Now it gets interesting. Without this line, 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 its session. And it doesn’t look at processes other than those to which it can send signals. We don’t need this privileges. proc_session, proc_info and file_link_any are part of the basic privilege set. We remove them, by adding a <code>!</code> in front of the privilege.

Okay, we have notify the SMF of the configuration changes:

# svcadm -v refresh apache2
Action refresh set for svc:/network/http:apache2.

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 of file in the system. As we drop this privilege by using a regular user, we have to modify the ownership of some files and move some files.

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

We need some configuration changes, too. We have to move the LockFile and the PidFile. There wasn’t one of the two configuration directives in my config file, thus I’ve simply appended them to the end of the file.

# echo "LockFile /var/apache2/2.2/logs/accept.lock" >> /etc/apache2/2.2/httpd.conf 
# echo "PidFile /var/apache2/2.2/run/httpd.pid" >> /etc/apache2/2.2/httpd.conf

Okay, everything is in place. Let’s give it a try.

# svcadm -v enable -s apache2
svc:/network/http:apache2 enabled.

Now we check for the running httpd processes:

# ps -ef | grep "apache2" | grep -v "grep"
webservd  2239  2235   0 19:29:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2241  2235   0 19:29:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2235     1   1 19:29:53 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2238  2235   0 19:29:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2240  2235   0 19:29:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2242  2235   0 19:29:54 ?           0:00 /usr/apache2/2.2/bin/httpd -k start
webservd  2236  2235   0 19:29:54 ?           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.

# ppriv 2235
2235:	/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:

# ppriv 2238
2238:	/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

Before we changed the configuration of the webserver, it has the basic privileges of a regular user. Now we limited even this set.

The story of root - reprise

And then there was root again. And root was almighty. And this time, it wasn’t a bad thing. root was able to distribute the powers between the servants. But no one was as powerful as root. They had only the powers to do their job. But not more. One servant had still the problem with to many prayers, but now this servant wasn’t able to destroy the world.

Even the mere mortals learned to use the power of root. Only a small group of trusted priests had the knowledge of magic chant to speak through root. All other had only the knowledge of minor chants to pray for their special wishes.

root got really cautious to give away his powers. From this day forth root casted only the absolutely needed powers to his servants and believers. And the world of root was a more secure place. It was still possible to destroy the world, but now it was much harder as there were now several guardians to protect the power of root.

The End

Documentation

System Administration Guide: Security Services - Roles, Rights Profiles, and Privileges

RBAC

SMF and RBAC authorizations

Sun Whitepaper: RBAC in the Solaris Operating Environment

Custom Roles Using RBAC in the Solaris OS

Privileges

Limiting Service Privileges in the Solaris 10 Operating System

Privilege Debugging in the Solaris 10 Operating System